diff --git a/.gitattributes b/.gitattributes index bcc7d57b904..efb059f169a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,4 @@ contrib/* linguist-vendored *.h linguist-language=C++ +# to avoid frequent conflicts +tests/queries/0_stateless/arcadia_skip_list.txt text merge=union diff --git a/.github/codecov.yml b/.github/codecov.yml index 9b75efc791d..f185c5e2dcc 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -1,5 +1,5 @@ codecov: - max_report_age: off + max_report_age: "off" strict_yaml_branch: "master" ignore: @@ -14,4 +14,4 @@ ignore: comment: false github_checks: - annotations: false \ No newline at end of file + annotations: false diff --git a/.github/workflows/anchore-analysis.yml b/.github/workflows/anchore-analysis.yml index 50eaf45e2ef..1005c8f6c38 100644 --- a/.github/workflows/anchore-analysis.yml +++ b/.github/workflows/anchore-analysis.yml @@ -8,9 +8,9 @@ name: Docker Container Scan (clickhouse-server) -on: +"on": pull_request: - paths: + paths: - docker/server/Dockerfile - .github/workflows/anchore-analysis.yml schedule: @@ -20,20 +20,20 @@ jobs: Anchore-Build-Scan: runs-on: ubuntu-latest steps: - - name: Checkout the code - uses: actions/checkout@v2 - - name: Build the Docker image - run: | - cd docker/server - perl -pi -e 's|=\$version||g' Dockerfile - docker build . --file Dockerfile --tag localbuild/testimage:latest - - name: Run the local Anchore scan action itself with GitHub Advanced Security code scanning integration enabled - uses: anchore/scan-action@v2 - id: scan - with: - image: "localbuild/testimage:latest" - acs-report-enable: true - - name: Upload Anchore Scan Report - uses: github/codeql-action/upload-sarif@v1 - with: - sarif_file: ${{ steps.scan.outputs.sarif }} + - name: Checkout the code + uses: actions/checkout@v2 + - name: Build the Docker image + run: | + cd docker/server + perl -pi -e 's|=\$version||g' Dockerfile + docker build . --file Dockerfile --tag localbuild/testimage:latest + - name: Run the local Anchore scan action itself with GitHub Advanced Security code scanning integration enabled + uses: anchore/scan-action@v2 + id: scan + with: + image: "localbuild/testimage:latest" + acs-report-enable: true + - name: Upload Anchore Scan Report + uses: github/codeql-action/upload-sarif@v1 + with: + sarif_file: ${{ steps.scan.outputs.sarif }} diff --git a/.gitignore b/.gitignore index 1e9765dca9e..d33dbf0600d 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,9 @@ website/package-lock.json /prof *.iml + +# data store +/programs/server/data +/programs/server/metadata +/programs/server/store + diff --git a/.gitmodules b/.gitmodules index 519ba082304..7a2c5600e65 100644 --- a/.gitmodules +++ b/.gitmodules @@ -220,4 +220,4 @@ url = https://github.com/ClickHouse-Extras/boringssl.git [submodule "contrib/NuRaft"] path = contrib/NuRaft - url = https://github.com/eBay/NuRaft.git + url = https://github.com/ClickHouse-Extras/NuRaft.git diff --git a/.potato.yml b/.potato.yml index 113bdacbdde..7cb87c58bd1 100644 --- a/.potato.yml +++ b/.potato.yml @@ -14,14 +14,14 @@ handlers: # The trigger for creating the Yandex.Tracker issue. When the specified event occurs, it transfers PR data to Yandex.Tracker. github:pullRequest:labeled: data: - # The Yandex.Tracker queue to create the issue in. Each issue in Tracker belongs to one of the project queues. - queue: CLICKHOUSEDOCS - # The issue title. - summary: '[Potato] Pull Request #{{pullRequest.number}}' - # The issue description. - description: > + # The Yandex.Tracker queue to create the issue in. Each issue in Tracker belongs to one of the project queues. + queue: CLICKHOUSEDOCS + # The issue title. + summary: '[Potato] Pull Request #{{pullRequest.number}}' + # The issue description. + description: > {{pullRequest.description}} Ссылка на Pull Request: {{pullRequest.webUrl}} - # The condition for creating the Yandex.Tracker issue. - condition: eventPayload.labels.filter(label => ['pr-feature'].includes(label.name)).length + # The condition for creating the Yandex.Tracker issue. + condition: eventPayload.labels.filter(label => ['pr-feature'].includes(label.name)).length diff --git a/.yamllint b/.yamllint new file mode 100644 index 00000000000..fe161e71849 --- /dev/null +++ b/.yamllint @@ -0,0 +1,15 @@ +# vi: ft=yaml +extends: default + +rules: + indentation: + level: warning + indent-sequences: consistent + line-length: + # there are some bash -c "", so this is OK + max: 300 + level: warning + comments: + min-spaces-from-content: 1 + document-start: + present: false diff --git a/CHANGELOG.md b/CHANGELOG.md index e2c777b3bcf..928991dc937 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,159 @@ +## ClickHouse release 21.3 + +### ClickHouse release v21.3, 2021-03-12 + +#### Backward Incompatible Change + +* Now it's not allowed to create MergeTree tables in old syntax with table TTL because it's just ignored. Attach of old tables is still possible. [#20282](https://github.com/ClickHouse/ClickHouse/pull/20282) ([alesapin](https://github.com/alesapin)). +* Now all case-insensitive function names will be rewritten to their canonical representations. This is needed for projection query routing (the upcoming feature). [#20174](https://github.com/ClickHouse/ClickHouse/pull/20174) ([Amos Bird](https://github.com/amosbird)). +* Fix creation of `TTL` in cases, when its expression is a function and it is the same as `ORDER BY` key. Now it's allowed to set custom aggregation to primary key columns in `TTL` with `GROUP BY`. Backward incompatible: For primary key columns, which are not in `GROUP BY` and aren't set explicitly now is applied function `any` instead of `max`, when TTL is expired. Also if you use TTL with `WHERE` or `GROUP BY` you can see exceptions at merges, while making rolling update. [#15450](https://github.com/ClickHouse/ClickHouse/pull/15450) ([Anton Popov](https://github.com/CurtizJ)). + +#### New Feature + +* Add file engine settings: `engine_file_empty_if_not_exists` and `engine_file_truncate_on_insert`. [#20620](https://github.com/ClickHouse/ClickHouse/pull/20620) ([M0r64n](https://github.com/M0r64n)). +* Add aggregate function `deltaSum` for summing the differences between consecutive rows. [#20057](https://github.com/ClickHouse/ClickHouse/pull/20057) ([Russ Frank](https://github.com/rf)). +* New `event_time_microseconds` column in `system.part_log` table. [#20027](https://github.com/ClickHouse/ClickHouse/pull/20027) ([Bharat Nallan](https://github.com/bharatnc)). +* Added `timezoneOffset(datetime)` function which will give the offset from UTC in seconds. This close [#issue:19850](https://github.com/ClickHouse/ClickHouse/issues/19850). [#19962](https://github.com/ClickHouse/ClickHouse/pull/19962) ([keenwolf](https://github.com/keen-wolf)). +* Add setting `insert_shard_id` to support insert data into specific shard from distributed table. [#19961](https://github.com/ClickHouse/ClickHouse/pull/19961) ([flynn](https://github.com/ucasFL)). +* Function `reinterpretAs` updated to support big integers. Fixes [#19691](https://github.com/ClickHouse/ClickHouse/issues/19691). [#19858](https://github.com/ClickHouse/ClickHouse/pull/19858) ([Maksim Kita](https://github.com/kitaisreal)). +* Added Server Side Encryption Customer Keys (the `x-amz-server-side-encryption-customer-(key/md5)` header) support in S3 client. See [the link](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html). Closes [#19428](https://github.com/ClickHouse/ClickHouse/issues/19428). [#19748](https://github.com/ClickHouse/ClickHouse/pull/19748) ([Vladimir Chebotarev](https://github.com/excitoon)). +* Added `implicit_key` option for `executable` dictionary source. It allows to avoid printing key for every record if records comes in the same order as the input keys. Implements [#14527](https://github.com/ClickHouse/ClickHouse/issues/14527). [#19677](https://github.com/ClickHouse/ClickHouse/pull/19677) ([Maksim Kita](https://github.com/kitaisreal)). +* Add quota type `query_selects` and `query_inserts`. [#19603](https://github.com/ClickHouse/ClickHouse/pull/19603) ([JackyWoo](https://github.com/JackyWoo)). +* Add function `extractTextFromHTML` [#19600](https://github.com/ClickHouse/ClickHouse/pull/19600) ([zlx19950903](https://github.com/zlx19950903)), ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Tables with `MergeTree*` engine now have two new table-level settings for query concurrency control. Setting `max_concurrent_queries` limits the number of concurrently executed queries which are related to this table. Setting `min_marks_to_honor_max_concurrent_queries` tells to apply previous setting only if query reads at least this number of marks. [#19544](https://github.com/ClickHouse/ClickHouse/pull/19544) ([Amos Bird](https://github.com/amosbird)). +* Added `file` function to read file from user_files directory as a String. This is different from the `file` table function. This implements [#issue:18851](https://github.com/ClickHouse/ClickHouse/issues/18851). [#19204](https://github.com/ClickHouse/ClickHouse/pull/19204) ([keenwolf](https://github.com/keen-wolf)). + +#### Experimental feature + +* Add experimental `Replicated` database engine. It replicates DDL queries across multiple hosts. [#16193](https://github.com/ClickHouse/ClickHouse/pull/16193) ([tavplubix](https://github.com/tavplubix)). +* Introduce experimental support for window functions, enabled with `allow_experimental_functions = 1`. This is a preliminary, alpha-quality implementation that is not suitable for production use and will change in backward-incompatible ways in future releases. Please see [the documentation](https://github.com/ClickHouse/ClickHouse/blob/master/docs/en/sql-reference/window-functions/index.md#experimental-window-functions) for the list of supported features. [#20337](https://github.com/ClickHouse/ClickHouse/pull/20337) ([Alexander Kuzmenkov](https://github.com/akuzm)). +* Add the ability to backup/restore metadata files for DiskS3. [#18377](https://github.com/ClickHouse/ClickHouse/pull/18377) ([Pavel Kovalenko](https://github.com/Jokser)). + +#### Performance Improvement + +* Hedged requests for remote queries. When setting `use_hedged_requests` enabled (off by default), allow to establish many connections with different replicas for query. New connection is enabled in case existent connection(s) with replica(s) were not established within `hedged_connection_timeout` or no data was received within `receive_data_timeout`. Query uses the first connection which send non empty progress packet (or data packet, if `allow_changing_replica_until_first_data_packet`); other connections are cancelled. Queries with `max_parallel_replicas > 1` are supported. [#19291](https://github.com/ClickHouse/ClickHouse/pull/19291) ([Kruglov Pavel](https://github.com/Avogar)). This allows to significantly reduce tail latencies on very large clusters. +* Added support for `PREWHERE` (and enable the corresponding optimization) when tables have row-level security expressions specified. [#19576](https://github.com/ClickHouse/ClickHouse/pull/19576) ([Denis Glazachev](https://github.com/traceon)). +* The setting `distributed_aggregation_memory_efficient` is enabled by default. It will lower memory usage and improve performance of distributed queries. [#20599](https://github.com/ClickHouse/ClickHouse/pull/20599) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Improve performance of GROUP BY multiple fixed size keys. [#20472](https://github.com/ClickHouse/ClickHouse/pull/20472) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Improve performance of aggregate functions by more strict aliasing. [#19946](https://github.com/ClickHouse/ClickHouse/pull/19946) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Speed up reading from `Memory` tables in extreme cases (when reading speed is in order of 50 GB/sec) by simplification of pipeline and (consequently) less lock contention in pipeline scheduling. [#20468](https://github.com/ClickHouse/ClickHouse/pull/20468) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Partially reimplement HTTP server to make it making less copies of incoming and outgoing data. It gives up to 1.5 performance improvement on inserting long records over HTTP. [#19516](https://github.com/ClickHouse/ClickHouse/pull/19516) ([Ivan](https://github.com/abyss7)). +* Add `compress` setting for `Memory` tables. If it's enabled the table will use less RAM. On some machines and datasets it can also work faster on SELECT, but it is not always the case. This closes [#20093](https://github.com/ClickHouse/ClickHouse/issues/20093). Note: there are reasons why Memory tables can work slower than MergeTree: (1) lack of compression (2) static size of blocks (3) lack of indices and prewhere... [#20168](https://github.com/ClickHouse/ClickHouse/pull/20168) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Slightly better code in aggregation. [#20978](https://github.com/ClickHouse/ClickHouse/pull/20978) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Add back `intDiv`/`modulo` specializations for better performance. This fixes [#21293](https://github.com/ClickHouse/ClickHouse/issues/21293) . The regression was introduced in https://github.com/ClickHouse/ClickHouse/pull/18145 . [#21307](https://github.com/ClickHouse/ClickHouse/pull/21307) ([Amos Bird](https://github.com/amosbird)). +* Do not squash blocks too much on INSERT SELECT if inserting into Memory table. In previous versions inefficient data representation was created in Memory table after INSERT SELECT. This closes [#13052](https://github.com/ClickHouse/ClickHouse/issues/13052). [#20169](https://github.com/ClickHouse/ClickHouse/pull/20169) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Fix at least one case when DataType parser may have exponential complexity (found by fuzzer). This closes [#20096](https://github.com/ClickHouse/ClickHouse/issues/20096). [#20132](https://github.com/ClickHouse/ClickHouse/pull/20132) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Parallelize SELECT with FINAL for single part with level > 0 when `do_not_merge_across_partitions_select_final` setting is 1. [#19375](https://github.com/ClickHouse/ClickHouse/pull/19375) ([Kruglov Pavel](https://github.com/Avogar)). +* Fill only requested columns when querying `system.parts` and `system.parts_columns`. Closes [#19570](https://github.com/ClickHouse/ClickHouse/issues/19570). [#21035](https://github.com/ClickHouse/ClickHouse/pull/21035) ([Anmol Arora](https://github.com/anmolarora)). +* Perform algebraic optimizations of arithmetic expressions inside `avg` aggregate function. close [#20092](https://github.com/ClickHouse/ClickHouse/issues/20092). [#20183](https://github.com/ClickHouse/ClickHouse/pull/20183) ([flynn](https://github.com/ucasFL)). + +#### Improvement + +* Case-insensitive compression methods for table functions. Also fixed LZMA compression method which was checked in upper case. [#21416](https://github.com/ClickHouse/ClickHouse/pull/21416) ([Vladimir Chebotarev](https://github.com/excitoon)). +* Add two settings to delay or throw error during insertion when there are too many inactive parts. This is useful when server fails to clean up parts quickly enough. [#20178](https://github.com/ClickHouse/ClickHouse/pull/20178) ([Amos Bird](https://github.com/amosbird)). +* Provide better compatibility for mysql clients. 1. mysql jdbc 2. mycli. [#21367](https://github.com/ClickHouse/ClickHouse/pull/21367) ([Amos Bird](https://github.com/amosbird)). +* Forbid to drop a column if it's referenced by materialized view. Closes [#21164](https://github.com/ClickHouse/ClickHouse/issues/21164). [#21303](https://github.com/ClickHouse/ClickHouse/pull/21303) ([flynn](https://github.com/ucasFL)). +* MySQL dictionary source will now retry unexpected connection failures (Lost connection to MySQL server during query) which sometimes happen on SSL/TLS connections. [#21237](https://github.com/ClickHouse/ClickHouse/pull/21237) ([Alexander Kazakov](https://github.com/Akazz)). +* Usability improvement: more consistent `DateTime64` parsing: recognize the case when unix timestamp with subsecond resolution is specified as scaled integer (like `1111111111222` instead of `1111111111.222`). This closes [#13194](https://github.com/ClickHouse/ClickHouse/issues/13194). [#21053](https://github.com/ClickHouse/ClickHouse/pull/21053) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Do only merging of sorted blocks on initiator with distributed_group_by_no_merge. [#20882](https://github.com/ClickHouse/ClickHouse/pull/20882) ([Azat Khuzhin](https://github.com/azat)). +* When loading config for mysql source ClickHouse will now randomize the list of replicas with the same priority to ensure the round-robin logics of picking mysql endpoint. This closes [#20629](https://github.com/ClickHouse/ClickHouse/issues/20629). [#20632](https://github.com/ClickHouse/ClickHouse/pull/20632) ([Alexander Kazakov](https://github.com/Akazz)). +* Function 'reinterpretAs(x, Type)' renamed into 'reinterpret(x, Type)'. [#20611](https://github.com/ClickHouse/ClickHouse/pull/20611) ([Maksim Kita](https://github.com/kitaisreal)). +* Support vhost for RabbitMQ engine [#20576](https://github.com/ClickHouse/ClickHouse/issues/20576). [#20596](https://github.com/ClickHouse/ClickHouse/pull/20596) ([Kseniia Sumarokova](https://github.com/kssenii)). +* Improved serialization for data types combined of Arrays and Tuples. Improved matching enum data types to protobuf enum type. Fixed serialization of the `Map` data type. Omitted values are now set by default. [#20506](https://github.com/ClickHouse/ClickHouse/pull/20506) ([Vitaly Baranov](https://github.com/vitlibar)). +* Fixed race between execution of distributed DDL tasks and cleanup of DDL queue. Now DDL task cannot be removed from ZooKeeper if there are active workers. Fixes [#20016](https://github.com/ClickHouse/ClickHouse/issues/20016). [#20448](https://github.com/ClickHouse/ClickHouse/pull/20448) ([tavplubix](https://github.com/tavplubix)). +* Make FQDN and other DNS related functions work correctly in alpine images. [#20336](https://github.com/ClickHouse/ClickHouse/pull/20336) ([filimonov](https://github.com/filimonov)). +* Do not allow early constant folding of explicitly forbidden functions. [#20303](https://github.com/ClickHouse/ClickHouse/pull/20303) ([Azat Khuzhin](https://github.com/azat)). +* Implicit conversion from integer to Decimal type might succeeded if integer value doe not fit into Decimal type. Now it throws `ARGUMENT_OUT_OF_BOUND`. [#20232](https://github.com/ClickHouse/ClickHouse/pull/20232) ([tavplubix](https://github.com/tavplubix)). +* Lockless `SYSTEM FLUSH DISTRIBUTED`. [#20215](https://github.com/ClickHouse/ClickHouse/pull/20215) ([Azat Khuzhin](https://github.com/azat)). +* Normalize count(constant), sum(1) to count(). This is needed for projection query routing. [#20175](https://github.com/ClickHouse/ClickHouse/pull/20175) ([Amos Bird](https://github.com/amosbird)). +* Support all native integer types in bitmap functions. [#20171](https://github.com/ClickHouse/ClickHouse/pull/20171) ([Amos Bird](https://github.com/amosbird)). +* Updated `CacheDictionary`, `ComplexCacheDictionary`, `SSDCacheDictionary`, `SSDComplexKeyDictionary` to use LRUHashMap as underlying index. [#20164](https://github.com/ClickHouse/ClickHouse/pull/20164) ([Maksim Kita](https://github.com/kitaisreal)). +* The setting `access_management` is now configurable on startup by providing `CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT`, defaults to disabled (`0`) which was the prior value. [#20139](https://github.com/ClickHouse/ClickHouse/pull/20139) ([Marquitos](https://github.com/sonirico)). +* Fix toDateTime64(toDate()/toDateTime()) for DateTime64 - Implement DateTime64 clamping to match DateTime behaviour. [#20131](https://github.com/ClickHouse/ClickHouse/pull/20131) ([Azat Khuzhin](https://github.com/azat)). +* Quota improvements: SHOW TABLES is now considered as one query in the quota calculations, not two queries. SYSTEM queries now consume quota. Fix calculation of interval's end in quota consumption. [#20106](https://github.com/ClickHouse/ClickHouse/pull/20106) ([Vitaly Baranov](https://github.com/vitlibar)). +* Supports `path IN (set)` expressions for `system.zookeeper` table. [#20105](https://github.com/ClickHouse/ClickHouse/pull/20105) ([小路](https://github.com/nicelulu)). +* Show full details of `MaterializeMySQL` tables in `system.tables`. [#20051](https://github.com/ClickHouse/ClickHouse/pull/20051) ([Stig Bakken](https://github.com/stigsb)). +* Fix data race in executable dictionary that was possible only on misuse (when the script returns data ignoring its input). [#20045](https://github.com/ClickHouse/ClickHouse/pull/20045) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* The value of MYSQL_OPT_RECONNECT option can now be controlled by "opt_reconnect" parameter in the config section of mysql replica. [#19998](https://github.com/ClickHouse/ClickHouse/pull/19998) ([Alexander Kazakov](https://github.com/Akazz)). +* If user calls `JSONExtract` function with `Float32` type requested, allow inaccurate conversion to the result type. For example the number `0.1` in JSON is double precision and is not representable in Float32, but the user still wants to get it. Previous versions return 0 for non-Nullable type and NULL for Nullable type to indicate that conversion is imprecise. The logic was 100% correct but it was surprising to users and leading to questions. This closes [#13962](https://github.com/ClickHouse/ClickHouse/issues/13962). [#19960](https://github.com/ClickHouse/ClickHouse/pull/19960) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Add conversion of block structure for INSERT into Distributed tables if it does not match. [#19947](https://github.com/ClickHouse/ClickHouse/pull/19947) ([Azat Khuzhin](https://github.com/azat)). +* Improvement for the `system.distributed_ddl_queue` table. Initialize MaxDDLEntryID to the last value after restarting. Before this PR, MaxDDLEntryID will remain zero until a new DDLTask is processed. [#19924](https://github.com/ClickHouse/ClickHouse/pull/19924) ([Amos Bird](https://github.com/amosbird)). +* Show `MaterializeMySQL` tables in `system.parts`. [#19770](https://github.com/ClickHouse/ClickHouse/pull/19770) ([Stig Bakken](https://github.com/stigsb)). +* Add separate config directive for `Buffer` profile. [#19721](https://github.com/ClickHouse/ClickHouse/pull/19721) ([Azat Khuzhin](https://github.com/azat)). +* Move conditions that are not related to JOIN to WHERE clause. [#18720](https://github.com/ClickHouse/ClickHouse/issues/18720). [#19685](https://github.com/ClickHouse/ClickHouse/pull/19685) ([hexiaoting](https://github.com/hexiaoting)). +* Add ability to throttle INSERT into Distributed based on amount of pending bytes for async send (`bytes_to_delay_insert`/`max_delay_to_insert` and `bytes_to_throw_insert` settings for `Distributed` engine has been added). [#19673](https://github.com/ClickHouse/ClickHouse/pull/19673) ([Azat Khuzhin](https://github.com/azat)). +* Fix some rare cases when write errors can be ignored in destructors. [#19451](https://github.com/ClickHouse/ClickHouse/pull/19451) ([Azat Khuzhin](https://github.com/azat)). +* Print inline frames in stack traces for fatal errors. [#19317](https://github.com/ClickHouse/ClickHouse/pull/19317) ([Ivan](https://github.com/abyss7)). + +#### Bug Fix + +* Fix redundant reconnects to ZooKeeper and the possibility of two active sessions for a single clickhouse server. Both problems introduced in #14678. [#21264](https://github.com/ClickHouse/ClickHouse/pull/21264) ([alesapin](https://github.com/alesapin)). +* Fix error `Bad cast from type ... to DB::ColumnLowCardinality` while inserting into table with `LowCardinality` column from `Values` format. Fixes #21140 [#21357](https://github.com/ClickHouse/ClickHouse/pull/21357) ([Nikolai Kochetov](https://github.com/KochetovNicolai)). +* Fix a deadlock in `ALTER DELETE` mutations for non replicated MergeTree table engines when the predicate contains the table itself. Fixes [#20558](https://github.com/ClickHouse/ClickHouse/issues/20558). [#21477](https://github.com/ClickHouse/ClickHouse/pull/21477) ([alesapin](https://github.com/alesapin)). +* Fix SIGSEGV for distributed queries on failures. [#21434](https://github.com/ClickHouse/ClickHouse/pull/21434) ([Azat Khuzhin](https://github.com/azat)). +* Now `ALTER MODIFY COLUMN` queries will correctly affect changes in partition key, skip indices, TTLs, and so on. Fixes [#13675](https://github.com/ClickHouse/ClickHouse/issues/13675). [#21334](https://github.com/ClickHouse/ClickHouse/pull/21334) ([alesapin](https://github.com/alesapin)). +* Fix bug with `join_use_nulls` and joining `TOTALS` from subqueries. This closes [#19362](https://github.com/ClickHouse/ClickHouse/issues/19362) and [#21137](https://github.com/ClickHouse/ClickHouse/issues/21137). [#21248](https://github.com/ClickHouse/ClickHouse/pull/21248) ([vdimir](https://github.com/vdimir)). +* Fix crash in `EXPLAIN` for query with `UNION`. Fixes [#20876](https://github.com/ClickHouse/ClickHouse/issues/20876), [#21170](https://github.com/ClickHouse/ClickHouse/issues/21170). [#21246](https://github.com/ClickHouse/ClickHouse/pull/21246) ([flynn](https://github.com/ucasFL)). +* Now mutations allowed only for table engines that support them (MergeTree family, Memory, MaterializedView). Other engines will report a more clear error. Fixes [#21168](https://github.com/ClickHouse/ClickHouse/issues/21168). [#21183](https://github.com/ClickHouse/ClickHouse/pull/21183) ([alesapin](https://github.com/alesapin)). +* Fixes [#21112](https://github.com/ClickHouse/ClickHouse/issues/21112). Fixed bug that could cause duplicates with insert query (if one of the callbacks came a little too late). [#21138](https://github.com/ClickHouse/ClickHouse/pull/21138) ([Kseniia Sumarokova](https://github.com/kssenii)). +* Fix `input_format_null_as_default` take effective when types are nullable. This fixes [#21116](https://github.com/ClickHouse/ClickHouse/issues/21116) . [#21121](https://github.com/ClickHouse/ClickHouse/pull/21121) ([Amos Bird](https://github.com/amosbird)). +* fix bug related to cast Tuple to Map. Closes [#21029](https://github.com/ClickHouse/ClickHouse/issues/21029). [#21120](https://github.com/ClickHouse/ClickHouse/pull/21120) ([hexiaoting](https://github.com/hexiaoting)). +* Fix the metadata leak when the Replicated*MergeTree with custom (non default) ZooKeeper cluster is dropped. [#21119](https://github.com/ClickHouse/ClickHouse/pull/21119) ([fastio](https://github.com/fastio)). +* Fix type mismatch issue when using LowCardinality keys in joinGet. This fixes [#21114](https://github.com/ClickHouse/ClickHouse/issues/21114). [#21117](https://github.com/ClickHouse/ClickHouse/pull/21117) ([Amos Bird](https://github.com/amosbird)). +* fix default_replica_path and default_replica_name values are useless on Replicated(*)MergeTree engine when the engine needs specify other parameters. [#21060](https://github.com/ClickHouse/ClickHouse/pull/21060) ([mxzlxy](https://github.com/mxzlxy)). +* Out of bound memory access was possible when formatting specifically crafted out of range value of type `DateTime64`. This closes [#20494](https://github.com/ClickHouse/ClickHouse/issues/20494). This closes [#20543](https://github.com/ClickHouse/ClickHouse/issues/20543). [#21023](https://github.com/ClickHouse/ClickHouse/pull/21023) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Block parallel insertions into storage join. [#21009](https://github.com/ClickHouse/ClickHouse/pull/21009) ([vdimir](https://github.com/vdimir)). +* Fixed behaviour, when `ALTER MODIFY COLUMN` created mutation, that will knowingly fail. [#21007](https://github.com/ClickHouse/ClickHouse/pull/21007) ([Anton Popov](https://github.com/CurtizJ)). +* Closes [#9969](https://github.com/ClickHouse/ClickHouse/issues/9969). Fixed Brotli http compression error, which reproduced for large data sizes, slightly complicated structure and with json output format. Update Brotli to the latest version to include the "fix rare access to uninitialized data in ring-buffer". [#20991](https://github.com/ClickHouse/ClickHouse/pull/20991) ([Kseniia Sumarokova](https://github.com/kssenii)). +* Fix 'Empty task was returned from async task queue' on query cancellation. [#20881](https://github.com/ClickHouse/ClickHouse/pull/20881) ([Azat Khuzhin](https://github.com/azat)). +* `USE database;` query did not work when using MySQL 5.7 client to connect to ClickHouse server, it's fixed. Fixes [#18926](https://github.com/ClickHouse/ClickHouse/issues/18926). [#20878](https://github.com/ClickHouse/ClickHouse/pull/20878) ([tavplubix](https://github.com/tavplubix)). +* Fix usage of `-Distinct` combinator with `-State` combinator in aggregate functions. [#20866](https://github.com/ClickHouse/ClickHouse/pull/20866) ([Anton Popov](https://github.com/CurtizJ)). +* Fix subquery with union distinct and limit clause. close [#20597](https://github.com/ClickHouse/ClickHouse/issues/20597). [#20610](https://github.com/ClickHouse/ClickHouse/pull/20610) ([flynn](https://github.com/ucasFL)). +* Fixed inconsistent behavior of dictionary in case of queries where we look for absent keys in dictionary. [#20578](https://github.com/ClickHouse/ClickHouse/pull/20578) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)). +* Fix the number of threads for scalar subqueries and subqueries for index (after [#19007](https://github.com/ClickHouse/ClickHouse/issues/19007) single thread was always used). Fixes [#20457](https://github.com/ClickHouse/ClickHouse/issues/20457), [#20512](https://github.com/ClickHouse/ClickHouse/issues/20512). [#20550](https://github.com/ClickHouse/ClickHouse/pull/20550) ([Nikolai Kochetov](https://github.com/KochetovNicolai)). +* Fix crash which could happen if unknown packet was received from remove query (was introduced in [#17868](https://github.com/ClickHouse/ClickHouse/issues/17868)). [#20547](https://github.com/ClickHouse/ClickHouse/pull/20547) ([Azat Khuzhin](https://github.com/azat)). +* Add proper checks while parsing directory names for async INSERT (fixes SIGSEGV). [#20498](https://github.com/ClickHouse/ClickHouse/pull/20498) ([Azat Khuzhin](https://github.com/azat)). +* Fix function `transform` does not work properly for floating point keys. Closes [#20460](https://github.com/ClickHouse/ClickHouse/issues/20460). [#20479](https://github.com/ClickHouse/ClickHouse/pull/20479) ([flynn](https://github.com/ucasFL)). +* Fix infinite loop when propagating WITH aliases to subqueries. This fixes [#20388](https://github.com/ClickHouse/ClickHouse/issues/20388). [#20476](https://github.com/ClickHouse/ClickHouse/pull/20476) ([Amos Bird](https://github.com/amosbird)). +* Fix abnormal server termination when http client goes away. [#20464](https://github.com/ClickHouse/ClickHouse/pull/20464) ([Azat Khuzhin](https://github.com/azat)). +* Fix `LOGICAL_ERROR` for `join_use_nulls=1` when JOIN contains const from SELECT. [#20461](https://github.com/ClickHouse/ClickHouse/pull/20461) ([Azat Khuzhin](https://github.com/azat)). +* Check if table function `view` is used in expression list and throw an error. This fixes [#20342](https://github.com/ClickHouse/ClickHouse/issues/20342). [#20350](https://github.com/ClickHouse/ClickHouse/pull/20350) ([Amos Bird](https://github.com/amosbird)). +* Avoid invalid dereference in RANGE_HASHED() dictionary. [#20345](https://github.com/ClickHouse/ClickHouse/pull/20345) ([Azat Khuzhin](https://github.com/azat)). +* Fix null dereference with `join_use_nulls=1`. [#20344](https://github.com/ClickHouse/ClickHouse/pull/20344) ([Azat Khuzhin](https://github.com/azat)). +* Fix incorrect result of binary operations between two constant decimals of different scale. Fixes [#20283](https://github.com/ClickHouse/ClickHouse/issues/20283). [#20339](https://github.com/ClickHouse/ClickHouse/pull/20339) ([Maksim Kita](https://github.com/kitaisreal)). +* Fix too often retries of failed background tasks for `ReplicatedMergeTree` table engines family. This could lead to too verbose logging and increased CPU load. Fixes [#20203](https://github.com/ClickHouse/ClickHouse/issues/20203). [#20335](https://github.com/ClickHouse/ClickHouse/pull/20335) ([alesapin](https://github.com/alesapin)). +* Restrict to `DROP` or `RENAME` version column of `*CollapsingMergeTree` and `ReplacingMergeTree` table engines. [#20300](https://github.com/ClickHouse/ClickHouse/pull/20300) ([alesapin](https://github.com/alesapin)). +* Fixed the behavior when in case of broken JSON we tried to read the whole file into memory which leads to exception from the allocator. Fixes [#19719](https://github.com/ClickHouse/ClickHouse/issues/19719). [#20286](https://github.com/ClickHouse/ClickHouse/pull/20286) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)). +* Fix exception during vertical merge for `MergeTree` table engines family which don't allow to perform vertical merges. Fixes [#20259](https://github.com/ClickHouse/ClickHouse/issues/20259). [#20279](https://github.com/ClickHouse/ClickHouse/pull/20279) ([alesapin](https://github.com/alesapin)). +* Fix rare server crash on config reload during the shutdown. Fixes [#19689](https://github.com/ClickHouse/ClickHouse/issues/19689). [#20224](https://github.com/ClickHouse/ClickHouse/pull/20224) ([alesapin](https://github.com/alesapin)). +* Fix CTE when using in INSERT SELECT. This fixes [#20187](https://github.com/ClickHouse/ClickHouse/issues/20187), fixes [#20195](https://github.com/ClickHouse/ClickHouse/issues/20195). [#20211](https://github.com/ClickHouse/ClickHouse/pull/20211) ([Amos Bird](https://github.com/amosbird)). +* Fixes [#19314](https://github.com/ClickHouse/ClickHouse/issues/19314). [#20156](https://github.com/ClickHouse/ClickHouse/pull/20156) ([Ivan](https://github.com/abyss7)). +* fix toMinute function to handle special timezone correctly. [#20149](https://github.com/ClickHouse/ClickHouse/pull/20149) ([keenwolf](https://github.com/keen-wolf)). +* Fix server crash after query with `if` function with `Tuple` type of then/else branches result. `Tuple` type must contain `Array` or another complex type. Fixes [#18356](https://github.com/ClickHouse/ClickHouse/issues/18356). [#20133](https://github.com/ClickHouse/ClickHouse/pull/20133) ([alesapin](https://github.com/alesapin)). +* The `MongoDB` table engine now establishes connection only when it's going to read data. `ATTACH TABLE` won't try to connect anymore. [#20110](https://github.com/ClickHouse/ClickHouse/pull/20110) ([Vitaly Baranov](https://github.com/vitlibar)). +* Bugfix in StorageJoin. [#20079](https://github.com/ClickHouse/ClickHouse/pull/20079) ([vdimir](https://github.com/vdimir)). +* Fix the case when calculating modulo of division of negative number by small divisor, the resulting data type was not large enough to accomodate the negative result. This closes [#20052](https://github.com/ClickHouse/ClickHouse/issues/20052). [#20067](https://github.com/ClickHouse/ClickHouse/pull/20067) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* MaterializeMySQL: Fix replication for statements that update several tables. [#20066](https://github.com/ClickHouse/ClickHouse/pull/20066) ([Håvard Kvålen](https://github.com/havardk)). +* Prevent "Connection refused" in docker during initialization script execution. [#20012](https://github.com/ClickHouse/ClickHouse/pull/20012) ([filimonov](https://github.com/filimonov)). +* `EmbeddedRocksDB` is an experimental storage. Fix the issue with lack of proper type checking. Simplified code. This closes [#19967](https://github.com/ClickHouse/ClickHouse/issues/19967). [#19972](https://github.com/ClickHouse/ClickHouse/pull/19972) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Fix a segfault in function `fromModifiedJulianDay` when the argument type is `Nullable(T)` for any integral types other than Int32. [#19959](https://github.com/ClickHouse/ClickHouse/pull/19959) ([PHO](https://github.com/depressed-pho)). +* BloomFilter index crash fix. Fixes [#19757](https://github.com/ClickHouse/ClickHouse/issues/19757). [#19884](https://github.com/ClickHouse/ClickHouse/pull/19884) ([Maksim Kita](https://github.com/kitaisreal)). +* Deadlock was possible if system.text_log is enabled. This fixes [#19874](https://github.com/ClickHouse/ClickHouse/issues/19874). [#19875](https://github.com/ClickHouse/ClickHouse/pull/19875) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Fix starting the server with tables having default expressions containing dictGet(). Allow getting return type of dictGet() without loading dictionary. [#19805](https://github.com/ClickHouse/ClickHouse/pull/19805) ([Vitaly Baranov](https://github.com/vitlibar)). +* Fix clickhouse-client abort exception while executing only `select`. [#19790](https://github.com/ClickHouse/ClickHouse/pull/19790) ([taiyang-li](https://github.com/taiyang-li)). +* Fix a bug that moving pieces to destination table may failed in case of launching multiple clickhouse-copiers. [#19743](https://github.com/ClickHouse/ClickHouse/pull/19743) ([madianjun](https://github.com/mdianjun)). +* Background thread which executes `ON CLUSTER` queries might hang waiting for dropped replicated table to do something. It's fixed. [#19684](https://github.com/ClickHouse/ClickHouse/pull/19684) ([yiguolei](https://github.com/yiguolei)). + +#### Build/Testing/Packaging Improvement + +* Allow to build ClickHouse with AVX-2 enabled globally. It gives slight performance benefits on modern CPUs. Not recommended for production and will not be supported as official build for now. [#20180](https://github.com/ClickHouse/ClickHouse/pull/20180) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Fix some of the issues found by Coverity. See [#19964](https://github.com/ClickHouse/ClickHouse/issues/19964). [#20010](https://github.com/ClickHouse/ClickHouse/pull/20010) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Allow to start up with modified binary under gdb. In previous version if you set up breakpoint in gdb before start, server will refuse to start up due to failed integrity check. [#21258](https://github.com/ClickHouse/ClickHouse/pull/21258) ([alexey-milovidov](https://github.com/alexey-milovidov)). +* Add a test for different compression methods in Kafka. [#21111](https://github.com/ClickHouse/ClickHouse/pull/21111) ([filimonov](https://github.com/filimonov)). +* Fixed port clash from test_storage_kerberized_hdfs test. [#19974](https://github.com/ClickHouse/ClickHouse/pull/19974) ([Ilya Yatsishin](https://github.com/qoega)). +* Print `stdout` and `stderr` to log when failed to start docker in integration tests. Before this PR there was a very short error message in this case which didn't help to investigate the problems. [#20631](https://github.com/ClickHouse/ClickHouse/pull/20631) ([Vitaly Baranov](https://github.com/vitlibar)). + + ## ClickHouse release 21.2 ### ClickHouse release v21.2.2.8-stable, 2021-02-07 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9002f1df140..d310f7c298c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,7 +155,6 @@ option(ENABLE_TESTS "Provide unit_test_dbms target with Google.Test unit tests" if (OS_LINUX AND NOT UNBUNDLED AND MAKE_STATIC_LIBRARIES AND NOT SPLIT_SHARED_LIBRARIES AND CMAKE_VERSION VERSION_GREATER "3.9.0") # Only for Linux, x86_64. - # Implies ${ENABLE_FASTMEMCPY} option(GLIBC_COMPATIBILITY "Enable compatibility with older glibc libraries." ON) elseif(GLIBC_COMPATIBILITY) message (${RECONFIGURE_MESSAGE_LEVEL} "Glibc compatibility cannot be enabled in current configuration") @@ -169,7 +168,7 @@ endif () set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic") if (OS_LINUX) - find_program (OBJCOPY_PATH NAMES "llvm-objcopy" "llvm-objcopy-11" "llvm-objcopy-10" "llvm-objcopy-9" "llvm-objcopy-8" "objcopy") + find_program (OBJCOPY_PATH NAMES "llvm-objcopy" "llvm-objcopy-12" "llvm-objcopy-11" "llvm-objcopy-10" "llvm-objcopy-9" "llvm-objcopy-8" "objcopy") if (OBJCOPY_PATH) message(STATUS "Using objcopy: ${OBJCOPY_PATH}.") @@ -241,9 +240,7 @@ else() message(STATUS "Disabling compiler -pipe option (have only ${AVAILABLE_PHYSICAL_MEMORY} mb of memory)") endif() -if(NOT DISABLE_CPU_OPTIMIZE) - include(cmake/cpu_features.cmake) -endif() +include(cmake/cpu_features.cmake) option(ARCH_NATIVE "Add -march=native compiler flag") @@ -331,7 +328,7 @@ if (COMPILER_CLANG) endif () # Always prefer llvm tools when using clang. For instance, we cannot use GNU ar when llvm LTO is enabled - find_program (LLVM_AR_PATH NAMES "llvm-ar" "llvm-ar-11" "llvm-ar-10" "llvm-ar-9" "llvm-ar-8") + find_program (LLVM_AR_PATH NAMES "llvm-ar" "llvm-ar-12" "llvm-ar-11" "llvm-ar-10" "llvm-ar-9" "llvm-ar-8") if (LLVM_AR_PATH) message(STATUS "Using llvm-ar: ${LLVM_AR_PATH}.") @@ -340,7 +337,7 @@ if (COMPILER_CLANG) message(WARNING "Cannot find llvm-ar. System ar will be used instead. It does not work with ThinLTO.") endif () - find_program (LLVM_RANLIB_PATH NAMES "llvm-ranlib" "llvm-ranlib-11" "llvm-ranlib-10" "llvm-ranlib-9" "llvm-ranlib-8") + find_program (LLVM_RANLIB_PATH NAMES "llvm-ranlib" "llvm-ranlib-12" "llvm-ranlib-11" "llvm-ranlib-10" "llvm-ranlib-9" "llvm-ranlib-8") if (LLVM_RANLIB_PATH) message(STATUS "Using llvm-ranlib: ${LLVM_RANLIB_PATH}.") @@ -536,7 +533,7 @@ macro (add_executable target) # explicitly acquire and interpose malloc symbols by clickhouse_malloc # if GLIBC_COMPATIBILITY is ON and ENABLE_THINLTO is on than provide memcpy symbol explicitly to neutrialize thinlto's libcall generation. if (GLIBC_COMPATIBILITY AND ENABLE_THINLTO) - _add_executable (${ARGV} $ $) + _add_executable (${ARGV} $ $) else () _add_executable (${ARGV} $) endif () diff --git a/README.md b/README.md index 1c6a021c00c..3329a98877f 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,3 @@ ClickHouse® is an open-source column-oriented database management system that a * [Code Browser](https://clickhouse.tech/codebrowser/html_report/ClickHouse/index.html) with syntax highlight and navigation. * [Contacts](https://clickhouse.tech/#contacts) can help to get your questions answered if there are any. * You can also [fill this form](https://clickhouse.tech/#meet) to meet Yandex ClickHouse team in person. - -## Upcoming Events -* [Chinese ClickHouse Meetup (online)](http://hdxu.cn/8KxZE) on 6 February 2021. diff --git a/base/common/CMakeLists.txt b/base/common/CMakeLists.txt index cea52b443dd..b4bf4f55466 100644 --- a/base/common/CMakeLists.txt +++ b/base/common/CMakeLists.txt @@ -74,7 +74,6 @@ target_link_libraries (common ${CITYHASH_LIBRARIES} boost::headers_only boost::system - FastMemcpy Poco::Net Poco::Net::SSL Poco::Util diff --git a/base/common/DateLUTImpl.h b/base/common/DateLUTImpl.h index 0538d3a9ab8..0c7465ec7a5 100644 --- a/base/common/DateLUTImpl.h +++ b/base/common/DateLUTImpl.h @@ -7,6 +7,7 @@ #include #include + #define DATE_LUT_MAX (0xFFFFFFFFU - 86400) #define DATE_LUT_MAX_DAY_NUM (0xFFFFFFFFU / 86400) /// Table size is bigger than DATE_LUT_MAX_DAY_NUM to fill all indices within UInt16 range: this allows to remove extra check. @@ -249,7 +250,7 @@ public: { DayNum index = findIndex(t); - if (unlikely(index == 0)) + if (unlikely(index == 0 || index > DATE_LUT_MAX_DAY_NUM)) return t + offset_at_start_of_epoch; time_t res = t - lut[index].date; @@ -264,18 +265,18 @@ public: { DayNum index = findIndex(t); - /// If it is not 1970 year (findIndex found nothing appropriate), - /// than limit number of hours to avoid insane results like 1970-01-01 89:28:15 - if (unlikely(index == 0)) + /// If it is overflow case, + /// then limit number of hours to avoid insane results like 1970-01-01 89:28:15 + if (unlikely(index == 0 || index > DATE_LUT_MAX_DAY_NUM)) return static_cast((t + offset_at_start_of_epoch) / 3600) % 24; - time_t res = t - lut[index].date; + time_t time = t - lut[index].date; - /// Data is cleaned to avoid possibility of underflow. - if (res >= lut[index].time_at_offset_change) - res += lut[index].amount_of_offset_change; + if (time >= lut[index].time_at_offset_change) + time += lut[index].amount_of_offset_change; - return res / 3600; + unsigned res = time / 3600; + return res <= 23 ? res : 0; } /** Calculating offset from UTC in seconds. @@ -314,15 +315,21 @@ public: * each minute, with added or subtracted leap second, spans exactly 60 unix timestamps. */ - inline unsigned toSecond(time_t t) const { return t % 60; } + inline unsigned toSecond(time_t t) const { return UInt32(t) % 60; } inline unsigned toMinute(time_t t) const { if (offset_is_whole_number_of_hours_everytime) - return (t / 60) % 60; + return (UInt32(t) / 60) % 60; - UInt32 date = find(t).date; - return (UInt32(t) - date) / 60 % 60; + /// To consider the DST changing situation within this day. + /// also make the special timezones with no whole hour offset such as 'Australia/Lord_Howe' been taken into account + DayNum index = findIndex(t); + UInt32 res = t - lut[index].date; + if (lut[index].amount_of_offset_change != 0 && t >= lut[index].date + lut[index].time_at_offset_change) + res += lut[index].amount_of_offset_change; + + return res / 60 % 60; } inline time_t toStartOfMinute(time_t t) const { return t / 60 * 60; } @@ -555,9 +562,7 @@ public: } } - /* - * check and change mode to effective - */ + /// Check and change mode to effective. inline UInt8 check_week_mode(UInt8 mode) const { UInt8 week_format = (mode & 7); @@ -566,10 +571,9 @@ public: return week_format; } - /* - * Calc weekday from d - * Returns 0 for monday, 1 for tuesday ... - */ + /** Calculate weekday from d. + * Returns 0 for monday, 1 for tuesday... + */ inline unsigned calc_weekday(DayNum d, bool sunday_first_day_of_week) const { if (!sunday_first_day_of_week) @@ -578,7 +582,7 @@ public: return toDayOfWeek(DayNum(d + 1)) - 1; } - /* Calc days in one year. */ + /// Calculate days in one year. inline unsigned calc_days_in_year(UInt16 year) const { return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)) ? 366 : 365); diff --git a/base/common/arithmeticOverflow.h b/base/common/arithmeticOverflow.h index 8df037a14af..a92fe56b9cb 100644 --- a/base/common/arithmeticOverflow.h +++ b/base/common/arithmeticOverflow.h @@ -1,9 +1,30 @@ #pragma once #include +#include + namespace common { + /// Multiply and ignore overflow. + template + inline auto NO_SANITIZE_UNDEFINED mulIgnoreOverflow(T1 x, T2 y) + { + return x * y; + } + + template + inline auto NO_SANITIZE_UNDEFINED addIgnoreOverflow(T1 x, T2 y) + { + return x + y; + } + + template + inline auto NO_SANITIZE_UNDEFINED subIgnoreOverflow(T1 x, T2 y) + { + return x - y; + } + template inline bool addOverflow(T x, T y, T & res) { @@ -33,14 +54,14 @@ namespace common { static constexpr __int128 min_int128 = minInt128(); static constexpr __int128 max_int128 = maxInt128(); - res = x + y; + res = addIgnoreOverflow(x, y); return (y > 0 && x > max_int128 - y) || (y < 0 && x < min_int128 - y); } template <> inline bool addOverflow(wInt256 x, wInt256 y, wInt256 & res) { - res = x + y; + res = addIgnoreOverflow(x, y); return (y > 0 && x > std::numeric_limits::max() - y) || (y < 0 && x < std::numeric_limits::min() - y); } @@ -48,7 +69,7 @@ namespace common template <> inline bool addOverflow(wUInt256 x, wUInt256 y, wUInt256 & res) { - res = x + y; + res = addIgnoreOverflow(x, y); return x > std::numeric_limits::max() - y; } @@ -81,14 +102,14 @@ namespace common { static constexpr __int128 min_int128 = minInt128(); static constexpr __int128 max_int128 = maxInt128(); - res = x - y; + res = subIgnoreOverflow(x, y); return (y < 0 && x > max_int128 + y) || (y > 0 && x < min_int128 + y); } template <> inline bool subOverflow(wInt256 x, wInt256 y, wInt256 & res) { - res = x - y; + res = subIgnoreOverflow(x, y); return (y < 0 && x > std::numeric_limits::max() + y) || (y > 0 && x < std::numeric_limits::min() + y); } @@ -96,7 +117,7 @@ namespace common template <> inline bool subOverflow(wUInt256 x, wUInt256 y, wUInt256 & res) { - res = x - y; + res = subIgnoreOverflow(x, y); return x < y; } @@ -127,33 +148,33 @@ namespace common template <> inline bool mulOverflow(__int128 x, __int128 y, __int128 & res) { - res = static_cast(x) * static_cast(y); /// Avoid signed integer overflow. + res = mulIgnoreOverflow(x, y); if (!x || !y) return false; unsigned __int128 a = (x > 0) ? x : -x; unsigned __int128 b = (y > 0) ? y : -y; - return (a * b) / b != a; + return mulIgnoreOverflow(a, b) / b != a; } template <> inline bool mulOverflow(wInt256 x, wInt256 y, wInt256 & res) { - res = x * y; + res = mulIgnoreOverflow(x, y); if (!x || !y) return false; wInt256 a = (x > 0) ? x : -x; wInt256 b = (y > 0) ? y : -y; - return (a * b) / b != a; + return mulIgnoreOverflow(a, b) / b != a; } template <> inline bool mulOverflow(wUInt256 x, wUInt256 y, wUInt256 & res) { - res = x * y; + res = mulIgnoreOverflow(x, y); if (!x || !y) return false; - return (x * y) / y != x; + return res / y != x; } } diff --git a/base/common/defines.h b/base/common/defines.h index 845a53179ef..ada8245f494 100644 --- a/base/common/defines.h +++ b/base/common/defines.h @@ -1,5 +1,20 @@ #pragma once +/// __has_feature supported only by clang. +/// +/// But libcxx/libcxxabi overrides it to 0, +/// thus the checks for __has_feature will be wrong. +/// +/// NOTE: +/// - __has_feature cannot be simply undefined, +/// since this will be broken if some C++ header will be included after +/// including +/// - it should not have fallback to 0, +/// since this may create false-positive detection (common problem) +#if defined(__clang__) && defined(__has_feature) +# define ch_has_feature __has_feature +#endif + #if defined(_MSC_VER) # if !defined(likely) # define likely(x) (x) @@ -32,8 +47,8 @@ /// Check for presence of address sanitizer #if !defined(ADDRESS_SANITIZER) -# if defined(__has_feature) -# if __has_feature(address_sanitizer) +# if defined(ch_has_feature) +# if ch_has_feature(address_sanitizer) # define ADDRESS_SANITIZER 1 # endif # elif defined(__SANITIZE_ADDRESS__) @@ -42,8 +57,8 @@ #endif #if !defined(THREAD_SANITIZER) -# if defined(__has_feature) -# if __has_feature(thread_sanitizer) +# if defined(ch_has_feature) +# if ch_has_feature(thread_sanitizer) # define THREAD_SANITIZER 1 # endif # elif defined(__SANITIZE_THREAD__) @@ -52,8 +67,8 @@ #endif #if !defined(MEMORY_SANITIZER) -# if defined(__has_feature) -# if __has_feature(memory_sanitizer) +# if defined(ch_has_feature) +# if ch_has_feature(memory_sanitizer) # define MEMORY_SANITIZER 1 # endif # elif defined(__MEMORY_SANITIZER__) @@ -61,6 +76,16 @@ # endif #endif +#if !defined(UNDEFINED_BEHAVIOR_SANITIZER) +# if defined(__has_feature) +# if __has_feature(undefined_behavior_sanitizer) +# define UNDEFINED_BEHAVIOR_SANITIZER 1 +# endif +# elif defined(__UNDEFINED_BEHAVIOR_SANITIZER__) +# define UNDEFINED_BEHAVIOR_SANITIZER 1 +# endif +#endif + #if defined(ADDRESS_SANITIZER) # define BOOST_USE_ASAN 1 # define BOOST_USE_UCONTEXT 1 diff --git a/base/common/phdr_cache.cpp b/base/common/phdr_cache.cpp index 4f6a066adab..49d566dac19 100644 --- a/base/common/phdr_cache.cpp +++ b/base/common/phdr_cache.cpp @@ -15,11 +15,11 @@ #endif #define __msan_unpoison(X, Y) // NOLINT -#if defined(__has_feature) -# if __has_feature(memory_sanitizer) -# undef __msan_unpoison -# include -# endif +#if defined(ch_has_feature) +# if ch_has_feature(memory_sanitizer) +# undef __msan_unpoison +# include +# endif #endif #include diff --git a/base/common/tests/CMakeLists.txt b/base/common/tests/CMakeLists.txt index b7082ee9900..6775d443fb6 100644 --- a/base/common/tests/CMakeLists.txt +++ b/base/common/tests/CMakeLists.txt @@ -11,7 +11,7 @@ set(PLATFORM_LIBS ${CMAKE_DL_LIBS}) target_link_libraries (date_lut2 PRIVATE common ${PLATFORM_LIBS}) target_link_libraries (date_lut3 PRIVATE common ${PLATFORM_LIBS}) target_link_libraries (date_lut_default_timezone PRIVATE common ${PLATFORM_LIBS}) -target_link_libraries (local_date_time_comparison PRIVATE common) +target_link_libraries (local_date_time_comparison PRIVATE common ${PLATFORM_LIBS}) target_link_libraries (realloc-perf PRIVATE common) add_check(local_date_time_comparison) diff --git a/base/common/wide_integer_impl.h b/base/common/wide_integer_impl.h index a34e757eaa5..5b981326e25 100644 --- a/base/common/wide_integer_impl.h +++ b/base/common/wide_integer_impl.h @@ -249,15 +249,15 @@ struct integer::_impl return; } - const T alpha = t / max_int; + const T alpha = t / static_cast(max_int); - if (alpha <= max_int) + if (alpha <= static_cast(max_int)) self = static_cast(alpha); else // max(double) / 2^64 will surely contain less than 52 precision bits, so speed up computations. set_multiplier(self, alpha); self *= max_int; - self += static_cast(t - alpha * max_int); // += b_i + self += static_cast(t - alpha * static_cast(max_int)); // += b_i } constexpr static void wide_integer_from_bultin(integer& self, double rhs) noexcept { @@ -275,7 +275,7 @@ struct integer::_impl "On your system long double has less than 64 precision bits," "which may result in UB when initializing double from int64_t"); - if ((rhs > 0 && rhs < max_int) || (rhs < 0 && rhs > min_int)) + if ((rhs > 0 && rhs < static_cast(max_int)) || (rhs < 0 && rhs > static_cast(min_int))) { self = static_cast(rhs); return; diff --git a/base/daemon/BaseDaemon.cpp b/base/daemon/BaseDaemon.cpp index 491ffe6a775..83384038b7c 100644 --- a/base/daemon/BaseDaemon.cpp +++ b/base/daemon/BaseDaemon.cpp @@ -416,7 +416,9 @@ static void sanitizerDeathCallback() else log_message = "Terminate called without an active exception"; - static const size_t buf_size = 1024; + /// POSIX.1 says that write(2)s of less than PIPE_BUF bytes must be atomic - man 7 pipe + /// And the buffer should not be too small because our exception messages can be large. + static constexpr size_t buf_size = PIPE_BUF; if (log_message.size() > buf_size - 16) log_message.resize(buf_size - 16); @@ -562,6 +564,7 @@ void debugIncreaseOOMScore() { DB::WriteBufferFromFile buf("/proc/self/oom_score_adj"); buf.write(new_score.c_str(), new_score.size()); + buf.close(); } catch (const Poco::Exception & e) { @@ -784,7 +787,7 @@ void BaseDaemon::initializeTerminationAndSignalProcessing() /// Setup signal handlers. /// SIGTSTP is added for debugging purposes. To output a stack trace of any running thread at anytime. - addSignalHandler({SIGABRT, SIGSEGV, SIGILL, SIGBUS, SIGSYS, SIGFPE, SIGPIPE, SIGTSTP}, signalHandler, &handled_signals); + addSignalHandler({SIGABRT, SIGSEGV, SIGILL, SIGBUS, SIGSYS, SIGFPE, SIGPIPE, SIGTSTP, SIGTRAP}, signalHandler, &handled_signals); addSignalHandler({SIGHUP, SIGUSR1}, closeLogsSignalHandler, &handled_signals); addSignalHandler({SIGINT, SIGQUIT, SIGTERM}, terminateRequestedSignalHandler, &handled_signals); diff --git a/base/daemon/BaseDaemon.h b/base/daemon/BaseDaemon.h index 42d94629ae9..8b9d765cf2e 100644 --- a/base/daemon/BaseDaemon.h +++ b/base/daemon/BaseDaemon.h @@ -83,7 +83,7 @@ public: template void writeToGraphite(const std::string & key, const T & value, const std::string & config_name = DEFAULT_GRAPHITE_CONFIG_NAME, time_t timestamp = 0, const std::string & custom_root_path = "") { - auto writer = getGraphiteWriter(config_name); + auto *writer = getGraphiteWriter(config_name); if (writer) writer->write(key, value, timestamp, custom_root_path); } @@ -91,7 +91,7 @@ public: template void writeToGraphite(const GraphiteWriter::KeyValueVector & key_vals, const std::string & config_name = DEFAULT_GRAPHITE_CONFIG_NAME, time_t timestamp = 0, const std::string & custom_root_path = "") { - auto writer = getGraphiteWriter(config_name); + auto *writer = getGraphiteWriter(config_name); if (writer) writer->write(key_vals, timestamp, custom_root_path); } @@ -99,7 +99,7 @@ public: template void writeToGraphite(const GraphiteWriter::KeyValueVector & key_vals, const std::chrono::system_clock::time_point & current_time, const std::string & custom_root_path) { - auto writer = getGraphiteWriter(); + auto *writer = getGraphiteWriter(); if (writer) writer->write(key_vals, std::chrono::system_clock::to_time_t(current_time), custom_root_path); } diff --git a/base/glibc-compatibility/CMakeLists.txt b/base/glibc-compatibility/CMakeLists.txt index 684c6162941..e785e2ab2ce 100644 --- a/base/glibc-compatibility/CMakeLists.txt +++ b/base/glibc-compatibility/CMakeLists.txt @@ -1,5 +1,8 @@ if (GLIBC_COMPATIBILITY) - set (ENABLE_FASTMEMCPY ON) + add_subdirectory(memcpy) + if(TARGET memcpy) + set(MEMCPY_LIBRARY memcpy) + endif() enable_language(ASM) include(CheckIncludeFile) @@ -27,13 +30,6 @@ if (GLIBC_COMPATIBILITY) list(APPEND glibc_compatibility_sources musl/getentropy.c) endif() - if (NOT ARCH_ARM) - # clickhouse_memcpy don't support ARCH_ARM, see https://github.com/ClickHouse/ClickHouse/issues/18951 - add_library (clickhouse_memcpy OBJECT - ${ClickHouse_SOURCE_DIR}/contrib/FastMemcpy/memcpy_wrapper.c - ) - endif() - # Need to omit frame pointers to match the performance of glibc set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer") @@ -51,15 +47,16 @@ if (GLIBC_COMPATIBILITY) target_compile_options(glibc-compatibility PRIVATE -fPIC) endif () - target_link_libraries(global-libs INTERFACE glibc-compatibility) + target_link_libraries(global-libs INTERFACE glibc-compatibility ${MEMCPY_LIBRARY}) install( - TARGETS glibc-compatibility + TARGETS glibc-compatibility ${MEMCPY_LIBRARY} EXPORT global ARCHIVE DESTINATION lib ) message (STATUS "Some symbols from glibc will be replaced for compatibility") + elseif (YANDEX_OFFICIAL_BUILD) message (WARNING "Option GLIBC_COMPATIBILITY must be turned on for production builds.") endif () diff --git a/base/glibc-compatibility/memcpy/CMakeLists.txt b/base/glibc-compatibility/memcpy/CMakeLists.txt new file mode 100644 index 00000000000..133995d9b96 --- /dev/null +++ b/base/glibc-compatibility/memcpy/CMakeLists.txt @@ -0,0 +1,8 @@ +if (ARCH_AMD64) + add_library(memcpy STATIC memcpy.cpp) + + # We allow to include memcpy.h from user code for better inlining. + target_include_directories(memcpy PUBLIC $) + + target_compile_options(memcpy PRIVATE -fno-builtin-memcpy) +endif () diff --git a/base/glibc-compatibility/memcpy/memcpy.cpp b/base/glibc-compatibility/memcpy/memcpy.cpp new file mode 100644 index 00000000000..ec43a2c3649 --- /dev/null +++ b/base/glibc-compatibility/memcpy/memcpy.cpp @@ -0,0 +1,6 @@ +#include "memcpy.h" + +extern "C" void * memcpy(void * __restrict dst, const void * __restrict src, size_t size) +{ + return inline_memcpy(dst, src, size); +} diff --git a/base/glibc-compatibility/memcpy/memcpy.h b/base/glibc-compatibility/memcpy/memcpy.h new file mode 100644 index 00000000000..f9f81bcb0fe --- /dev/null +++ b/base/glibc-compatibility/memcpy/memcpy.h @@ -0,0 +1,217 @@ +#include + +#include + + +/** Custom memcpy implementation for ClickHouse. + * It has the following benefits over using glibc's implementation: + * 1. Avoiding dependency on specific version of glibc's symbol, like memcpy@@GLIBC_2.14 for portability. + * 2. Avoiding indirect call via PLT due to shared linking, that can be less efficient. + * 3. It's possible to include this header and call inline_memcpy directly for better inlining or interprocedural analysis. + * 4. Better results on our performance tests on current CPUs: up to 25% on some queries and up to 0.7%..1% in average across all queries. + * + * Writing our own memcpy is extremely difficult for the following reasons: + * 1. The optimal variant depends on the specific CPU model. + * 2. The optimal variant depends on the distribution of size arguments. + * 3. It depends on the number of threads copying data concurrently. + * 4. It also depends on how the calling code is using the copied data and how the different memcpy calls are related to each other. + * Due to vast range of scenarios it makes proper testing especially difficult. + * When writing our own memcpy there is a risk to overoptimize it + * on non-representative microbenchmarks while making real-world use cases actually worse. + * + * Most of the benchmarks for memcpy on the internet are wrong. + * + * Let's look at the details: + * + * For small size, the order of branches in code is important. + * There are variants with specific order of branches (like here or in glibc) + * or with jump table (in asm code see example from Cosmopolitan libc: + * https://github.com/jart/cosmopolitan/blob/de09bec215675e9b0beb722df89c6f794da74f3f/libc/nexgen32e/memcpy.S#L61) + * or with Duff device in C (see https://github.com/skywind3000/FastMemcpy/) + * + * It's also important how to copy uneven sizes. + * Almost every implementation, including this, is using two overlapping movs. + * + * It is important to disable -ftree-loop-distribute-patterns when compiling memcpy implementation, + * otherwise the compiler can replace internal loops to a call to memcpy that will lead to infinite recursion. + * + * For larger sizes it's important to choose the instructions used: + * - SSE or AVX or AVX-512; + * - rep movsb; + * Performance will depend on the size threshold, on the CPU model, on the "erms" flag + * ("Enhansed Rep MovS" - it indicates that performance of "rep movsb" is decent for large sizes) + * https://stackoverflow.com/questions/43343231/enhanced-rep-movsb-for-memcpy + * + * Using AVX-512 can be bad due to throttling. + * Using AVX can be bad if most code is using SSE due to switching penalty + * (it also depends on the usage of "vzeroupper" instruction). + * But in some cases AVX gives a win. + * + * It also depends on how many times the loop will be unrolled. + * We are unrolling the loop 8 times (by the number of available registers), but it not always the best. + * + * It also depends on the usage of aligned or unaligned loads/stores. + * We are using unaligned loads and aligned stores. + * + * It also depends on the usage of prefetch instructions. It makes sense on some Intel CPUs but can slow down performance on AMD. + * Setting up correct offset for prefetching is non-obvious. + * + * Non-temporary (cache bypassing) stores can be used for very large sizes (more than a half of L3 cache). + * But the exact threshold is unclear - when doing memcpy from multiple threads the optimal threshold can be lower, + * because L3 cache is shared (and L2 cache is partially shared). + * + * Very large size of memcpy typically indicates suboptimal (not cache friendly) algorithms in code or unrealistic scenarios, + * so we don't pay attention to using non-temporary stores. + * + * On recent Intel CPUs, the presence of "erms" makes "rep movsb" the most benefitial, + * even comparing to non-temporary aligned unrolled stores even with the most wide registers. + * + * memcpy can be written in asm, C or C++. The latter can also use inline asm. + * The asm implementation can be better to make sure that compiler won't make the code worse, + * to ensure the order of branches, the code layout, the usage of all required registers. + * But if it is located in separate translation unit, inlining will not be possible + * (inline asm can be used to overcome this limitation). + * Sometimes C or C++ code can be further optimized by compiler. + * For example, clang is capable replacing SSE intrinsics to AVX code if -mavx is used. + * + * Please note that compiler can replace plain code to memcpy and vice versa. + * - memcpy with compile-time known small size is replaced to simple instructions without a call to memcpy; + * it is controlled by -fbuiltin-memcpy and can be manually ensured by calling __builtin_memcpy. + * This is often used to implement unaligned load/store without undefined behaviour in C++. + * - a loop with copying bytes can be recognized and replaced by a call to memcpy; + * it is controlled by -ftree-loop-distribute-patterns. + * - also note that a loop with copying bytes can be unrolled, peeled and vectorized that will give you + * inline code somewhat similar to a decent implementation of memcpy. + * + * This description is up to date as of Mar 2021. + * + * How to test the memcpy implementation for performance: + * 1. Test on real production workload. + * 2. For synthetic test, see utils/memcpy-bench, but make sure you will do the best to exhaust the wide range of scenarios. + * + * TODO: Add self-tuning memcpy with bayesian bandits algorithm for large sizes. + * See https://habr.com/en/company/yandex/blog/457612/ + */ + + +static inline void * inline_memcpy(void * __restrict dst_, const void * __restrict src_, size_t size) +{ + /// We will use pointer arithmetic, so char pointer will be used. + /// Note that __restrict makes sense (otherwise compiler will reload data from memory + /// instead of using the value of registers due to possible aliasing). + char * __restrict dst = reinterpret_cast(dst_); + const char * __restrict src = reinterpret_cast(src_); + + /// Standard memcpy returns the original value of dst. It is rarely used but we have to do it. + /// If you use memcpy with small but non-constant sizes, you can call inline_memcpy directly + /// for inlining and removing this single instruction. + void * ret = dst; + +tail: + /// Small sizes and tails after the loop for large sizes. + /// The order of branches is important but in fact the optimal order depends on the distribution of sizes in your application. + /// This order of branches is from the disassembly of glibc's code. + /// We copy chunks of possibly uneven size with two overlapping movs. + /// Example: to copy 5 bytes [0, 1, 2, 3, 4] we will copy tail [1, 2, 3, 4] first and then head [0, 1, 2, 3]. + if (size <= 16) + { + if (size >= 8) + { + /// Chunks of 8..16 bytes. + __builtin_memcpy(dst + size - 8, src + size - 8, 8); + __builtin_memcpy(dst, src, 8); + } + else if (size >= 4) + { + /// Chunks of 4..7 bytes. + __builtin_memcpy(dst + size - 4, src + size - 4, 4); + __builtin_memcpy(dst, src, 4); + } + else if (size >= 2) + { + /// Chunks of 2..3 bytes. + __builtin_memcpy(dst + size - 2, src + size - 2, 2); + __builtin_memcpy(dst, src, 2); + } + else if (size >= 1) + { + /// A single byte. + *dst = *src; + } + /// No bytes remaining. + } + else + { + /// Medium and large sizes. + if (size <= 128) + { + /// Medium size, not enough for full loop unrolling. + + /// We will copy the last 16 bytes. + _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + size - 16), _mm_loadu_si128(reinterpret_cast(src + size - 16))); + + /// Then we will copy every 16 bytes from the beginning in a loop. + /// The last loop iteration will possibly overwrite some part of already copied last 16 bytes. + /// This is Ok, similar to the code for small sizes above. + while (size > 16) + { + _mm_storeu_si128(reinterpret_cast<__m128i *>(dst), _mm_loadu_si128(reinterpret_cast(src))); + dst += 16; + src += 16; + size -= 16; + } + } + else + { + /// Large size with fully unrolled loop. + + /// Align destination to 16 bytes boundary. + size_t padding = (16 - (reinterpret_cast(dst) & 15)) & 15; + + /// If not aligned - we will copy first 16 bytes with unaligned stores. + if (padding > 0) + { + __m128i head = _mm_loadu_si128(reinterpret_cast(src)); + _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), head); + dst += padding; + src += padding; + size -= padding; + } + + /// Aligned unrolled copy. We will use all available SSE registers. + /// It's not possible to have both src and dst aligned. + /// So, we will use aligned stores and unaligned loads. + __m128i c0, c1, c2, c3, c4, c5, c6, c7; + + while (size >= 128) + { + c0 = _mm_loadu_si128(reinterpret_cast(src) + 0); + c1 = _mm_loadu_si128(reinterpret_cast(src) + 1); + c2 = _mm_loadu_si128(reinterpret_cast(src) + 2); + c3 = _mm_loadu_si128(reinterpret_cast(src) + 3); + c4 = _mm_loadu_si128(reinterpret_cast(src) + 4); + c5 = _mm_loadu_si128(reinterpret_cast(src) + 5); + c6 = _mm_loadu_si128(reinterpret_cast(src) + 6); + c7 = _mm_loadu_si128(reinterpret_cast(src) + 7); + src += 128; + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 0), c0); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 1), c1); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 2), c2); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 3), c3); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 4), c4); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 5), c5); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 6), c6); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 7), c7); + dst += 128; + + size -= 128; + } + + /// The latest remaining 0..127 bytes will be processed as usual. + goto tail; + } + } + + return ret; +} + diff --git a/base/mysqlxx/Connection.cpp b/base/mysqlxx/Connection.cpp index 8a15115cb06..2dbbc0c73f3 100644 --- a/base/mysqlxx/Connection.cpp +++ b/base/mysqlxx/Connection.cpp @@ -51,10 +51,11 @@ Connection::Connection( const char* ssl_key, unsigned timeout, unsigned rw_timeout, - bool enable_local_infile) + bool enable_local_infile, + bool opt_reconnect) : Connection() { - connect(db, server, user, password, port, socket, ssl_ca, ssl_cert, ssl_key, timeout, rw_timeout, enable_local_infile); + connect(db, server, user, password, port, socket, ssl_ca, ssl_cert, ssl_key, timeout, rw_timeout, enable_local_infile, opt_reconnect); } Connection::Connection(const std::string & config_name) @@ -80,7 +81,8 @@ void Connection::connect(const char* db, const char * ssl_key, unsigned timeout, unsigned rw_timeout, - bool enable_local_infile) + bool enable_local_infile, + bool opt_reconnect) { if (is_connected) disconnect(); @@ -104,9 +106,8 @@ void Connection::connect(const char* db, if (mysql_options(driver.get(), MYSQL_OPT_LOCAL_INFILE, &enable_local_infile_arg)) throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get())); - /// Enables auto-reconnect. - bool reconnect = true; - if (mysql_options(driver.get(), MYSQL_OPT_RECONNECT, reinterpret_cast(&reconnect))) + /// See C API Developer Guide: Automatic Reconnection Control + if (mysql_options(driver.get(), MYSQL_OPT_RECONNECT, reinterpret_cast(&opt_reconnect))) throw ConnectionFailed(errorMessage(driver.get()), mysql_errno(driver.get())); /// Specifies particular ssl key and certificate if it needs diff --git a/base/mysqlxx/Connection.h b/base/mysqlxx/Connection.h index ca67db0e0c6..65955136eb1 100644 --- a/base/mysqlxx/Connection.h +++ b/base/mysqlxx/Connection.h @@ -14,6 +14,8 @@ /// Disable LOAD DATA LOCAL INFILE because it is insecure #define MYSQLXX_DEFAULT_ENABLE_LOCAL_INFILE false +/// See https://dev.mysql.com/doc/c-api/5.7/en/c-api-auto-reconnect.html +#define MYSQLXX_DEFAULT_MYSQL_OPT_RECONNECT true namespace mysqlxx @@ -76,7 +78,8 @@ public: const char * ssl_key = "", unsigned timeout = MYSQLXX_DEFAULT_TIMEOUT, unsigned rw_timeout = MYSQLXX_DEFAULT_RW_TIMEOUT, - bool enable_local_infile = MYSQLXX_DEFAULT_ENABLE_LOCAL_INFILE); + bool enable_local_infile = MYSQLXX_DEFAULT_ENABLE_LOCAL_INFILE, + bool opt_reconnect = MYSQLXX_DEFAULT_MYSQL_OPT_RECONNECT); /// Creates connection. Can be used if Poco::Util::Application is using. /// All settings will be got from config_name section of configuration. @@ -96,7 +99,8 @@ public: const char* ssl_key, unsigned timeout = MYSQLXX_DEFAULT_TIMEOUT, unsigned rw_timeout = MYSQLXX_DEFAULT_RW_TIMEOUT, - bool enable_local_infile = MYSQLXX_DEFAULT_ENABLE_LOCAL_INFILE); + bool enable_local_infile = MYSQLXX_DEFAULT_ENABLE_LOCAL_INFILE, + bool opt_reconnect = MYSQLXX_DEFAULT_MYSQL_OPT_RECONNECT); void connect(const std::string & config_name) { @@ -112,6 +116,7 @@ public: std::string ssl_cert = cfg.getString(config_name + ".ssl_cert", ""); std::string ssl_key = cfg.getString(config_name + ".ssl_key", ""); bool enable_local_infile = cfg.getBool(config_name + ".enable_local_infile", MYSQLXX_DEFAULT_ENABLE_LOCAL_INFILE); + bool opt_reconnect = cfg.getBool(config_name + ".opt_reconnect", MYSQLXX_DEFAULT_MYSQL_OPT_RECONNECT); unsigned timeout = cfg.getInt(config_name + ".connect_timeout", @@ -135,7 +140,8 @@ public: ssl_key.c_str(), timeout, rw_timeout, - enable_local_infile); + enable_local_infile, + opt_reconnect); } /// If MySQL connection was established. diff --git a/base/mysqlxx/Exception.h b/base/mysqlxx/Exception.h index eaeb3565af1..48cd0997b94 100644 --- a/base/mysqlxx/Exception.h +++ b/base/mysqlxx/Exception.h @@ -26,6 +26,15 @@ struct ConnectionFailed : public Exception }; +/// Connection to MySQL server was lost +struct ConnectionLost : public Exception +{ + ConnectionLost(const std::string & msg, int code = 0) : Exception(msg, code) {} + const char * name() const throw() override { return "mysqlxx::ConnectionLost"; } + const char * className() const throw() override { return "mysqlxx::ConnectionLost"; } +}; + + /// Erroneous query. struct BadQuery : public Exception { diff --git a/base/mysqlxx/Pool.cpp b/base/mysqlxx/Pool.cpp index 2cb3e62db84..386b4544b78 100644 --- a/base/mysqlxx/Pool.cpp +++ b/base/mysqlxx/Pool.cpp @@ -10,7 +10,6 @@ #include -#include #include @@ -41,7 +40,9 @@ void Pool::Entry::decrementRefCount() Pool::Pool(const Poco::Util::AbstractConfiguration & cfg, const std::string & config_name, unsigned default_connections_, unsigned max_connections_, const char * parent_config_name_) - : default_connections(default_connections_), max_connections(max_connections_) + : logger(Poco::Logger::get("mysqlxx::Pool")) + , default_connections(default_connections_) + , max_connections(max_connections_) { server = cfg.getString(config_name + ".host"); @@ -78,6 +79,9 @@ Pool::Pool(const Poco::Util::AbstractConfiguration & cfg, const std::string & co enable_local_infile = cfg.getBool(config_name + ".enable_local_infile", cfg.getBool(parent_config_name + ".enable_local_infile", MYSQLXX_DEFAULT_ENABLE_LOCAL_INFILE)); + + opt_reconnect = cfg.getBool(config_name + ".opt_reconnect", + cfg.getBool(parent_config_name + ".opt_reconnect", MYSQLXX_DEFAULT_MYSQL_OPT_RECONNECT)); } else { @@ -96,6 +100,8 @@ Pool::Pool(const Poco::Util::AbstractConfiguration & cfg, const std::string & co enable_local_infile = cfg.getBool( config_name + ".enable_local_infile", MYSQLXX_DEFAULT_ENABLE_LOCAL_INFILE); + + opt_reconnect = cfg.getBool(config_name + ".opt_reconnect", MYSQLXX_DEFAULT_MYSQL_OPT_RECONNECT); } connect_timeout = cfg.getInt(config_name + ".connect_timeout", @@ -125,20 +131,30 @@ Pool::Entry Pool::get() initialize(); for (;;) { + logger.trace("(%s): Iterating through existing MySQL connections", getDescription()); + for (auto & connection : connections) { if (connection->ref_count == 0) return Entry(connection, this); } + logger.trace("(%s): Trying to allocate a new connection.", getDescription()); if (connections.size() < static_cast(max_connections)) { Connection * conn = allocConnection(); if (conn) return Entry(conn, this); + + logger.trace("(%s): Unable to create a new connection: Allocation failed.", getDescription()); + } + else + { + logger.trace("(%s): Unable to create a new connection: Max number of connections has been reached.", getDescription()); } lock.unlock(); + logger.trace("(%s): Sleeping for %d seconds.", getDescription(), MYSQLXX_POOL_SLEEP_ON_CONNECT_FAIL); sleepForSeconds(MYSQLXX_POOL_SLEEP_ON_CONNECT_FAIL); lock.lock(); } @@ -158,12 +174,13 @@ Pool::Entry Pool::tryGet() /// Fixme: There is a race condition here b/c we do not synchronize with Pool::Entry's copy-assignment operator if (connection_ptr->ref_count == 0) { - Entry res(connection_ptr, this); - if (res.tryForceConnected()) /// Tries to reestablish connection as well - return res; + { + Entry res(connection_ptr, this); + if (res.tryForceConnected()) /// Tries to reestablish connection as well + return res; + } - auto & logger = Poco::Util::Application::instance().logger(); - logger.information("Idle connection to mysql server cannot be recovered, dropping it."); + logger.debug("(%s): Idle connection to MySQL server cannot be recovered, dropping it.", getDescription()); /// This one is disconnected, cannot be reestablished and so needs to be disposed of. connection_it = connections.erase(connection_it); @@ -186,6 +203,8 @@ Pool::Entry Pool::tryGet() void Pool::removeConnection(Connection* connection) { + logger.trace("(%s): Removing connection.", getDescription()); + std::lock_guard lock(mutex); if (connection) { @@ -210,8 +229,6 @@ void Pool::Entry::forceConnected() const if (data == nullptr) throw Poco::RuntimeException("Tried to access NULL database connection."); - Poco::Util::Application & app = Poco::Util::Application::instance(); - bool first = true; while (!tryForceConnected()) { @@ -220,7 +237,7 @@ void Pool::Entry::forceConnected() const else sleepForSeconds(MYSQLXX_POOL_SLEEP_ON_CONNECT_FAIL); - app.logger().information("MYSQL: Reconnecting to " + pool->description); + pool->logger.debug("Entry: Reconnecting to MySQL server %s", pool->description); data->conn.connect( pool->db.c_str(), pool->server.c_str(), @@ -233,7 +250,8 @@ void Pool::Entry::forceConnected() const pool->ssl_key.c_str(), pool->connect_timeout, pool->rw_timeout, - pool->enable_local_infile); + pool->enable_local_infile, + pool->opt_reconnect); } } @@ -242,18 +260,22 @@ bool Pool::Entry::tryForceConnected() const { auto * const mysql_driver = data->conn.getDriver(); const auto prev_connection_id = mysql_thread_id(mysql_driver); + + pool->logger.trace("Entry(connection %lu): sending PING to check if it is alive.", prev_connection_id); if (data->conn.ping()) /// Attempts to reestablish lost connection { const auto current_connection_id = mysql_thread_id(mysql_driver); if (prev_connection_id != current_connection_id) { - auto & logger = Poco::Util::Application::instance().logger(); - logger.information("Connection to mysql server has been reestablished. Connection id changed: %lu -> %lu", - prev_connection_id, current_connection_id); + pool->logger.debug("Entry(connection %lu): Reconnected to MySQL server. Connection id changed: %lu -> %lu", + current_connection_id, prev_connection_id, current_connection_id); } + + pool->logger.trace("Entry(connection %lu): PING ok.", current_connection_id); return true; } + pool->logger.trace("Entry(connection %lu): PING failed.", prev_connection_id); return false; } @@ -274,15 +296,13 @@ void Pool::initialize() Pool::Connection * Pool::allocConnection(bool dont_throw_if_failed_first_time) { - Poco::Util::Application & app = Poco::Util::Application::instance(); - - std::unique_ptr conn(new Connection); + std::unique_ptr conn_ptr{new Connection}; try { - app.logger().information("MYSQL: Connecting to " + description); + logger.debug("Connecting to %s", description); - conn->conn.connect( + conn_ptr->conn.connect( db.c_str(), server.c_str(), user.c_str(), @@ -294,29 +314,29 @@ Pool::Connection * Pool::allocConnection(bool dont_throw_if_failed_first_time) ssl_key.c_str(), connect_timeout, rw_timeout, - enable_local_infile); + enable_local_infile, + opt_reconnect); } catch (mysqlxx::ConnectionFailed & e) { + logger.error(e.what()); + if ((!was_successful && !dont_throw_if_failed_first_time) || e.errnum() == ER_ACCESS_DENIED_ERROR || e.errnum() == ER_DBACCESS_DENIED_ERROR || e.errnum() == ER_BAD_DB_ERROR) { - app.logger().error(e.what()); throw; } else { - app.logger().error(e.what()); return nullptr; } } + connections.push_back(conn_ptr.get()); was_successful = true; - auto * connection = conn.release(); - connections.push_back(connection); - return connection; + return conn_ptr.release(); } } diff --git a/base/mysqlxx/Pool.h b/base/mysqlxx/Pool.h index 83b00e0081a..b6189663f55 100644 --- a/base/mysqlxx/Pool.h +++ b/base/mysqlxx/Pool.h @@ -6,6 +6,8 @@ #include #include +#include + #include @@ -165,19 +167,21 @@ public: unsigned rw_timeout_ = MYSQLXX_DEFAULT_RW_TIMEOUT, unsigned default_connections_ = MYSQLXX_POOL_DEFAULT_START_CONNECTIONS, unsigned max_connections_ = MYSQLXX_POOL_DEFAULT_MAX_CONNECTIONS, - unsigned enable_local_infile_ = MYSQLXX_DEFAULT_ENABLE_LOCAL_INFILE) - : default_connections(default_connections_), max_connections(max_connections_), - db(db_), server(server_), user(user_), password(password_), port(port_), socket(socket_), - connect_timeout(connect_timeout_), rw_timeout(rw_timeout_), enable_local_infile(enable_local_infile_) {} + unsigned enable_local_infile_ = MYSQLXX_DEFAULT_ENABLE_LOCAL_INFILE, + bool opt_reconnect_ = MYSQLXX_DEFAULT_MYSQL_OPT_RECONNECT) + : logger(Poco::Logger::get("mysqlxx::Pool")), default_connections(default_connections_), + max_connections(max_connections_), db(db_), server(server_), user(user_), password(password_), port(port_), socket(socket_), + connect_timeout(connect_timeout_), rw_timeout(rw_timeout_), enable_local_infile(enable_local_infile_), + opt_reconnect(opt_reconnect_) {} Pool(const Pool & other) - : default_connections{other.default_connections}, + : logger(other.logger), default_connections{other.default_connections}, max_connections{other.max_connections}, db{other.db}, server{other.server}, user{other.user}, password{other.password}, port{other.port}, socket{other.socket}, connect_timeout{other.connect_timeout}, rw_timeout{other.rw_timeout}, - enable_local_infile{other.enable_local_infile} + enable_local_infile{other.enable_local_infile}, opt_reconnect(other.opt_reconnect) {} Pool & operator=(const Pool &) = delete; @@ -201,6 +205,8 @@ public: void removeConnection(Connection * connection); protected: + Poco::Logger & logger; + /// Number of MySQL connections which are created at launch. unsigned default_connections; /// Maximum possible number of connections @@ -231,6 +237,7 @@ private: std::string ssl_cert; std::string ssl_key; bool enable_local_infile; + bool opt_reconnect; /// True if connection was established at least once. bool was_successful{false}; diff --git a/base/mysqlxx/PoolWithFailover.cpp b/base/mysqlxx/PoolWithFailover.cpp index 5bee75aab1b..5e9f70f4ac1 100644 --- a/base/mysqlxx/PoolWithFailover.cpp +++ b/base/mysqlxx/PoolWithFailover.cpp @@ -1,3 +1,8 @@ +#include +#include +#include +#include + #include @@ -33,6 +38,19 @@ PoolWithFailover::PoolWithFailover(const Poco::Util::AbstractConfiguration & con std::make_shared(config_, replica_name, default_connections_, max_connections_, config_name_.c_str())); } } + + /// PoolWithFailover objects are stored in a cache inside PoolFactory. + /// This cache is reset by ExternalDictionariesLoader after every SYSTEM RELOAD DICTIONAR{Y|IES} + /// which triggers massive re-constructing of connection pools. + /// The state of PRNGs like std::mt19937 is considered to be quite heavy + /// thus here we attempt to optimize its construction. + static thread_local std::mt19937 rnd_generator( + std::hash{}(std::this_thread::get_id()) + std::clock()); + for (auto & [_, replicas] : replicas_by_priority) + { + if (replicas.size() > 1) + std::shuffle(replicas.begin(), replicas.end(), rnd_generator); + } } else { diff --git a/base/mysqlxx/Query.cpp b/base/mysqlxx/Query.cpp index f3485c54edc..d4514c3e988 100644 --- a/base/mysqlxx/Query.cpp +++ b/base/mysqlxx/Query.cpp @@ -1,11 +1,16 @@ #if __has_include() +#include #include #else +#include #include #endif +#include + #include #include +#include namespace mysqlxx @@ -57,8 +62,24 @@ void Query::reset() void Query::executeImpl() { std::string query_string = query_buf.str(); - if (mysql_real_query(conn->getDriver(), query_string.data(), query_string.size())) - throw BadQuery(errorMessage(conn->getDriver()), mysql_errno(conn->getDriver())); + + MYSQL* mysql_driver = conn->getDriver(); + + auto & logger = Poco::Logger::get("mysqlxx::Query"); + logger.trace("Running MySQL query using connection %lu", mysql_thread_id(mysql_driver)); + if (mysql_real_query(mysql_driver, query_string.data(), query_string.size())) + { + const auto err_no = mysql_errno(mysql_driver); + switch (err_no) + { + case CR_SERVER_GONE_ERROR: + [[fallthrough]]; + case CR_SERVER_LOST: + throw ConnectionLost(errorMessage(mysql_driver), err_no); + default: + throw BadQuery(errorMessage(mysql_driver), err_no); + } + } } UseQueryResult Query::use() diff --git a/base/readpassphrase/CMakeLists.txt b/base/readpassphrase/CMakeLists.txt index 574130ce6e3..51b12106eca 100644 --- a/base/readpassphrase/CMakeLists.txt +++ b/base/readpassphrase/CMakeLists.txt @@ -4,5 +4,5 @@ add_library(readpassphrase readpassphrase.c) set_target_properties(readpassphrase PROPERTIES LINKER_LANGUAGE C) -target_compile_options(readpassphrase PRIVATE -Wno-unused-result -Wno-reserved-id-macro) +target_compile_options(readpassphrase PRIVATE -Wno-unused-result -Wno-reserved-id-macro -Wno-disabled-macro-expansion) target_include_directories(readpassphrase PUBLIC .) diff --git a/base/readpassphrase/readpassphrase.c b/base/readpassphrase/readpassphrase.c index 9e8097643bb..8a7d3153915 100644 --- a/base/readpassphrase/readpassphrase.c +++ b/base/readpassphrase/readpassphrase.c @@ -94,7 +94,7 @@ restart: if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { memcpy(&term, &oterm, sizeof(term)); if (!(flags & RPP_ECHO_ON)) - term.c_lflag &= ~(ECHO | ECHONL); + term.c_lflag &= ~((unsigned int) (ECHO | ECHONL)); #ifdef VSTATUS if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) term.c_cc[VSTATUS] = _POSIX_VDISABLE; diff --git a/cmake/autogenerated_versions.txt b/cmake/autogenerated_versions.txt index ce92ae203ea..bd7885bc41b 100644 --- a/cmake/autogenerated_versions.txt +++ b/cmake/autogenerated_versions.txt @@ -1,9 +1,9 @@ # This strings autochanged from release_lib.sh: -SET(VERSION_REVISION 54448) +SET(VERSION_REVISION 54449) SET(VERSION_MAJOR 21) -SET(VERSION_MINOR 3) +SET(VERSION_MINOR 4) SET(VERSION_PATCH 1) -SET(VERSION_GITHASH ef72ba7349f230321750c13ee63b49a11a7c0adc) -SET(VERSION_DESCRIBE v21.3.1.1-prestable) -SET(VERSION_STRING 21.3.1.1) +SET(VERSION_GITHASH af2135ef9dc72f16fa4f229b731262c3f0a8bbdc) +SET(VERSION_DESCRIBE v21.4.1.1-prestable) +SET(VERSION_STRING 21.4.1.1) # end of autochange diff --git a/cmake/find/ccache.cmake b/cmake/find/ccache.cmake index d8e9cf9588d..fea1f8b4c97 100644 --- a/cmake/find/ccache.cmake +++ b/cmake/find/ccache.cmake @@ -32,27 +32,25 @@ if (CCACHE_FOUND AND NOT COMPILER_MATCHES_CCACHE) if (CCACHE_VERSION VERSION_GREATER "3.2.0" OR NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") message(STATUS "Using ${CCACHE_FOUND} ${CCACHE_VERSION}") - # debian (debhlpers) set SOURCE_DATE_EPOCH environment variable, that is + set_property (GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_FOUND}) + set_property (GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_FOUND}) + + # debian (debhelpers) set SOURCE_DATE_EPOCH environment variable, that is # filled from the debian/changelog or current time. # # - 4.0+ ccache always includes this environment variable into the hash # of the manifest, which do not allow to use previous cache, - # - 4.2+ ccache ignores SOURCE_DATE_EPOCH under time_macros sloppiness. + # - 4.2+ ccache ignores SOURCE_DATE_EPOCH for every file w/o __DATE__/__TIME__ # # So for: - # - 4.2+ time_macros sloppiness is used, + # - 4.2+ does not require any sloppiness # - 4.0+ will ignore SOURCE_DATE_EPOCH environment variable. if (CCACHE_VERSION VERSION_GREATER_EQUAL "4.2") - message(STATUS "Use time_macros sloppiness for ccache") - set_property (GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_FOUND} --set-config=sloppiness=time_macros") - set_property (GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE_FOUND} --set-config=sloppiness=time_macros") + message(STATUS "ccache is 4.2+ no quirks for SOURCE_DATE_EPOCH required") elseif (CCACHE_VERSION VERSION_GREATER_EQUAL "4.0") message(STATUS "Ignore SOURCE_DATE_EPOCH for ccache") set_property (GLOBAL PROPERTY RULE_LAUNCH_COMPILE "env -u SOURCE_DATE_EPOCH ${CCACHE_FOUND}") set_property (GLOBAL PROPERTY RULE_LAUNCH_LINK "env -u SOURCE_DATE_EPOCH ${CCACHE_FOUND}") - else() - set_property (GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_FOUND}) - set_property (GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_FOUND}) endif() else () message(${RECONFIGURE_MESSAGE_LEVEL} "Not using ${CCACHE_FOUND} ${CCACHE_VERSION} bug: https://bugzilla.samba.org/show_bug.cgi?id=8118") diff --git a/cmake/find/krb5.cmake b/cmake/find/krb5.cmake index bd9c8e239cd..49b7462b710 100644 --- a/cmake/find/krb5.cmake +++ b/cmake/find/krb5.cmake @@ -5,8 +5,8 @@ if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/krb5/README") set (ENABLE_KRB5 0) endif () -if (NOT CMAKE_SYSTEM_NAME MATCHES "Linux") - message (WARNING "krb5 disabled in non-Linux environments") +if (NOT CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT (CMAKE_SYSTEM_NAME MATCHES "Darwin" AND NOT CMAKE_CROSSCOMPILING)) + message (WARNING "krb5 disabled in non-Linux and non-native-Darwin environments") set (ENABLE_KRB5 0) endif () diff --git a/cmake/find/nuraft.cmake b/cmake/find/nuraft.cmake index d31fe9c1de8..7fa5251946e 100644 --- a/cmake/find/nuraft.cmake +++ b/cmake/find/nuraft.cmake @@ -11,7 +11,7 @@ if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/NuRaft/CMakeLists.txt") return() endif () -if (NOT OS_FREEBSD) +if (NOT OS_FREEBSD AND NOT OS_DARWIN) set (USE_NURAFT 1) set (NURAFT_LIBRARY nuraft) @@ -20,5 +20,5 @@ if (NOT OS_FREEBSD) message (STATUS "Using NuRaft=${USE_NURAFT}: ${NURAFT_INCLUDE_DIR} : ${NURAFT_LIBRARY}") else() set (USE_NURAFT 0) - message (STATUS "Using internal NuRaft library on FreeBSD is not supported") + message (STATUS "Using internal NuRaft library on FreeBSD and Darwin is not supported") endif() diff --git a/cmake/tools.cmake b/cmake/tools.cmake index cc4046d2469..abb11843d59 100644 --- a/cmake/tools.cmake +++ b/cmake/tools.cmake @@ -75,8 +75,13 @@ if (OS_LINUX AND NOT LINKER_NAME) endif () if (LINKER_NAME) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}") + if (COMPILER_CLANG AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12.0.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 12.0.0)) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --ld-path=${LINKER_NAME}") + set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --ld-path=${LINKER_NAME}") + else () + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}") + set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}") + endif () message(STATUS "Using custom linker by name: ${LINKER_NAME}") endif () diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 20b4fad0437..6a56b4cc733 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -32,12 +32,12 @@ endif() set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL 1) +add_subdirectory (abseil-cpp-cmake) add_subdirectory (antlr4-runtime-cmake) add_subdirectory (boost-cmake) add_subdirectory (cctz-cmake) add_subdirectory (consistent-hashing) add_subdirectory (dragonbox-cmake) -add_subdirectory (FastMemcpy) add_subdirectory (hyperscan-cmake) add_subdirectory (jemalloc-cmake) add_subdirectory (libcpuid-cmake) diff --git a/contrib/FastMemcpy/CMakeLists.txt b/contrib/FastMemcpy/CMakeLists.txt deleted file mode 100644 index 8efe6d45dff..00000000000 --- a/contrib/FastMemcpy/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -option (ENABLE_FASTMEMCPY "Enable FastMemcpy library (only internal)" ${ENABLE_LIBRARIES}) - -if (NOT OS_LINUX OR ARCH_AARCH64) - set (ENABLE_FASTMEMCPY OFF) -endif () - -if (ENABLE_FASTMEMCPY) - set (LIBRARY_DIR ${ClickHouse_SOURCE_DIR}/contrib/FastMemcpy) - - set (SRCS - ${LIBRARY_DIR}/FastMemcpy.c - - memcpy_wrapper.c - ) - - add_library (FastMemcpy ${SRCS}) - target_include_directories (FastMemcpy PUBLIC ${LIBRARY_DIR}) - - target_compile_definitions(FastMemcpy PUBLIC USE_FASTMEMCPY=1) - - message (STATUS "Using FastMemcpy") -else () - add_library (FastMemcpy INTERFACE) - - target_compile_definitions(FastMemcpy INTERFACE USE_FASTMEMCPY=0) - - message (STATUS "Not using FastMemcpy") -endif () diff --git a/contrib/FastMemcpy/FastMemcpy.c b/contrib/FastMemcpy/FastMemcpy.c deleted file mode 100644 index 5021bcc7d16..00000000000 --- a/contrib/FastMemcpy/FastMemcpy.c +++ /dev/null @@ -1,220 +0,0 @@ -//===================================================================== -// -// FastMemcpy.c - skywind3000@163.com, 2015 -// -// feature: -// 50% speed up in avg. vs standard memcpy (tested in vc2012/gcc4.9) -// -//===================================================================== -#include -#include -#include -#include - -#if (defined(_WIN32) || defined(WIN32)) -#include -#include -#ifdef _MSC_VER -#pragma comment(lib, "winmm.lib") -#endif -#elif defined(__unix) -#include -#include -#else -#error it can only be compiled under windows or unix -#endif - -#include "FastMemcpy.h" - -unsigned int gettime() -{ - #if (defined(_WIN32) || defined(WIN32)) - return timeGetTime(); - #else - static struct timezone tz={ 0,0 }; - struct timeval time; - gettimeofday(&time,&tz); - return (time.tv_sec * 1000 + time.tv_usec / 1000); - #endif -} - -void sleepms(unsigned int millisec) -{ -#if defined(_WIN32) || defined(WIN32) - Sleep(millisec); -#else - usleep(millisec * 1000); -#endif -} - - -void benchmark(int dstalign, int srcalign, size_t size, int times) -{ - char *DATA1 = (char*)malloc(size + 64); - char *DATA2 = (char*)malloc(size + 64); - size_t LINEAR1 = ((size_t)DATA1); - size_t LINEAR2 = ((size_t)DATA2); - char *ALIGN1 = (char*)(((64 - (LINEAR1 & 63)) & 63) + LINEAR1); - char *ALIGN2 = (char*)(((64 - (LINEAR2 & 63)) & 63) + LINEAR2); - char *dst = (dstalign)? ALIGN1 : (ALIGN1 + 1); - char *src = (srcalign)? ALIGN2 : (ALIGN2 + 3); - unsigned int t1, t2; - int k; - - sleepms(100); - t1 = gettime(); - for (k = times; k > 0; k--) { - memcpy(dst, src, size); - } - t1 = gettime() - t1; - sleepms(100); - t2 = gettime(); - for (k = times; k > 0; k--) { - memcpy_fast(dst, src, size); - } - t2 = gettime() - t2; - - free(DATA1); - free(DATA2); - - printf("result(dst %s, src %s): memcpy_fast=%dms memcpy=%d ms\n", - dstalign? "aligned" : "unalign", - srcalign? "aligned" : "unalign", (int)t2, (int)t1); -} - - -void bench(int copysize, int times) -{ - printf("benchmark(size=%d bytes, times=%d):\n", copysize, times); - benchmark(1, 1, copysize, times); - benchmark(1, 0, copysize, times); - benchmark(0, 1, copysize, times); - benchmark(0, 0, copysize, times); - printf("\n"); -} - - -void random_bench(int maxsize, int times) -{ - static char A[11 * 1024 * 1024 + 2]; - static char B[11 * 1024 * 1024 + 2]; - static int random_offsets[0x10000]; - static int random_sizes[0x8000]; - unsigned int i, p1, p2; - unsigned int t1, t2; - for (i = 0; i < 0x10000; i++) { // generate random offsets - random_offsets[i] = rand() % (10 * 1024 * 1024 + 1); - } - for (i = 0; i < 0x8000; i++) { // generate random sizes - random_sizes[i] = 1 + rand() % maxsize; - } - sleepms(100); - t1 = gettime(); - for (p1 = 0, p2 = 0, i = 0; i < times; i++) { - int offset1 = random_offsets[(p1++) & 0xffff]; - int offset2 = random_offsets[(p1++) & 0xffff]; - int size = random_sizes[(p2++) & 0x7fff]; - memcpy(A + offset1, B + offset2, size); - } - t1 = gettime() - t1; - sleepms(100); - t2 = gettime(); - for (p1 = 0, p2 = 0, i = 0; i < times; i++) { - int offset1 = random_offsets[(p1++) & 0xffff]; - int offset2 = random_offsets[(p1++) & 0xffff]; - int size = random_sizes[(p2++) & 0x7fff]; - memcpy_fast(A + offset1, B + offset2, size); - } - t2 = gettime() - t2; - printf("benchmark random access:\n"); - printf("memcpy_fast=%dms memcpy=%dms\n\n", (int)t2, (int)t1); -} - - -#ifdef _MSC_VER -#pragma comment(lib, "winmm.lib") -#endif - -int main(void) -{ - bench(32, 0x1000000); - bench(64, 0x1000000); - bench(512, 0x800000); - bench(1024, 0x400000); - bench(4096, 0x80000); - bench(8192, 0x40000); - bench(1024 * 1024 * 1, 0x800); - bench(1024 * 1024 * 4, 0x200); - bench(1024 * 1024 * 8, 0x100); - - random_bench(2048, 8000000); - - return 0; -} - - - - -/* -benchmark(size=32 bytes, times=16777216): -result(dst aligned, src aligned): memcpy_fast=78ms memcpy=260 ms -result(dst aligned, src unalign): memcpy_fast=78ms memcpy=250 ms -result(dst unalign, src aligned): memcpy_fast=78ms memcpy=266 ms -result(dst unalign, src unalign): memcpy_fast=78ms memcpy=234 ms - -benchmark(size=64 bytes, times=16777216): -result(dst aligned, src aligned): memcpy_fast=109ms memcpy=281 ms -result(dst aligned, src unalign): memcpy_fast=109ms memcpy=328 ms -result(dst unalign, src aligned): memcpy_fast=109ms memcpy=343 ms -result(dst unalign, src unalign): memcpy_fast=93ms memcpy=344 ms - -benchmark(size=512 bytes, times=8388608): -result(dst aligned, src aligned): memcpy_fast=125ms memcpy=218 ms -result(dst aligned, src unalign): memcpy_fast=156ms memcpy=484 ms -result(dst unalign, src aligned): memcpy_fast=172ms memcpy=546 ms -result(dst unalign, src unalign): memcpy_fast=172ms memcpy=515 ms - -benchmark(size=1024 bytes, times=4194304): -result(dst aligned, src aligned): memcpy_fast=109ms memcpy=172 ms -result(dst aligned, src unalign): memcpy_fast=187ms memcpy=453 ms -result(dst unalign, src aligned): memcpy_fast=172ms memcpy=437 ms -result(dst unalign, src unalign): memcpy_fast=156ms memcpy=452 ms - -benchmark(size=4096 bytes, times=524288): -result(dst aligned, src aligned): memcpy_fast=62ms memcpy=78 ms -result(dst aligned, src unalign): memcpy_fast=109ms memcpy=202 ms -result(dst unalign, src aligned): memcpy_fast=94ms memcpy=203 ms -result(dst unalign, src unalign): memcpy_fast=110ms memcpy=218 ms - -benchmark(size=8192 bytes, times=262144): -result(dst aligned, src aligned): memcpy_fast=62ms memcpy=78 ms -result(dst aligned, src unalign): memcpy_fast=78ms memcpy=202 ms -result(dst unalign, src aligned): memcpy_fast=78ms memcpy=203 ms -result(dst unalign, src unalign): memcpy_fast=94ms memcpy=203 ms - -benchmark(size=1048576 bytes, times=2048): -result(dst aligned, src aligned): memcpy_fast=203ms memcpy=191 ms -result(dst aligned, src unalign): memcpy_fast=219ms memcpy=281 ms -result(dst unalign, src aligned): memcpy_fast=218ms memcpy=328 ms -result(dst unalign, src unalign): memcpy_fast=218ms memcpy=312 ms - -benchmark(size=4194304 bytes, times=512): -result(dst aligned, src aligned): memcpy_fast=312ms memcpy=406 ms -result(dst aligned, src unalign): memcpy_fast=296ms memcpy=421 ms -result(dst unalign, src aligned): memcpy_fast=312ms memcpy=468 ms -result(dst unalign, src unalign): memcpy_fast=297ms memcpy=452 ms - -benchmark(size=8388608 bytes, times=256): -result(dst aligned, src aligned): memcpy_fast=281ms memcpy=452 ms -result(dst aligned, src unalign): memcpy_fast=280ms memcpy=468 ms -result(dst unalign, src aligned): memcpy_fast=298ms memcpy=514 ms -result(dst unalign, src unalign): memcpy_fast=344ms memcpy=472 ms - -benchmark random access: -memcpy_fast=515ms memcpy=1014ms - -*/ - - - - diff --git a/contrib/FastMemcpy/FastMemcpy.h b/contrib/FastMemcpy/FastMemcpy.h deleted file mode 100644 index 5dcbfcf1656..00000000000 --- a/contrib/FastMemcpy/FastMemcpy.h +++ /dev/null @@ -1,694 +0,0 @@ -//===================================================================== -// -// FastMemcpy.c - skywind3000@163.com, 2015 -// -// feature: -// 50% speed up in avg. vs standard memcpy (tested in vc2012/gcc5.1) -// -//===================================================================== -#ifndef __FAST_MEMCPY_H__ -#define __FAST_MEMCPY_H__ - -#include -#include -#include - - -//--------------------------------------------------------------------- -// force inline for compilers -//--------------------------------------------------------------------- -#ifndef INLINE -#ifdef __GNUC__ -#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) - #define INLINE __inline__ __attribute__((always_inline)) -#else - #define INLINE __inline__ -#endif -#elif defined(_MSC_VER) - #define INLINE __forceinline -#elif (defined(__BORLANDC__) || defined(__WATCOMC__)) - #define INLINE __inline -#else - #define INLINE -#endif -#endif - -typedef __attribute__((__aligned__(1))) uint16_t uint16_unaligned_t; -typedef __attribute__((__aligned__(1))) uint32_t uint32_unaligned_t; -typedef __attribute__((__aligned__(1))) uint64_t uint64_unaligned_t; - -//--------------------------------------------------------------------- -// fast copy for different sizes -//--------------------------------------------------------------------- -static INLINE void memcpy_sse2_16(void *dst, const void *src) { - __m128i m0 = _mm_loadu_si128(((const __m128i*)src) + 0); - _mm_storeu_si128(((__m128i*)dst) + 0, m0); -} - -static INLINE void memcpy_sse2_32(void *dst, const void *src) { - __m128i m0 = _mm_loadu_si128(((const __m128i*)src) + 0); - __m128i m1 = _mm_loadu_si128(((const __m128i*)src) + 1); - _mm_storeu_si128(((__m128i*)dst) + 0, m0); - _mm_storeu_si128(((__m128i*)dst) + 1, m1); -} - -static INLINE void memcpy_sse2_64(void *dst, const void *src) { - __m128i m0 = _mm_loadu_si128(((const __m128i*)src) + 0); - __m128i m1 = _mm_loadu_si128(((const __m128i*)src) + 1); - __m128i m2 = _mm_loadu_si128(((const __m128i*)src) + 2); - __m128i m3 = _mm_loadu_si128(((const __m128i*)src) + 3); - _mm_storeu_si128(((__m128i*)dst) + 0, m0); - _mm_storeu_si128(((__m128i*)dst) + 1, m1); - _mm_storeu_si128(((__m128i*)dst) + 2, m2); - _mm_storeu_si128(((__m128i*)dst) + 3, m3); -} - -static INLINE void memcpy_sse2_128(void *dst, const void *src) { - __m128i m0 = _mm_loadu_si128(((const __m128i*)src) + 0); - __m128i m1 = _mm_loadu_si128(((const __m128i*)src) + 1); - __m128i m2 = _mm_loadu_si128(((const __m128i*)src) + 2); - __m128i m3 = _mm_loadu_si128(((const __m128i*)src) + 3); - __m128i m4 = _mm_loadu_si128(((const __m128i*)src) + 4); - __m128i m5 = _mm_loadu_si128(((const __m128i*)src) + 5); - __m128i m6 = _mm_loadu_si128(((const __m128i*)src) + 6); - __m128i m7 = _mm_loadu_si128(((const __m128i*)src) + 7); - _mm_storeu_si128(((__m128i*)dst) + 0, m0); - _mm_storeu_si128(((__m128i*)dst) + 1, m1); - _mm_storeu_si128(((__m128i*)dst) + 2, m2); - _mm_storeu_si128(((__m128i*)dst) + 3, m3); - _mm_storeu_si128(((__m128i*)dst) + 4, m4); - _mm_storeu_si128(((__m128i*)dst) + 5, m5); - _mm_storeu_si128(((__m128i*)dst) + 6, m6); - _mm_storeu_si128(((__m128i*)dst) + 7, m7); -} - - -//--------------------------------------------------------------------- -// tiny memory copy with jump table optimized -//--------------------------------------------------------------------- -/// Attribute is used to avoid an error with undefined behaviour sanitizer -/// ../contrib/FastMemcpy/FastMemcpy.h:91:56: runtime error: applying zero offset to null pointer -/// Found by 01307_orc_output_format.sh, cause - ORCBlockInputFormat and external ORC library. -__attribute__((__no_sanitize__("undefined"))) static INLINE void *memcpy_tiny(void *dst, const void *src, size_t size) { - unsigned char *dd = ((unsigned char*)dst) + size; - const unsigned char *ss = ((const unsigned char*)src) + size; - - switch (size) { - case 64: - memcpy_sse2_64(dd - 64, ss - 64); - case 0: - break; - - case 65: - memcpy_sse2_64(dd - 65, ss - 65); - case 1: - dd[-1] = ss[-1]; - break; - - case 66: - memcpy_sse2_64(dd - 66, ss - 66); - case 2: - *((uint16_unaligned_t*)(dd - 2)) = *((uint16_unaligned_t*)(ss - 2)); - break; - - case 67: - memcpy_sse2_64(dd - 67, ss - 67); - case 3: - *((uint16_unaligned_t*)(dd - 3)) = *((uint16_unaligned_t*)(ss - 3)); - dd[-1] = ss[-1]; - break; - - case 68: - memcpy_sse2_64(dd - 68, ss - 68); - case 4: - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 69: - memcpy_sse2_64(dd - 69, ss - 69); - case 5: - *((uint32_unaligned_t*)(dd - 5)) = *((uint32_unaligned_t*)(ss - 5)); - dd[-1] = ss[-1]; - break; - - case 70: - memcpy_sse2_64(dd - 70, ss - 70); - case 6: - *((uint32_unaligned_t*)(dd - 6)) = *((uint32_unaligned_t*)(ss - 6)); - *((uint16_unaligned_t*)(dd - 2)) = *((uint16_unaligned_t*)(ss - 2)); - break; - - case 71: - memcpy_sse2_64(dd - 71, ss - 71); - case 7: - *((uint32_unaligned_t*)(dd - 7)) = *((uint32_unaligned_t*)(ss - 7)); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 72: - memcpy_sse2_64(dd - 72, ss - 72); - case 8: - *((uint64_unaligned_t*)(dd - 8)) = *((uint64_unaligned_t*)(ss - 8)); - break; - - case 73: - memcpy_sse2_64(dd - 73, ss - 73); - case 9: - *((uint64_unaligned_t*)(dd - 9)) = *((uint64_unaligned_t*)(ss - 9)); - dd[-1] = ss[-1]; - break; - - case 74: - memcpy_sse2_64(dd - 74, ss - 74); - case 10: - *((uint64_unaligned_t*)(dd - 10)) = *((uint64_unaligned_t*)(ss - 10)); - *((uint16_unaligned_t*)(dd - 2)) = *((uint16_unaligned_t*)(ss - 2)); - break; - - case 75: - memcpy_sse2_64(dd - 75, ss - 75); - case 11: - *((uint64_unaligned_t*)(dd - 11)) = *((uint64_unaligned_t*)(ss - 11)); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 76: - memcpy_sse2_64(dd - 76, ss - 76); - case 12: - *((uint64_unaligned_t*)(dd - 12)) = *((uint64_unaligned_t*)(ss - 12)); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 77: - memcpy_sse2_64(dd - 77, ss - 77); - case 13: - *((uint64_unaligned_t*)(dd - 13)) = *((uint64_unaligned_t*)(ss - 13)); - *((uint32_unaligned_t*)(dd - 5)) = *((uint32_unaligned_t*)(ss - 5)); - dd[-1] = ss[-1]; - break; - - case 78: - memcpy_sse2_64(dd - 78, ss - 78); - case 14: - *((uint64_unaligned_t*)(dd - 14)) = *((uint64_unaligned_t*)(ss - 14)); - *((uint64_unaligned_t*)(dd - 8)) = *((uint64_unaligned_t*)(ss - 8)); - break; - - case 79: - memcpy_sse2_64(dd - 79, ss - 79); - case 15: - *((uint64_unaligned_t*)(dd - 15)) = *((uint64_unaligned_t*)(ss - 15)); - *((uint64_unaligned_t*)(dd - 8)) = *((uint64_unaligned_t*)(ss - 8)); - break; - - case 80: - memcpy_sse2_64(dd - 80, ss - 80); - case 16: - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 81: - memcpy_sse2_64(dd - 81, ss - 81); - case 17: - memcpy_sse2_16(dd - 17, ss - 17); - dd[-1] = ss[-1]; - break; - - case 82: - memcpy_sse2_64(dd - 82, ss - 82); - case 18: - memcpy_sse2_16(dd - 18, ss - 18); - *((uint16_unaligned_t*)(dd - 2)) = *((uint16_unaligned_t*)(ss - 2)); - break; - - case 83: - memcpy_sse2_64(dd - 83, ss - 83); - case 19: - memcpy_sse2_16(dd - 19, ss - 19); - *((uint16_unaligned_t*)(dd - 3)) = *((uint16_unaligned_t*)(ss - 3)); - dd[-1] = ss[-1]; - break; - - case 84: - memcpy_sse2_64(dd - 84, ss - 84); - case 20: - memcpy_sse2_16(dd - 20, ss - 20); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 85: - memcpy_sse2_64(dd - 85, ss - 85); - case 21: - memcpy_sse2_16(dd - 21, ss - 21); - *((uint32_unaligned_t*)(dd - 5)) = *((uint32_unaligned_t*)(ss - 5)); - dd[-1] = ss[-1]; - break; - - case 86: - memcpy_sse2_64(dd - 86, ss - 86); - case 22: - memcpy_sse2_16(dd - 22, ss - 22); - *((uint32_unaligned_t*)(dd - 6)) = *((uint32_unaligned_t*)(ss - 6)); - *((uint16_unaligned_t*)(dd - 2)) = *((uint16_unaligned_t*)(ss - 2)); - break; - - case 87: - memcpy_sse2_64(dd - 87, ss - 87); - case 23: - memcpy_sse2_16(dd - 23, ss - 23); - *((uint32_unaligned_t*)(dd - 7)) = *((uint32_unaligned_t*)(ss - 7)); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 88: - memcpy_sse2_64(dd - 88, ss - 88); - case 24: - memcpy_sse2_16(dd - 24, ss - 24); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 89: - memcpy_sse2_64(dd - 89, ss - 89); - case 25: - memcpy_sse2_16(dd - 25, ss - 25); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 90: - memcpy_sse2_64(dd - 90, ss - 90); - case 26: - memcpy_sse2_16(dd - 26, ss - 26); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 91: - memcpy_sse2_64(dd - 91, ss - 91); - case 27: - memcpy_sse2_16(dd - 27, ss - 27); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 92: - memcpy_sse2_64(dd - 92, ss - 92); - case 28: - memcpy_sse2_16(dd - 28, ss - 28); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 93: - memcpy_sse2_64(dd - 93, ss - 93); - case 29: - memcpy_sse2_16(dd - 29, ss - 29); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 94: - memcpy_sse2_64(dd - 94, ss - 94); - case 30: - memcpy_sse2_16(dd - 30, ss - 30); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 95: - memcpy_sse2_64(dd - 95, ss - 95); - case 31: - memcpy_sse2_16(dd - 31, ss - 31); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 96: - memcpy_sse2_64(dd - 96, ss - 96); - case 32: - memcpy_sse2_32(dd - 32, ss - 32); - break; - - case 97: - memcpy_sse2_64(dd - 97, ss - 97); - case 33: - memcpy_sse2_32(dd - 33, ss - 33); - dd[-1] = ss[-1]; - break; - - case 98: - memcpy_sse2_64(dd - 98, ss - 98); - case 34: - memcpy_sse2_32(dd - 34, ss - 34); - *((uint16_unaligned_t*)(dd - 2)) = *((uint16_unaligned_t*)(ss - 2)); - break; - - case 99: - memcpy_sse2_64(dd - 99, ss - 99); - case 35: - memcpy_sse2_32(dd - 35, ss - 35); - *((uint16_unaligned_t*)(dd - 3)) = *((uint16_unaligned_t*)(ss - 3)); - dd[-1] = ss[-1]; - break; - - case 100: - memcpy_sse2_64(dd - 100, ss - 100); - case 36: - memcpy_sse2_32(dd - 36, ss - 36); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 101: - memcpy_sse2_64(dd - 101, ss - 101); - case 37: - memcpy_sse2_32(dd - 37, ss - 37); - *((uint32_unaligned_t*)(dd - 5)) = *((uint32_unaligned_t*)(ss - 5)); - dd[-1] = ss[-1]; - break; - - case 102: - memcpy_sse2_64(dd - 102, ss - 102); - case 38: - memcpy_sse2_32(dd - 38, ss - 38); - *((uint32_unaligned_t*)(dd - 6)) = *((uint32_unaligned_t*)(ss - 6)); - *((uint16_unaligned_t*)(dd - 2)) = *((uint16_unaligned_t*)(ss - 2)); - break; - - case 103: - memcpy_sse2_64(dd - 103, ss - 103); - case 39: - memcpy_sse2_32(dd - 39, ss - 39); - *((uint32_unaligned_t*)(dd - 7)) = *((uint32_unaligned_t*)(ss - 7)); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 104: - memcpy_sse2_64(dd - 104, ss - 104); - case 40: - memcpy_sse2_32(dd - 40, ss - 40); - *((uint64_unaligned_t*)(dd - 8)) = *((uint64_unaligned_t*)(ss - 8)); - break; - - case 105: - memcpy_sse2_64(dd - 105, ss - 105); - case 41: - memcpy_sse2_32(dd - 41, ss - 41); - *((uint64_unaligned_t*)(dd - 9)) = *((uint64_unaligned_t*)(ss - 9)); - dd[-1] = ss[-1]; - break; - - case 106: - memcpy_sse2_64(dd - 106, ss - 106); - case 42: - memcpy_sse2_32(dd - 42, ss - 42); - *((uint64_unaligned_t*)(dd - 10)) = *((uint64_unaligned_t*)(ss - 10)); - *((uint16_unaligned_t*)(dd - 2)) = *((uint16_unaligned_t*)(ss - 2)); - break; - - case 107: - memcpy_sse2_64(dd - 107, ss - 107); - case 43: - memcpy_sse2_32(dd - 43, ss - 43); - *((uint64_unaligned_t*)(dd - 11)) = *((uint64_unaligned_t*)(ss - 11)); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 108: - memcpy_sse2_64(dd - 108, ss - 108); - case 44: - memcpy_sse2_32(dd - 44, ss - 44); - *((uint64_unaligned_t*)(dd - 12)) = *((uint64_unaligned_t*)(ss - 12)); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 109: - memcpy_sse2_64(dd - 109, ss - 109); - case 45: - memcpy_sse2_32(dd - 45, ss - 45); - *((uint64_unaligned_t*)(dd - 13)) = *((uint64_unaligned_t*)(ss - 13)); - *((uint32_unaligned_t*)(dd - 5)) = *((uint32_unaligned_t*)(ss - 5)); - dd[-1] = ss[-1]; - break; - - case 110: - memcpy_sse2_64(dd - 110, ss - 110); - case 46: - memcpy_sse2_32(dd - 46, ss - 46); - *((uint64_unaligned_t*)(dd - 14)) = *((uint64_unaligned_t*)(ss - 14)); - *((uint64_unaligned_t*)(dd - 8)) = *((uint64_unaligned_t*)(ss - 8)); - break; - - case 111: - memcpy_sse2_64(dd - 111, ss - 111); - case 47: - memcpy_sse2_32(dd - 47, ss - 47); - *((uint64_unaligned_t*)(dd - 15)) = *((uint64_unaligned_t*)(ss - 15)); - *((uint64_unaligned_t*)(dd - 8)) = *((uint64_unaligned_t*)(ss - 8)); - break; - - case 112: - memcpy_sse2_64(dd - 112, ss - 112); - case 48: - memcpy_sse2_32(dd - 48, ss - 48); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 113: - memcpy_sse2_64(dd - 113, ss - 113); - case 49: - memcpy_sse2_32(dd - 49, ss - 49); - memcpy_sse2_16(dd - 17, ss - 17); - dd[-1] = ss[-1]; - break; - - case 114: - memcpy_sse2_64(dd - 114, ss - 114); - case 50: - memcpy_sse2_32(dd - 50, ss - 50); - memcpy_sse2_16(dd - 18, ss - 18); - *((uint16_unaligned_t*)(dd - 2)) = *((uint16_unaligned_t*)(ss - 2)); - break; - - case 115: - memcpy_sse2_64(dd - 115, ss - 115); - case 51: - memcpy_sse2_32(dd - 51, ss - 51); - memcpy_sse2_16(dd - 19, ss - 19); - *((uint16_unaligned_t*)(dd - 3)) = *((uint16_unaligned_t*)(ss - 3)); - dd[-1] = ss[-1]; - break; - - case 116: - memcpy_sse2_64(dd - 116, ss - 116); - case 52: - memcpy_sse2_32(dd - 52, ss - 52); - memcpy_sse2_16(dd - 20, ss - 20); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 117: - memcpy_sse2_64(dd - 117, ss - 117); - case 53: - memcpy_sse2_32(dd - 53, ss - 53); - memcpy_sse2_16(dd - 21, ss - 21); - *((uint32_unaligned_t*)(dd - 5)) = *((uint32_unaligned_t*)(ss - 5)); - dd[-1] = ss[-1]; - break; - - case 118: - memcpy_sse2_64(dd - 118, ss - 118); - case 54: - memcpy_sse2_32(dd - 54, ss - 54); - memcpy_sse2_16(dd - 22, ss - 22); - *((uint32_unaligned_t*)(dd - 6)) = *((uint32_unaligned_t*)(ss - 6)); - *((uint16_unaligned_t*)(dd - 2)) = *((uint16_unaligned_t*)(ss - 2)); - break; - - case 119: - memcpy_sse2_64(dd - 119, ss - 119); - case 55: - memcpy_sse2_32(dd - 55, ss - 55); - memcpy_sse2_16(dd - 23, ss - 23); - *((uint32_unaligned_t*)(dd - 7)) = *((uint32_unaligned_t*)(ss - 7)); - *((uint32_unaligned_t*)(dd - 4)) = *((uint32_unaligned_t*)(ss - 4)); - break; - - case 120: - memcpy_sse2_64(dd - 120, ss - 120); - case 56: - memcpy_sse2_32(dd - 56, ss - 56); - memcpy_sse2_16(dd - 24, ss - 24); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 121: - memcpy_sse2_64(dd - 121, ss - 121); - case 57: - memcpy_sse2_32(dd - 57, ss - 57); - memcpy_sse2_16(dd - 25, ss - 25); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 122: - memcpy_sse2_64(dd - 122, ss - 122); - case 58: - memcpy_sse2_32(dd - 58, ss - 58); - memcpy_sse2_16(dd - 26, ss - 26); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 123: - memcpy_sse2_64(dd - 123, ss - 123); - case 59: - memcpy_sse2_32(dd - 59, ss - 59); - memcpy_sse2_16(dd - 27, ss - 27); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 124: - memcpy_sse2_64(dd - 124, ss - 124); - case 60: - memcpy_sse2_32(dd - 60, ss - 60); - memcpy_sse2_16(dd - 28, ss - 28); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 125: - memcpy_sse2_64(dd - 125, ss - 125); - case 61: - memcpy_sse2_32(dd - 61, ss - 61); - memcpy_sse2_16(dd - 29, ss - 29); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 126: - memcpy_sse2_64(dd - 126, ss - 126); - case 62: - memcpy_sse2_32(dd - 62, ss - 62); - memcpy_sse2_16(dd - 30, ss - 30); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 127: - memcpy_sse2_64(dd - 127, ss - 127); - case 63: - memcpy_sse2_32(dd - 63, ss - 63); - memcpy_sse2_16(dd - 31, ss - 31); - memcpy_sse2_16(dd - 16, ss - 16); - break; - - case 128: - memcpy_sse2_128(dd - 128, ss - 128); - break; - } - - return dst; -} - - -//--------------------------------------------------------------------- -// main routine -//--------------------------------------------------------------------- -static void* memcpy_fast(void *destination, const void *source, size_t size) -{ - unsigned char *dst = (unsigned char*)destination; - const unsigned char *src = (const unsigned char*)source; - static size_t cachesize = 0x200000; // L2-cache size - size_t padding; - - // small memory copy - if (size <= 128) { - return memcpy_tiny(dst, src, size); - } - - // align destination to 16 bytes boundary - padding = (16 - (((size_t)dst) & 15)) & 15; - - if (padding > 0) { - __m128i head = _mm_loadu_si128((const __m128i*)src); - _mm_storeu_si128((__m128i*)dst, head); - dst += padding; - src += padding; - size -= padding; - } - - // medium size copy - if (size <= cachesize) { - __m128i c0, c1, c2, c3, c4, c5, c6, c7; - - for (; size >= 128; size -= 128) { - c0 = _mm_loadu_si128(((const __m128i*)src) + 0); - c1 = _mm_loadu_si128(((const __m128i*)src) + 1); - c2 = _mm_loadu_si128(((const __m128i*)src) + 2); - c3 = _mm_loadu_si128(((const __m128i*)src) + 3); - c4 = _mm_loadu_si128(((const __m128i*)src) + 4); - c5 = _mm_loadu_si128(((const __m128i*)src) + 5); - c6 = _mm_loadu_si128(((const __m128i*)src) + 6); - c7 = _mm_loadu_si128(((const __m128i*)src) + 7); - _mm_prefetch((const char*)(src + 256), _MM_HINT_NTA); - src += 128; - _mm_store_si128((((__m128i*)dst) + 0), c0); - _mm_store_si128((((__m128i*)dst) + 1), c1); - _mm_store_si128((((__m128i*)dst) + 2), c2); - _mm_store_si128((((__m128i*)dst) + 3), c3); - _mm_store_si128((((__m128i*)dst) + 4), c4); - _mm_store_si128((((__m128i*)dst) + 5), c5); - _mm_store_si128((((__m128i*)dst) + 6), c6); - _mm_store_si128((((__m128i*)dst) + 7), c7); - dst += 128; - } - } - else { // big memory copy - __m128i c0, c1, c2, c3, c4, c5, c6, c7; - - _mm_prefetch((const char*)(src), _MM_HINT_NTA); - - if ((((size_t)src) & 15) == 0) { // source aligned - for (; size >= 128; size -= 128) { - c0 = _mm_load_si128(((const __m128i*)src) + 0); - c1 = _mm_load_si128(((const __m128i*)src) + 1); - c2 = _mm_load_si128(((const __m128i*)src) + 2); - c3 = _mm_load_si128(((const __m128i*)src) + 3); - c4 = _mm_load_si128(((const __m128i*)src) + 4); - c5 = _mm_load_si128(((const __m128i*)src) + 5); - c6 = _mm_load_si128(((const __m128i*)src) + 6); - c7 = _mm_load_si128(((const __m128i*)src) + 7); - _mm_prefetch((const char*)(src + 256), _MM_HINT_NTA); - src += 128; - _mm_stream_si128((((__m128i*)dst) + 0), c0); - _mm_stream_si128((((__m128i*)dst) + 1), c1); - _mm_stream_si128((((__m128i*)dst) + 2), c2); - _mm_stream_si128((((__m128i*)dst) + 3), c3); - _mm_stream_si128((((__m128i*)dst) + 4), c4); - _mm_stream_si128((((__m128i*)dst) + 5), c5); - _mm_stream_si128((((__m128i*)dst) + 6), c6); - _mm_stream_si128((((__m128i*)dst) + 7), c7); - dst += 128; - } - } - else { // source unaligned - for (; size >= 128; size -= 128) { - c0 = _mm_loadu_si128(((const __m128i*)src) + 0); - c1 = _mm_loadu_si128(((const __m128i*)src) + 1); - c2 = _mm_loadu_si128(((const __m128i*)src) + 2); - c3 = _mm_loadu_si128(((const __m128i*)src) + 3); - c4 = _mm_loadu_si128(((const __m128i*)src) + 4); - c5 = _mm_loadu_si128(((const __m128i*)src) + 5); - c6 = _mm_loadu_si128(((const __m128i*)src) + 6); - c7 = _mm_loadu_si128(((const __m128i*)src) + 7); - _mm_prefetch((const char*)(src + 256), _MM_HINT_NTA); - src += 128; - _mm_stream_si128((((__m128i*)dst) + 0), c0); - _mm_stream_si128((((__m128i*)dst) + 1), c1); - _mm_stream_si128((((__m128i*)dst) + 2), c2); - _mm_stream_si128((((__m128i*)dst) + 3), c3); - _mm_stream_si128((((__m128i*)dst) + 4), c4); - _mm_stream_si128((((__m128i*)dst) + 5), c5); - _mm_stream_si128((((__m128i*)dst) + 6), c6); - _mm_stream_si128((((__m128i*)dst) + 7), c7); - dst += 128; - } - } - _mm_sfence(); - } - - memcpy_tiny(dst, src, size); - - return destination; -} - - -#endif diff --git a/contrib/FastMemcpy/FastMemcpy_Avx.c b/contrib/FastMemcpy/FastMemcpy_Avx.c deleted file mode 100644 index 6538c6b2126..00000000000 --- a/contrib/FastMemcpy/FastMemcpy_Avx.c +++ /dev/null @@ -1,171 +0,0 @@ -//===================================================================== -// -// FastMemcpy.c - skywind3000@163.com, 2015 -// -// feature: -// 50% speed up in avg. vs standard memcpy (tested in vc2012/gcc4.9) -// -//===================================================================== -#include -#include -#include -#include -#include - -#if (defined(_WIN32) || defined(WIN32)) -#include -#include -#ifdef _MSC_VER -#pragma comment(lib, "winmm.lib") -#endif -#elif defined(__unix) -#include -#include -#else -#error it can only be compiled under windows or unix -#endif - -#include "FastMemcpy_Avx.h" - - -unsigned int gettime() -{ - #if (defined(_WIN32) || defined(WIN32)) - return timeGetTime(); - #else - static struct timezone tz={ 0,0 }; - struct timeval time; - gettimeofday(&time,&tz); - return (time.tv_sec * 1000 + time.tv_usec / 1000); - #endif -} - -void sleepms(unsigned int millisec) -{ -#if defined(_WIN32) || defined(WIN32) - Sleep(millisec); -#else - usleep(millisec * 1000); -#endif -} - - - -void benchmark(int dstalign, int srcalign, size_t size, int times) -{ - char *DATA1 = (char*)malloc(size + 64); - char *DATA2 = (char*)malloc(size + 64); - size_t LINEAR1 = ((size_t)DATA1); - size_t LINEAR2 = ((size_t)DATA2); - char *ALIGN1 = (char*)(((64 - (LINEAR1 & 63)) & 63) + LINEAR1); - char *ALIGN2 = (char*)(((64 - (LINEAR2 & 63)) & 63) + LINEAR2); - char *dst = (dstalign)? ALIGN1 : (ALIGN1 + 1); - char *src = (srcalign)? ALIGN2 : (ALIGN2 + 3); - unsigned int t1, t2; - int k; - - sleepms(100); - t1 = gettime(); - for (k = times; k > 0; k--) { - memcpy(dst, src, size); - } - t1 = gettime() - t1; - sleepms(100); - t2 = gettime(); - for (k = times; k > 0; k--) { - memcpy_fast(dst, src, size); - } - t2 = gettime() - t2; - - free(DATA1); - free(DATA2); - - printf("result(dst %s, src %s): memcpy_fast=%dms memcpy=%d ms\n", - dstalign? "aligned" : "unalign", - srcalign? "aligned" : "unalign", (int)t2, (int)t1); -} - - -void bench(int copysize, int times) -{ - printf("benchmark(size=%d bytes, times=%d):\n", copysize, times); - benchmark(1, 1, copysize, times); - benchmark(1, 0, copysize, times); - benchmark(0, 1, copysize, times); - benchmark(0, 0, copysize, times); - printf("\n"); -} - - -void random_bench(int maxsize, int times) -{ - static char A[11 * 1024 * 1024 + 2]; - static char B[11 * 1024 * 1024 + 2]; - static int random_offsets[0x10000]; - static int random_sizes[0x8000]; - unsigned int i, p1, p2; - unsigned int t1, t2; - for (i = 0; i < 0x10000; i++) { // generate random offsets - random_offsets[i] = rand() % (10 * 1024 * 1024 + 1); - } - for (i = 0; i < 0x8000; i++) { // generate random sizes - random_sizes[i] = 1 + rand() % maxsize; - } - sleepms(100); - t1 = gettime(); - for (p1 = 0, p2 = 0, i = 0; i < times; i++) { - int offset1 = random_offsets[(p1++) & 0xffff]; - int offset2 = random_offsets[(p1++) & 0xffff]; - int size = random_sizes[(p2++) & 0x7fff]; - memcpy(A + offset1, B + offset2, size); - } - t1 = gettime() - t1; - sleepms(100); - t2 = gettime(); - for (p1 = 0, p2 = 0, i = 0; i < times; i++) { - int offset1 = random_offsets[(p1++) & 0xffff]; - int offset2 = random_offsets[(p1++) & 0xffff]; - int size = random_sizes[(p2++) & 0x7fff]; - memcpy_fast(A + offset1, B + offset2, size); - } - t2 = gettime() - t2; - printf("benchmark random access:\n"); - printf("memcpy_fast=%dms memcpy=%dms\n\n", (int)t2, (int)t1); -} - - -#ifdef _MSC_VER -#pragma comment(lib, "winmm.lib") -#endif - -int main(void) -{ -#if 1 - bench(32, 0x1000000); - bench(64, 0x1000000); - bench(512, 0x800000); - bench(1024, 0x400000); -#endif - bench(4096, 0x80000); - bench(8192, 0x40000); -#if 1 - bench(1024 * 1024 * 1, 0x800); - bench(1024 * 1024 * 4, 0x200); -#endif - bench(1024 * 1024 * 8, 0x100); - - random_bench(2048, 8000000); - - return 0; -} - - - - -/* - -*/ - - - - diff --git a/contrib/FastMemcpy/FastMemcpy_Avx.h b/contrib/FastMemcpy/FastMemcpy_Avx.h deleted file mode 100644 index 8ba064b0350..00000000000 --- a/contrib/FastMemcpy/FastMemcpy_Avx.h +++ /dev/null @@ -1,492 +0,0 @@ -//===================================================================== -// -// FastMemcpy.c - skywind3000@163.com, 2015 -// -// feature: -// 50% speed up in avg. vs standard memcpy (tested in vc2012/gcc5.1) -// -//===================================================================== -#ifndef __FAST_MEMCPY_H__ -#define __FAST_MEMCPY_H__ - -#include -#include -#include - - -//--------------------------------------------------------------------- -// force inline for compilers -//--------------------------------------------------------------------- -#ifndef INLINE -#ifdef __GNUC__ -#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) - #define INLINE __inline__ __attribute__((always_inline)) -#else - #define INLINE __inline__ -#endif -#elif defined(_MSC_VER) - #define INLINE __forceinline -#elif (defined(__BORLANDC__) || defined(__WATCOMC__)) - #define INLINE __inline -#else - #define INLINE -#endif -#endif - - - -//--------------------------------------------------------------------- -// fast copy for different sizes -//--------------------------------------------------------------------- -static INLINE void memcpy_avx_16(void *dst, const void *src) { -#if 1 - __m128i m0 = _mm_loadu_si128(((const __m128i*)src) + 0); - _mm_storeu_si128(((__m128i*)dst) + 0, m0); -#else - *((uint64_t*)((char*)dst + 0)) = *((uint64_t*)((const char*)src + 0)); - *((uint64_t*)((char*)dst + 8)) = *((uint64_t*)((const char*)src + 8)); -#endif -} - -static INLINE void memcpy_avx_32(void *dst, const void *src) { - __m256i m0 = _mm256_loadu_si256(((const __m256i*)src) + 0); - _mm256_storeu_si256(((__m256i*)dst) + 0, m0); -} - -static INLINE void memcpy_avx_64(void *dst, const void *src) { - __m256i m0 = _mm256_loadu_si256(((const __m256i*)src) + 0); - __m256i m1 = _mm256_loadu_si256(((const __m256i*)src) + 1); - _mm256_storeu_si256(((__m256i*)dst) + 0, m0); - _mm256_storeu_si256(((__m256i*)dst) + 1, m1); -} - -static INLINE void memcpy_avx_128(void *dst, const void *src) { - __m256i m0 = _mm256_loadu_si256(((const __m256i*)src) + 0); - __m256i m1 = _mm256_loadu_si256(((const __m256i*)src) + 1); - __m256i m2 = _mm256_loadu_si256(((const __m256i*)src) + 2); - __m256i m3 = _mm256_loadu_si256(((const __m256i*)src) + 3); - _mm256_storeu_si256(((__m256i*)dst) + 0, m0); - _mm256_storeu_si256(((__m256i*)dst) + 1, m1); - _mm256_storeu_si256(((__m256i*)dst) + 2, m2); - _mm256_storeu_si256(((__m256i*)dst) + 3, m3); -} - -static INLINE void memcpy_avx_256(void *dst, const void *src) { - __m256i m0 = _mm256_loadu_si256(((const __m256i*)src) + 0); - __m256i m1 = _mm256_loadu_si256(((const __m256i*)src) + 1); - __m256i m2 = _mm256_loadu_si256(((const __m256i*)src) + 2); - __m256i m3 = _mm256_loadu_si256(((const __m256i*)src) + 3); - __m256i m4 = _mm256_loadu_si256(((const __m256i*)src) + 4); - __m256i m5 = _mm256_loadu_si256(((const __m256i*)src) + 5); - __m256i m6 = _mm256_loadu_si256(((const __m256i*)src) + 6); - __m256i m7 = _mm256_loadu_si256(((const __m256i*)src) + 7); - _mm256_storeu_si256(((__m256i*)dst) + 0, m0); - _mm256_storeu_si256(((__m256i*)dst) + 1, m1); - _mm256_storeu_si256(((__m256i*)dst) + 2, m2); - _mm256_storeu_si256(((__m256i*)dst) + 3, m3); - _mm256_storeu_si256(((__m256i*)dst) + 4, m4); - _mm256_storeu_si256(((__m256i*)dst) + 5, m5); - _mm256_storeu_si256(((__m256i*)dst) + 6, m6); - _mm256_storeu_si256(((__m256i*)dst) + 7, m7); -} - - -//--------------------------------------------------------------------- -// tiny memory copy with jump table optimized -//--------------------------------------------------------------------- -static INLINE void *memcpy_tiny(void *dst, const void *src, size_t size) { - unsigned char *dd = ((unsigned char*)dst) + size; - const unsigned char *ss = ((const unsigned char*)src) + size; - - switch (size) { - case 128: memcpy_avx_128(dd - 128, ss - 128); - case 0: break; - case 129: memcpy_avx_128(dd - 129, ss - 129); - case 1: dd[-1] = ss[-1]; break; - case 130: memcpy_avx_128(dd - 130, ss - 130); - case 2: *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; - case 131: memcpy_avx_128(dd - 131, ss - 131); - case 3: *((uint16_t*)(dd - 3)) = *((uint16_t*)(ss - 3)); dd[-1] = ss[-1]; break; - case 132: memcpy_avx_128(dd - 132, ss - 132); - case 4: *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; - case 133: memcpy_avx_128(dd - 133, ss - 133); - case 5: *((uint32_t*)(dd - 5)) = *((uint32_t*)(ss - 5)); dd[-1] = ss[-1]; break; - case 134: memcpy_avx_128(dd - 134, ss - 134); - case 6: *((uint32_t*)(dd - 6)) = *((uint32_t*)(ss - 6)); *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; - case 135: memcpy_avx_128(dd - 135, ss - 135); - case 7: *((uint32_t*)(dd - 7)) = *((uint32_t*)(ss - 7)); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; - case 136: memcpy_avx_128(dd - 136, ss - 136); - case 8: *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 137: memcpy_avx_128(dd - 137, ss - 137); - case 9: *((uint64_t*)(dd - 9)) = *((uint64_t*)(ss - 9)); dd[-1] = ss[-1]; break; - case 138: memcpy_avx_128(dd - 138, ss - 138); - case 10: *((uint64_t*)(dd - 10)) = *((uint64_t*)(ss - 10)); *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; - case 139: memcpy_avx_128(dd - 139, ss - 139); - case 11: *((uint64_t*)(dd - 11)) = *((uint64_t*)(ss - 11)); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; - case 140: memcpy_avx_128(dd - 140, ss - 140); - case 12: *((uint64_t*)(dd - 12)) = *((uint64_t*)(ss - 12)); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; - case 141: memcpy_avx_128(dd - 141, ss - 141); - case 13: *((uint64_t*)(dd - 13)) = *((uint64_t*)(ss - 13)); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 142: memcpy_avx_128(dd - 142, ss - 142); - case 14: *((uint64_t*)(dd - 14)) = *((uint64_t*)(ss - 14)); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 143: memcpy_avx_128(dd - 143, ss - 143); - case 15: *((uint64_t*)(dd - 15)) = *((uint64_t*)(ss - 15)); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 144: memcpy_avx_128(dd - 144, ss - 144); - case 16: memcpy_avx_16(dd - 16, ss - 16); break; - case 145: memcpy_avx_128(dd - 145, ss - 145); - case 17: memcpy_avx_16(dd - 17, ss - 17); dd[-1] = ss[-1]; break; - case 146: memcpy_avx_128(dd - 146, ss - 146); - case 18: memcpy_avx_16(dd - 18, ss - 18); *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; - case 147: memcpy_avx_128(dd - 147, ss - 147); - case 19: memcpy_avx_16(dd - 19, ss - 19); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; - case 148: memcpy_avx_128(dd - 148, ss - 148); - case 20: memcpy_avx_16(dd - 20, ss - 20); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; - case 149: memcpy_avx_128(dd - 149, ss - 149); - case 21: memcpy_avx_16(dd - 21, ss - 21); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 150: memcpy_avx_128(dd - 150, ss - 150); - case 22: memcpy_avx_16(dd - 22, ss - 22); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 151: memcpy_avx_128(dd - 151, ss - 151); - case 23: memcpy_avx_16(dd - 23, ss - 23); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 152: memcpy_avx_128(dd - 152, ss - 152); - case 24: memcpy_avx_16(dd - 24, ss - 24); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 153: memcpy_avx_128(dd - 153, ss - 153); - case 25: memcpy_avx_16(dd - 25, ss - 25); memcpy_avx_16(dd - 16, ss - 16); break; - case 154: memcpy_avx_128(dd - 154, ss - 154); - case 26: memcpy_avx_16(dd - 26, ss - 26); memcpy_avx_16(dd - 16, ss - 16); break; - case 155: memcpy_avx_128(dd - 155, ss - 155); - case 27: memcpy_avx_16(dd - 27, ss - 27); memcpy_avx_16(dd - 16, ss - 16); break; - case 156: memcpy_avx_128(dd - 156, ss - 156); - case 28: memcpy_avx_16(dd - 28, ss - 28); memcpy_avx_16(dd - 16, ss - 16); break; - case 157: memcpy_avx_128(dd - 157, ss - 157); - case 29: memcpy_avx_16(dd - 29, ss - 29); memcpy_avx_16(dd - 16, ss - 16); break; - case 158: memcpy_avx_128(dd - 158, ss - 158); - case 30: memcpy_avx_16(dd - 30, ss - 30); memcpy_avx_16(dd - 16, ss - 16); break; - case 159: memcpy_avx_128(dd - 159, ss - 159); - case 31: memcpy_avx_16(dd - 31, ss - 31); memcpy_avx_16(dd - 16, ss - 16); break; - case 160: memcpy_avx_128(dd - 160, ss - 160); - case 32: memcpy_avx_32(dd - 32, ss - 32); break; - case 161: memcpy_avx_128(dd - 161, ss - 161); - case 33: memcpy_avx_32(dd - 33, ss - 33); dd[-1] = ss[-1]; break; - case 162: memcpy_avx_128(dd - 162, ss - 162); - case 34: memcpy_avx_32(dd - 34, ss - 34); *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; - case 163: memcpy_avx_128(dd - 163, ss - 163); - case 35: memcpy_avx_32(dd - 35, ss - 35); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; - case 164: memcpy_avx_128(dd - 164, ss - 164); - case 36: memcpy_avx_32(dd - 36, ss - 36); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; - case 165: memcpy_avx_128(dd - 165, ss - 165); - case 37: memcpy_avx_32(dd - 37, ss - 37); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 166: memcpy_avx_128(dd - 166, ss - 166); - case 38: memcpy_avx_32(dd - 38, ss - 38); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 167: memcpy_avx_128(dd - 167, ss - 167); - case 39: memcpy_avx_32(dd - 39, ss - 39); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 168: memcpy_avx_128(dd - 168, ss - 168); - case 40: memcpy_avx_32(dd - 40, ss - 40); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 169: memcpy_avx_128(dd - 169, ss - 169); - case 41: memcpy_avx_32(dd - 41, ss - 41); memcpy_avx_16(dd - 16, ss - 16); break; - case 170: memcpy_avx_128(dd - 170, ss - 170); - case 42: memcpy_avx_32(dd - 42, ss - 42); memcpy_avx_16(dd - 16, ss - 16); break; - case 171: memcpy_avx_128(dd - 171, ss - 171); - case 43: memcpy_avx_32(dd - 43, ss - 43); memcpy_avx_16(dd - 16, ss - 16); break; - case 172: memcpy_avx_128(dd - 172, ss - 172); - case 44: memcpy_avx_32(dd - 44, ss - 44); memcpy_avx_16(dd - 16, ss - 16); break; - case 173: memcpy_avx_128(dd - 173, ss - 173); - case 45: memcpy_avx_32(dd - 45, ss - 45); memcpy_avx_16(dd - 16, ss - 16); break; - case 174: memcpy_avx_128(dd - 174, ss - 174); - case 46: memcpy_avx_32(dd - 46, ss - 46); memcpy_avx_16(dd - 16, ss - 16); break; - case 175: memcpy_avx_128(dd - 175, ss - 175); - case 47: memcpy_avx_32(dd - 47, ss - 47); memcpy_avx_16(dd - 16, ss - 16); break; - case 176: memcpy_avx_128(dd - 176, ss - 176); - case 48: memcpy_avx_32(dd - 48, ss - 48); memcpy_avx_16(dd - 16, ss - 16); break; - case 177: memcpy_avx_128(dd - 177, ss - 177); - case 49: memcpy_avx_32(dd - 49, ss - 49); memcpy_avx_32(dd - 32, ss - 32); break; - case 178: memcpy_avx_128(dd - 178, ss - 178); - case 50: memcpy_avx_32(dd - 50, ss - 50); memcpy_avx_32(dd - 32, ss - 32); break; - case 179: memcpy_avx_128(dd - 179, ss - 179); - case 51: memcpy_avx_32(dd - 51, ss - 51); memcpy_avx_32(dd - 32, ss - 32); break; - case 180: memcpy_avx_128(dd - 180, ss - 180); - case 52: memcpy_avx_32(dd - 52, ss - 52); memcpy_avx_32(dd - 32, ss - 32); break; - case 181: memcpy_avx_128(dd - 181, ss - 181); - case 53: memcpy_avx_32(dd - 53, ss - 53); memcpy_avx_32(dd - 32, ss - 32); break; - case 182: memcpy_avx_128(dd - 182, ss - 182); - case 54: memcpy_avx_32(dd - 54, ss - 54); memcpy_avx_32(dd - 32, ss - 32); break; - case 183: memcpy_avx_128(dd - 183, ss - 183); - case 55: memcpy_avx_32(dd - 55, ss - 55); memcpy_avx_32(dd - 32, ss - 32); break; - case 184: memcpy_avx_128(dd - 184, ss - 184); - case 56: memcpy_avx_32(dd - 56, ss - 56); memcpy_avx_32(dd - 32, ss - 32); break; - case 185: memcpy_avx_128(dd - 185, ss - 185); - case 57: memcpy_avx_32(dd - 57, ss - 57); memcpy_avx_32(dd - 32, ss - 32); break; - case 186: memcpy_avx_128(dd - 186, ss - 186); - case 58: memcpy_avx_32(dd - 58, ss - 58); memcpy_avx_32(dd - 32, ss - 32); break; - case 187: memcpy_avx_128(dd - 187, ss - 187); - case 59: memcpy_avx_32(dd - 59, ss - 59); memcpy_avx_32(dd - 32, ss - 32); break; - case 188: memcpy_avx_128(dd - 188, ss - 188); - case 60: memcpy_avx_32(dd - 60, ss - 60); memcpy_avx_32(dd - 32, ss - 32); break; - case 189: memcpy_avx_128(dd - 189, ss - 189); - case 61: memcpy_avx_32(dd - 61, ss - 61); memcpy_avx_32(dd - 32, ss - 32); break; - case 190: memcpy_avx_128(dd - 190, ss - 190); - case 62: memcpy_avx_32(dd - 62, ss - 62); memcpy_avx_32(dd - 32, ss - 32); break; - case 191: memcpy_avx_128(dd - 191, ss - 191); - case 63: memcpy_avx_32(dd - 63, ss - 63); memcpy_avx_32(dd - 32, ss - 32); break; - case 192: memcpy_avx_128(dd - 192, ss - 192); - case 64: memcpy_avx_64(dd - 64, ss - 64); break; - case 193: memcpy_avx_128(dd - 193, ss - 193); - case 65: memcpy_avx_64(dd - 65, ss - 65); dd[-1] = ss[-1]; break; - case 194: memcpy_avx_128(dd - 194, ss - 194); - case 66: memcpy_avx_64(dd - 66, ss - 66); *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; - case 195: memcpy_avx_128(dd - 195, ss - 195); - case 67: memcpy_avx_64(dd - 67, ss - 67); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; - case 196: memcpy_avx_128(dd - 196, ss - 196); - case 68: memcpy_avx_64(dd - 68, ss - 68); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; - case 197: memcpy_avx_128(dd - 197, ss - 197); - case 69: memcpy_avx_64(dd - 69, ss - 69); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 198: memcpy_avx_128(dd - 198, ss - 198); - case 70: memcpy_avx_64(dd - 70, ss - 70); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 199: memcpy_avx_128(dd - 199, ss - 199); - case 71: memcpy_avx_64(dd - 71, ss - 71); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 200: memcpy_avx_128(dd - 200, ss - 200); - case 72: memcpy_avx_64(dd - 72, ss - 72); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; - case 201: memcpy_avx_128(dd - 201, ss - 201); - case 73: memcpy_avx_64(dd - 73, ss - 73); memcpy_avx_16(dd - 16, ss - 16); break; - case 202: memcpy_avx_128(dd - 202, ss - 202); - case 74: memcpy_avx_64(dd - 74, ss - 74); memcpy_avx_16(dd - 16, ss - 16); break; - case 203: memcpy_avx_128(dd - 203, ss - 203); - case 75: memcpy_avx_64(dd - 75, ss - 75); memcpy_avx_16(dd - 16, ss - 16); break; - case 204: memcpy_avx_128(dd - 204, ss - 204); - case 76: memcpy_avx_64(dd - 76, ss - 76); memcpy_avx_16(dd - 16, ss - 16); break; - case 205: memcpy_avx_128(dd - 205, ss - 205); - case 77: memcpy_avx_64(dd - 77, ss - 77); memcpy_avx_16(dd - 16, ss - 16); break; - case 206: memcpy_avx_128(dd - 206, ss - 206); - case 78: memcpy_avx_64(dd - 78, ss - 78); memcpy_avx_16(dd - 16, ss - 16); break; - case 207: memcpy_avx_128(dd - 207, ss - 207); - case 79: memcpy_avx_64(dd - 79, ss - 79); memcpy_avx_16(dd - 16, ss - 16); break; - case 208: memcpy_avx_128(dd - 208, ss - 208); - case 80: memcpy_avx_64(dd - 80, ss - 80); memcpy_avx_16(dd - 16, ss - 16); break; - case 209: memcpy_avx_128(dd - 209, ss - 209); - case 81: memcpy_avx_64(dd - 81, ss - 81); memcpy_avx_32(dd - 32, ss - 32); break; - case 210: memcpy_avx_128(dd - 210, ss - 210); - case 82: memcpy_avx_64(dd - 82, ss - 82); memcpy_avx_32(dd - 32, ss - 32); break; - case 211: memcpy_avx_128(dd - 211, ss - 211); - case 83: memcpy_avx_64(dd - 83, ss - 83); memcpy_avx_32(dd - 32, ss - 32); break; - case 212: memcpy_avx_128(dd - 212, ss - 212); - case 84: memcpy_avx_64(dd - 84, ss - 84); memcpy_avx_32(dd - 32, ss - 32); break; - case 213: memcpy_avx_128(dd - 213, ss - 213); - case 85: memcpy_avx_64(dd - 85, ss - 85); memcpy_avx_32(dd - 32, ss - 32); break; - case 214: memcpy_avx_128(dd - 214, ss - 214); - case 86: memcpy_avx_64(dd - 86, ss - 86); memcpy_avx_32(dd - 32, ss - 32); break; - case 215: memcpy_avx_128(dd - 215, ss - 215); - case 87: memcpy_avx_64(dd - 87, ss - 87); memcpy_avx_32(dd - 32, ss - 32); break; - case 216: memcpy_avx_128(dd - 216, ss - 216); - case 88: memcpy_avx_64(dd - 88, ss - 88); memcpy_avx_32(dd - 32, ss - 32); break; - case 217: memcpy_avx_128(dd - 217, ss - 217); - case 89: memcpy_avx_64(dd - 89, ss - 89); memcpy_avx_32(dd - 32, ss - 32); break; - case 218: memcpy_avx_128(dd - 218, ss - 218); - case 90: memcpy_avx_64(dd - 90, ss - 90); memcpy_avx_32(dd - 32, ss - 32); break; - case 219: memcpy_avx_128(dd - 219, ss - 219); - case 91: memcpy_avx_64(dd - 91, ss - 91); memcpy_avx_32(dd - 32, ss - 32); break; - case 220: memcpy_avx_128(dd - 220, ss - 220); - case 92: memcpy_avx_64(dd - 92, ss - 92); memcpy_avx_32(dd - 32, ss - 32); break; - case 221: memcpy_avx_128(dd - 221, ss - 221); - case 93: memcpy_avx_64(dd - 93, ss - 93); memcpy_avx_32(dd - 32, ss - 32); break; - case 222: memcpy_avx_128(dd - 222, ss - 222); - case 94: memcpy_avx_64(dd - 94, ss - 94); memcpy_avx_32(dd - 32, ss - 32); break; - case 223: memcpy_avx_128(dd - 223, ss - 223); - case 95: memcpy_avx_64(dd - 95, ss - 95); memcpy_avx_32(dd - 32, ss - 32); break; - case 224: memcpy_avx_128(dd - 224, ss - 224); - case 96: memcpy_avx_64(dd - 96, ss - 96); memcpy_avx_32(dd - 32, ss - 32); break; - case 225: memcpy_avx_128(dd - 225, ss - 225); - case 97: memcpy_avx_64(dd - 97, ss - 97); memcpy_avx_64(dd - 64, ss - 64); break; - case 226: memcpy_avx_128(dd - 226, ss - 226); - case 98: memcpy_avx_64(dd - 98, ss - 98); memcpy_avx_64(dd - 64, ss - 64); break; - case 227: memcpy_avx_128(dd - 227, ss - 227); - case 99: memcpy_avx_64(dd - 99, ss - 99); memcpy_avx_64(dd - 64, ss - 64); break; - case 228: memcpy_avx_128(dd - 228, ss - 228); - case 100: memcpy_avx_64(dd - 100, ss - 100); memcpy_avx_64(dd - 64, ss - 64); break; - case 229: memcpy_avx_128(dd - 229, ss - 229); - case 101: memcpy_avx_64(dd - 101, ss - 101); memcpy_avx_64(dd - 64, ss - 64); break; - case 230: memcpy_avx_128(dd - 230, ss - 230); - case 102: memcpy_avx_64(dd - 102, ss - 102); memcpy_avx_64(dd - 64, ss - 64); break; - case 231: memcpy_avx_128(dd - 231, ss - 231); - case 103: memcpy_avx_64(dd - 103, ss - 103); memcpy_avx_64(dd - 64, ss - 64); break; - case 232: memcpy_avx_128(dd - 232, ss - 232); - case 104: memcpy_avx_64(dd - 104, ss - 104); memcpy_avx_64(dd - 64, ss - 64); break; - case 233: memcpy_avx_128(dd - 233, ss - 233); - case 105: memcpy_avx_64(dd - 105, ss - 105); memcpy_avx_64(dd - 64, ss - 64); break; - case 234: memcpy_avx_128(dd - 234, ss - 234); - case 106: memcpy_avx_64(dd - 106, ss - 106); memcpy_avx_64(dd - 64, ss - 64); break; - case 235: memcpy_avx_128(dd - 235, ss - 235); - case 107: memcpy_avx_64(dd - 107, ss - 107); memcpy_avx_64(dd - 64, ss - 64); break; - case 236: memcpy_avx_128(dd - 236, ss - 236); - case 108: memcpy_avx_64(dd - 108, ss - 108); memcpy_avx_64(dd - 64, ss - 64); break; - case 237: memcpy_avx_128(dd - 237, ss - 237); - case 109: memcpy_avx_64(dd - 109, ss - 109); memcpy_avx_64(dd - 64, ss - 64); break; - case 238: memcpy_avx_128(dd - 238, ss - 238); - case 110: memcpy_avx_64(dd - 110, ss - 110); memcpy_avx_64(dd - 64, ss - 64); break; - case 239: memcpy_avx_128(dd - 239, ss - 239); - case 111: memcpy_avx_64(dd - 111, ss - 111); memcpy_avx_64(dd - 64, ss - 64); break; - case 240: memcpy_avx_128(dd - 240, ss - 240); - case 112: memcpy_avx_64(dd - 112, ss - 112); memcpy_avx_64(dd - 64, ss - 64); break; - case 241: memcpy_avx_128(dd - 241, ss - 241); - case 113: memcpy_avx_64(dd - 113, ss - 113); memcpy_avx_64(dd - 64, ss - 64); break; - case 242: memcpy_avx_128(dd - 242, ss - 242); - case 114: memcpy_avx_64(dd - 114, ss - 114); memcpy_avx_64(dd - 64, ss - 64); break; - case 243: memcpy_avx_128(dd - 243, ss - 243); - case 115: memcpy_avx_64(dd - 115, ss - 115); memcpy_avx_64(dd - 64, ss - 64); break; - case 244: memcpy_avx_128(dd - 244, ss - 244); - case 116: memcpy_avx_64(dd - 116, ss - 116); memcpy_avx_64(dd - 64, ss - 64); break; - case 245: memcpy_avx_128(dd - 245, ss - 245); - case 117: memcpy_avx_64(dd - 117, ss - 117); memcpy_avx_64(dd - 64, ss - 64); break; - case 246: memcpy_avx_128(dd - 246, ss - 246); - case 118: memcpy_avx_64(dd - 118, ss - 118); memcpy_avx_64(dd - 64, ss - 64); break; - case 247: memcpy_avx_128(dd - 247, ss - 247); - case 119: memcpy_avx_64(dd - 119, ss - 119); memcpy_avx_64(dd - 64, ss - 64); break; - case 248: memcpy_avx_128(dd - 248, ss - 248); - case 120: memcpy_avx_64(dd - 120, ss - 120); memcpy_avx_64(dd - 64, ss - 64); break; - case 249: memcpy_avx_128(dd - 249, ss - 249); - case 121: memcpy_avx_64(dd - 121, ss - 121); memcpy_avx_64(dd - 64, ss - 64); break; - case 250: memcpy_avx_128(dd - 250, ss - 250); - case 122: memcpy_avx_64(dd - 122, ss - 122); memcpy_avx_64(dd - 64, ss - 64); break; - case 251: memcpy_avx_128(dd - 251, ss - 251); - case 123: memcpy_avx_64(dd - 123, ss - 123); memcpy_avx_64(dd - 64, ss - 64); break; - case 252: memcpy_avx_128(dd - 252, ss - 252); - case 124: memcpy_avx_64(dd - 124, ss - 124); memcpy_avx_64(dd - 64, ss - 64); break; - case 253: memcpy_avx_128(dd - 253, ss - 253); - case 125: memcpy_avx_64(dd - 125, ss - 125); memcpy_avx_64(dd - 64, ss - 64); break; - case 254: memcpy_avx_128(dd - 254, ss - 254); - case 126: memcpy_avx_64(dd - 126, ss - 126); memcpy_avx_64(dd - 64, ss - 64); break; - case 255: memcpy_avx_128(dd - 255, ss - 255); - case 127: memcpy_avx_64(dd - 127, ss - 127); memcpy_avx_64(dd - 64, ss - 64); break; - case 256: memcpy_avx_256(dd - 256, ss - 256); break; - } - - return dst; -} - - -//--------------------------------------------------------------------- -// main routine -//--------------------------------------------------------------------- -static void* memcpy_fast(void *destination, const void *source, size_t size) -{ - unsigned char *dst = (unsigned char*)destination; - const unsigned char *src = (const unsigned char*)source; - static size_t cachesize = 0x200000; // L3-cache size - size_t padding; - - // small memory copy - if (size <= 256) { - memcpy_tiny(dst, src, size); - _mm256_zeroupper(); - return destination; - } - - // align destination to 16 bytes boundary - padding = (32 - (((size_t)dst) & 31)) & 31; - -#if 0 - if (padding > 0) { - __m256i head = _mm256_loadu_si256((const __m256i*)src); - _mm256_storeu_si256((__m256i*)dst, head); - dst += padding; - src += padding; - size -= padding; - } -#else - __m256i head = _mm256_loadu_si256((const __m256i*)src); - _mm256_storeu_si256((__m256i*)dst, head); - dst += padding; - src += padding; - size -= padding; -#endif - - // medium size copy - if (size <= cachesize) { - __m256i c0, c1, c2, c3, c4, c5, c6, c7; - - for (; size >= 256; size -= 256) { - c0 = _mm256_loadu_si256(((const __m256i*)src) + 0); - c1 = _mm256_loadu_si256(((const __m256i*)src) + 1); - c2 = _mm256_loadu_si256(((const __m256i*)src) + 2); - c3 = _mm256_loadu_si256(((const __m256i*)src) + 3); - c4 = _mm256_loadu_si256(((const __m256i*)src) + 4); - c5 = _mm256_loadu_si256(((const __m256i*)src) + 5); - c6 = _mm256_loadu_si256(((const __m256i*)src) + 6); - c7 = _mm256_loadu_si256(((const __m256i*)src) + 7); - _mm_prefetch((const char*)(src + 512), _MM_HINT_NTA); - src += 256; - _mm256_storeu_si256((((__m256i*)dst) + 0), c0); - _mm256_storeu_si256((((__m256i*)dst) + 1), c1); - _mm256_storeu_si256((((__m256i*)dst) + 2), c2); - _mm256_storeu_si256((((__m256i*)dst) + 3), c3); - _mm256_storeu_si256((((__m256i*)dst) + 4), c4); - _mm256_storeu_si256((((__m256i*)dst) + 5), c5); - _mm256_storeu_si256((((__m256i*)dst) + 6), c6); - _mm256_storeu_si256((((__m256i*)dst) + 7), c7); - dst += 256; - } - } - else { // big memory copy - __m256i c0, c1, c2, c3, c4, c5, c6, c7; - /* __m256i c0, c1, c2, c3, c4, c5, c6, c7; */ - - _mm_prefetch((const char*)(src), _MM_HINT_NTA); - - if ((((size_t)src) & 31) == 0) { // source aligned - for (; size >= 256; size -= 256) { - c0 = _mm256_load_si256(((const __m256i*)src) + 0); - c1 = _mm256_load_si256(((const __m256i*)src) + 1); - c2 = _mm256_load_si256(((const __m256i*)src) + 2); - c3 = _mm256_load_si256(((const __m256i*)src) + 3); - c4 = _mm256_load_si256(((const __m256i*)src) + 4); - c5 = _mm256_load_si256(((const __m256i*)src) + 5); - c6 = _mm256_load_si256(((const __m256i*)src) + 6); - c7 = _mm256_load_si256(((const __m256i*)src) + 7); - _mm_prefetch((const char*)(src + 512), _MM_HINT_NTA); - src += 256; - _mm256_stream_si256((((__m256i*)dst) + 0), c0); - _mm256_stream_si256((((__m256i*)dst) + 1), c1); - _mm256_stream_si256((((__m256i*)dst) + 2), c2); - _mm256_stream_si256((((__m256i*)dst) + 3), c3); - _mm256_stream_si256((((__m256i*)dst) + 4), c4); - _mm256_stream_si256((((__m256i*)dst) + 5), c5); - _mm256_stream_si256((((__m256i*)dst) + 6), c6); - _mm256_stream_si256((((__m256i*)dst) + 7), c7); - dst += 256; - } - } - else { // source unaligned - for (; size >= 256; size -= 256) { - c0 = _mm256_loadu_si256(((const __m256i*)src) + 0); - c1 = _mm256_loadu_si256(((const __m256i*)src) + 1); - c2 = _mm256_loadu_si256(((const __m256i*)src) + 2); - c3 = _mm256_loadu_si256(((const __m256i*)src) + 3); - c4 = _mm256_loadu_si256(((const __m256i*)src) + 4); - c5 = _mm256_loadu_si256(((const __m256i*)src) + 5); - c6 = _mm256_loadu_si256(((const __m256i*)src) + 6); - c7 = _mm256_loadu_si256(((const __m256i*)src) + 7); - _mm_prefetch((const char*)(src + 512), _MM_HINT_NTA); - src += 256; - _mm256_stream_si256((((__m256i*)dst) + 0), c0); - _mm256_stream_si256((((__m256i*)dst) + 1), c1); - _mm256_stream_si256((((__m256i*)dst) + 2), c2); - _mm256_stream_si256((((__m256i*)dst) + 3), c3); - _mm256_stream_si256((((__m256i*)dst) + 4), c4); - _mm256_stream_si256((((__m256i*)dst) + 5), c5); - _mm256_stream_si256((((__m256i*)dst) + 6), c6); - _mm256_stream_si256((((__m256i*)dst) + 7), c7); - dst += 256; - } - } - _mm_sfence(); - } - - memcpy_tiny(dst, src, size); - _mm256_zeroupper(); - - return destination; -} - - -#endif - - - diff --git a/contrib/FastMemcpy/LICENSE b/contrib/FastMemcpy/LICENSE deleted file mode 100644 index c449da6aa8a..00000000000 --- a/contrib/FastMemcpy/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Linwei - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/contrib/FastMemcpy/README.md b/contrib/FastMemcpy/README.md deleted file mode 100644 index e253f6bf5dd..00000000000 --- a/contrib/FastMemcpy/README.md +++ /dev/null @@ -1,20 +0,0 @@ -Internal implementation of `memcpy` function. - -It has the following advantages over `libc`-supplied implementation: -- it is linked statically, so the function is called directly, not through a `PLT` (procedure lookup table of shared library); -- it is linked statically, so the function can have position-dependent code; -- your binaries will not depend on `glibc`'s memcpy, that forces dependency on specific symbol version like `memcpy@@GLIBC_2.14` and consequently on specific version of `glibc` library; -- you can include `memcpy.h` directly and the function has the chance to be inlined, which is beneficial for small but unknown at compile time sizes of memory regions; -- this version of `memcpy` pretend to be faster (in our benchmarks, the difference is within few percents). - -Currently it uses the implementation from **Linwei** (skywind3000@163.com). -Look at https://www.zhihu.com/question/35172305 for discussion. - -Drawbacks: -- only use SSE 2, doesn't use wider (AVX, AVX 512) vector registers when available; -- no CPU dispatching; doesn't take into account actual cache size. - -Also worth to look at: -- simple implementation from Facebook: https://github.com/facebook/folly/blob/master/folly/memcpy.S -- implementation from Agner Fog: http://www.agner.org/optimize/ -- glibc source code. diff --git a/contrib/FastMemcpy/memcpy_wrapper.c b/contrib/FastMemcpy/memcpy_wrapper.c deleted file mode 100644 index 1f57345980a..00000000000 --- a/contrib/FastMemcpy/memcpy_wrapper.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "FastMemcpy.h" - -void * memcpy(void * __restrict destination, const void * __restrict source, size_t size) -{ - return memcpy_fast(destination, source, size); -} diff --git a/contrib/NuRaft b/contrib/NuRaft index 410bd149da8..3d3683e7775 160000 --- a/contrib/NuRaft +++ b/contrib/NuRaft @@ -1 +1 @@ -Subproject commit 410bd149da84cdde60b4436b02b738749f4e87e1 +Subproject commit 3d3683e77753cfe015a05fae95ddf418e19f59e1 diff --git a/contrib/abseil-cpp-cmake/CMakeLists.txt b/contrib/abseil-cpp-cmake/CMakeLists.txt new file mode 100644 index 00000000000..c8cb512066a --- /dev/null +++ b/contrib/abseil-cpp-cmake/CMakeLists.txt @@ -0,0 +1,18 @@ +set(ABSL_ROOT_DIR "${ClickHouse_SOURCE_DIR}/contrib/abseil-cpp") +if(NOT EXISTS "${ABSL_ROOT_DIR}/CMakeLists.txt") + message(FATAL_ERROR " submodule third_party/abseil-cpp is missing. To fix try run: \n git submodule update --init --recursive") +endif() +add_subdirectory("${ABSL_ROOT_DIR}" "${ClickHouse_BINARY_DIR}/contrib/abseil-cpp") + +add_library(abseil_swiss_tables INTERFACE) + +target_link_libraries(abseil_swiss_tables INTERFACE + absl::flat_hash_map + absl::flat_hash_set +) + +get_target_property(FLAT_HASH_MAP_INCLUDE_DIR absl::flat_hash_map INTERFACE_INCLUDE_DIRECTORIES) +target_include_directories (abseil_swiss_tables SYSTEM BEFORE INTERFACE ${FLAT_HASH_MAP_INCLUDE_DIR}) + +get_target_property(FLAT_HASH_SET_INCLUDE_DIR absl::flat_hash_set INTERFACE_INCLUDE_DIRECTORIES) +target_include_directories (abseil_swiss_tables SYSTEM BEFORE INTERFACE ${FLAT_HASH_SET_INCLUDE_DIR}) diff --git a/contrib/boost b/contrib/boost index 8e259cd2a6b..ee24fa55bc4 160000 --- a/contrib/boost +++ b/contrib/boost @@ -1 +1 @@ -Subproject commit 8e259cd2a6b60d75dd17e73432f11bb7b9351bb1 +Subproject commit ee24fa55bc46e4d2ce7d0d052cc5a0d9b1be8c36 diff --git a/contrib/boringssl b/contrib/boringssl index 8b2bf912ba0..fd9ce1a0406 160000 --- a/contrib/boringssl +++ b/contrib/boringssl @@ -1 +1 @@ -Subproject commit 8b2bf912ba04823cfe9e7e8f5bb60cb7f6252449 +Subproject commit fd9ce1a0406f571507068b9555d0b545b8a18332 diff --git a/contrib/brotli b/contrib/brotli index 5805f99a533..63be8a99401 160000 --- a/contrib/brotli +++ b/contrib/brotli @@ -1 +1 @@ -Subproject commit 5805f99a533a8f8118699c0100d8c102f3605f65 +Subproject commit 63be8a99401992075c23e99f7c84de1c653e39e2 diff --git a/contrib/brotli-cmake/CMakeLists.txt b/contrib/brotli-cmake/CMakeLists.txt index e22f4593c02..4c5f584de9d 100644 --- a/contrib/brotli-cmake/CMakeLists.txt +++ b/contrib/brotli-cmake/CMakeLists.txt @@ -2,6 +2,8 @@ set(BROTLI_SOURCE_DIR ${ClickHouse_SOURCE_DIR}/contrib/brotli/c) set(BROTLI_BINARY_DIR ${ClickHouse_BINARY_DIR}/contrib/brotli/c) set(SRCS + ${BROTLI_SOURCE_DIR}/enc/command.c + ${BROTLI_SOURCE_DIR}/enc/fast_log.c ${BROTLI_SOURCE_DIR}/dec/bit_reader.c ${BROTLI_SOURCE_DIR}/dec/state.c ${BROTLI_SOURCE_DIR}/dec/huffman.c @@ -26,6 +28,9 @@ set(SRCS ${BROTLI_SOURCE_DIR}/enc/memory.c ${BROTLI_SOURCE_DIR}/common/dictionary.c ${BROTLI_SOURCE_DIR}/common/transform.c + ${BROTLI_SOURCE_DIR}/common/platform.c + ${BROTLI_SOURCE_DIR}/common/context.c + ${BROTLI_SOURCE_DIR}/common/constants.c ) add_library(brotli ${SRCS}) diff --git a/contrib/cassandra b/contrib/cassandra index b446d7eb68e..c097fb5c7e6 160000 --- a/contrib/cassandra +++ b/contrib/cassandra @@ -1 +1 @@ -Subproject commit b446d7eb68e6962f431e2b3771313bfe9a2bbd93 +Subproject commit c097fb5c7e63cc430016d9a8b240d8e63fbefa52 diff --git a/contrib/googletest b/contrib/googletest index 356f2d264a4..e7e591764ba 160000 --- a/contrib/googletest +++ b/contrib/googletest @@ -1 +1 @@ -Subproject commit 356f2d264a485db2fcc50ec1c672e0d37b6cb39b +Subproject commit e7e591764baba0a0c3c9ad0014430e7a27331d16 diff --git a/contrib/grpc-cmake/CMakeLists.txt b/contrib/grpc-cmake/CMakeLists.txt index 97ca3fab4db..b93968f62f9 100644 --- a/contrib/grpc-cmake/CMakeLists.txt +++ b/contrib/grpc-cmake/CMakeLists.txt @@ -39,11 +39,6 @@ set(_gRPC_SSL_LIBRARIES ${OPENSSL_LIBRARIES}) # Use abseil-cpp from ClickHouse contrib, not from gRPC third_party. set(gRPC_ABSL_PROVIDER "clickhouse" CACHE STRING "" FORCE) -set(ABSL_ROOT_DIR "${ClickHouse_SOURCE_DIR}/contrib/abseil-cpp") -if(NOT EXISTS "${ABSL_ROOT_DIR}/CMakeLists.txt") - message(FATAL_ERROR " grpc: submodule third_party/abseil-cpp is missing. To fix try run: \n git submodule update --init --recursive") -endif() -add_subdirectory("${ABSL_ROOT_DIR}" "${ClickHouse_BINARY_DIR}/contrib/abseil-cpp") # Choose to build static or shared library for c-ares. if (MAKE_STATIC_LIBRARIES) diff --git a/contrib/krb5-cmake/CMakeLists.txt b/contrib/krb5-cmake/CMakeLists.txt index f88402df1fa..fce7fbc582a 100644 --- a/contrib/krb5-cmake/CMakeLists.txt +++ b/contrib/krb5-cmake/CMakeLists.txt @@ -474,13 +474,6 @@ add_custom_command( WORKING_DIRECTORY "${KRB5_SOURCE_DIR}/util/et" ) -add_custom_target( - CREATE_COMPILE_ET ALL - DEPENDS ${KRB5_SOURCE_DIR}/util/et/compile_et - COMMENT "creating compile_et" - VERBATIM -) - file(GLOB_RECURSE ET_FILES "${KRB5_SOURCE_DIR}/*.et" ) @@ -531,7 +524,7 @@ add_custom_command( add_custom_target( - ERROR_MAP_H ALL + ERROR_MAP_H DEPENDS ${KRB5_SOURCE_DIR}/lib/gssapi/krb5/error_map.h COMMENT "generating error_map.h" VERBATIM @@ -544,14 +537,14 @@ add_custom_command( ) add_custom_target( - ERRMAP_H ALL + ERRMAP_H DEPENDS ${KRB5_SOURCE_DIR}/lib/gssapi/generic/errmap.h COMMENT "generating errmap.h" VERBATIM ) add_custom_target( - KRB_5_H ALL + KRB_5_H DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/include/krb5/krb5.h COMMENT "generating krb5.h" VERBATIM @@ -564,15 +557,19 @@ add_dependencies( ERRMAP_H ERROR_MAP_H KRB_5_H - ) +) preprocess_et(processed_et_files ${ET_FILES}) -add_custom_command( - OUTPUT ${KRB5_SOURCE_DIR}/lib/gssapi/generic/errmap.h - COMMAND perl -w -I../../../util ../../../util/gen.pl bimap errmap.h NAME=mecherrmap LEFT=OM_uint32 RIGHT=struct\ mecherror LEFTPRINT=print_OM_uint32 RIGHTPRINT=mecherror_print LEFTCMP=cmp_OM_uint32 RIGHTCMP=mecherror_cmp - WORKING_DIRECTORY "${KRB5_SOURCE_DIR}/lib/gssapi/generic" -) +if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/include_private/kcmrpc.h ${CMAKE_CURRENT_BINARY_DIR}/include_private/kcmrpc.c + COMMAND mig -header kcmrpc.h -user kcmrpc.c -sheader /dev/null -server /dev/null -I${KRB5_SOURCE_DIR}/lib/krb5/ccache ${KRB5_SOURCE_DIR}/lib/krb5/ccache/kcmrpc.defs + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include_private" + ) + + list(APPEND ALL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/include_private/kcmrpc.c) +endif() target_sources(${KRB5_LIBRARY} PRIVATE ${ALL_SRCS} @@ -604,6 +601,25 @@ file(COPY ${KRB5_SOURCE_DIR}/util/et/com_err.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/ ) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/osconf.h + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include_private/ +) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/profile.h + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include_private/ +) + +string(TOLOWER "${CMAKE_SYSTEM_NAME}" _system_name) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/autoconf_${_system_name}.h + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include_private/ +) + +file(RENAME + ${CMAKE_CURRENT_BINARY_DIR}/include_private/autoconf_${_system_name}.h + ${CMAKE_CURRENT_BINARY_DIR}/include_private/autoconf.h +) + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/krb5 ) @@ -633,7 +649,7 @@ target_include_directories(${KRB5_LIBRARY} PUBLIC ) target_include_directories(${KRB5_LIBRARY} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} #for autoconf.h + ${CMAKE_CURRENT_BINARY_DIR}/include_private # For autoconf.h and other generated headers. ${KRB5_SOURCE_DIR} ${KRB5_SOURCE_DIR}/include ${KRB5_SOURCE_DIR}/lib/gssapi/mechglue diff --git a/contrib/krb5-cmake/autoconf_darwin.h b/contrib/krb5-cmake/autoconf_darwin.h new file mode 100644 index 00000000000..965e2f02997 --- /dev/null +++ b/contrib/krb5-cmake/autoconf_darwin.h @@ -0,0 +1,764 @@ +/* include/autoconf.h. Generated from autoconf.h.in by configure. */ +/* include/autoconf.h.in. Generated from configure.in by autoheader. */ + + +#ifndef KRB5_AUTOCONF_H +#define KRB5_AUTOCONF_H + + +/* Define if AES-NI support is enabled */ +/* #undef AESNI */ + +/* Define if socket can't be bound to 0.0.0.0 */ +/* #undef BROKEN_STREAMS_SOCKETS */ + +/* Define if va_list objects can be simply copied by assignment. */ +/* #undef CAN_COPY_VA_LIST */ + +/* Define to reduce code size even if it means more cpu usage */ +/* #undef CONFIG_SMALL */ + +/* Define if __attribute__((constructor)) works */ +#define CONSTRUCTOR_ATTR_WORKS 1 + +/* Define to default ccache name */ +#define DEFCCNAME "FILE:/tmp/krb5cc_%{uid}" + +/* Define to default client keytab name */ +#define DEFCKTNAME "FILE:/etc/krb5/user/%{euid}/client.keytab" + +/* Define to default keytab name */ +#define DEFKTNAME "FILE:/etc/krb5.keytab" + +/* Define if library initialization should be delayed until first use */ +#define DELAY_INITIALIZER 1 + +/* Define if __attribute__((destructor)) works */ +#define DESTRUCTOR_ATTR_WORKS 1 + +/* Define to disable PKINIT plugin support */ +#define DISABLE_PKINIT 1 + +/* Define if LDAP KDB support within the Kerberos library (mainly ASN.1 code) + should be enabled. */ +/* #undef ENABLE_LDAP */ + +/* Define if translation functions should be used. */ +/* #undef ENABLE_NLS */ + +/* Define if thread support enabled */ +#define ENABLE_THREADS 1 + +/* Define as return type of endrpcent */ +#define ENDRPCENT_TYPE void + +/* Define if Fortuna PRNG is selected */ +#define FORTUNA 1 + +/* Define to the type of elements in the array set by `getgroups'. Usually + this is either `int' or `gid_t'. */ +#define GETGROUPS_T gid_t + +/* Define if gethostbyname_r returns int rather than struct hostent * */ +/* #undef GETHOSTBYNAME_R_RETURNS_INT */ + +/* Type of getpeername second argument. */ +#define GETPEERNAME_ARG3_TYPE GETSOCKNAME_ARG3_TYPE + +/* Define if getpwnam_r exists but takes only 4 arguments (e.g., POSIX draft 6 + implementations like some Solaris releases). */ +/* #undef GETPWNAM_R_4_ARGS */ + +/* Define if getpwnam_r returns an int */ +#define GETPWNAM_R_RETURNS_INT 1 + +/* Define if getpwuid_r exists but takes only 4 arguments (e.g., POSIX draft 6 + implementations like some Solaris releases). */ +/* #undef GETPWUID_R_4_ARGS */ + +/* Define if getservbyname_r returns int rather than struct servent * */ +/* #undef GETSERVBYNAME_R_RETURNS_INT */ + +/* Type of pointer target for argument 3 to getsockname */ +#define GETSOCKNAME_ARG3_TYPE socklen_t + +/* Define if gmtime_r returns int instead of struct tm pointer, as on old + HP-UX systems. */ +/* #undef GMTIME_R_RETURNS_INT */ + +/* Define if va_copy macro or function is available. */ +#define HAS_VA_COPY 1 + +/* Define to 1 if you have the `access' function. */ +#define HAVE_ACCESS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the `bswap16' function. */ +/* #undef HAVE_BSWAP16 */ + +/* Define to 1 if you have the `bswap64' function. */ +/* #undef HAVE_BSWAP64 */ + +/* Define to 1 if bswap_16 is available via byteswap.h */ +/* #undef HAVE_BSWAP_16 */ + +/* Define to 1 if bswap_64 is available via byteswap.h */ +/* #undef HAVE_BSWAP_64 */ + +/* Define if bt_rseq is available, for recursive btree traversal. */ +#define HAVE_BT_RSEQ 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BYTESWAP_H */ + +/* Define to 1 if you have the `chmod' function. */ +#define HAVE_CHMOD 1 + +/* Define if cmocka library is available. */ +/* #undef HAVE_CMOCKA */ + +/* Define to 1 if you have the `compile' function. */ +/* #undef HAVE_COMPILE */ + +/* Define if com_err has compatible gettext support */ +#define HAVE_COM_ERR_INTL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CPUID_H */ + +/* Define to 1 if you have the `daemon' function. */ +#define HAVE_DAEMON 1 + +/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you + don't. */ +#define HAVE_DECL_STRERROR_R 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `dn_skipname' function. */ +#define HAVE_DN_SKIPNAME 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ENDIAN_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the `fchmod' function. */ +#define HAVE_FCHMOD 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `flock' function. */ +#define HAVE_FLOCK 1 + +/* Define to 1 if you have the `fnmatch' function. */ +#define HAVE_FNMATCH 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FNMATCH_H 1 + +/* Define if you have the getaddrinfo function */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `getenv' function. */ +#define HAVE_GETENV 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define if gethostbyname_r exists and its return type is known */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* Define to 1 if you have the `getnameinfo' function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define if system getopt should be used. */ +#define HAVE_GETOPT 1 + +/* Define if system getopt_long should be used. */ +#define HAVE_GETOPT_LONG 1 + +/* Define if getpwnam_r is available and useful. */ +#define HAVE_GETPWNAM_R 1 + +/* Define if getpwuid_r is available and useful. */ +#define HAVE_GETPWUID_R 1 + +/* Define if getservbyname_r exists and its return type is known */ +/* #undef HAVE_GETSERVBYNAME_R */ + +/* Have the gettimeofday function */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `getusershell' function. */ +#define HAVE_GETUSERSHELL 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `inet_ntop' function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have the `inet_pton' function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if the system has the type `int16_t'. */ +#define HAVE_INT16_T 1 + +/* Define to 1 if the system has the type `int32_t'. */ +#define HAVE_INT32_T 1 + +/* Define to 1 if the system has the type `int8_t'. */ +#define HAVE_INT8_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KEYUTILS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#define HAVE_LIBCRYPTO 1 + +/* Define if building with libedit. */ +/* #undef HAVE_LIBEDIT */ + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +/* #undef HAVE_LIBNSL */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +#define HAVE_LIBRESOLV 1 + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define if the util library is available */ +#define HAVE_LIBUTIL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MACHINE_BYTE_ORDER_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MACHINE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkstemp' function. */ +#define HAVE_MKSTEMP 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define if netdb.h declares h_errno */ +#define HAVE_NETDB_H_H_ERRNO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the `ns_initparse' function. */ +#define HAVE_NS_INITPARSE 1 + +/* Define to 1 if you have the `ns_name_uncompress' function. */ +#define HAVE_NS_NAME_UNCOMPRESS 1 + +/* Define if OpenSSL supports cms. */ +#define HAVE_OPENSSL_CMS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PATHS_H 1 + +/* Define if persistent keyrings are supported */ +/* #undef HAVE_PERSISTENT_KEYRING */ + +/* Define to 1 if you have the header file. */ +#define HAVE_POLL_H 1 + +/* Define if #pragma weak references work */ +/* #undef HAVE_PRAGMA_WEAK_REF */ + +/* Define if you have POSIX threads libraries and header files. */ +#define HAVE_PTHREAD 1 + +/* Define to 1 if you have the `pthread_once' function. */ +#define HAVE_PTHREAD_ONCE 1 + +/* Have PTHREAD_PRIO_INHERIT. */ +#define HAVE_PTHREAD_PRIO_INHERIT 1 + +/* Define to 1 if you have the `pthread_rwlock_init' function. */ +#define HAVE_PTHREAD_RWLOCK_INIT 1 + +/* Define if pthread_rwlock_init is provided in the thread library. */ +#define HAVE_PTHREAD_RWLOCK_INIT_IN_THREAD_LIB 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define if building with GNU Readline. */ +/* #undef HAVE_READLINE */ + +/* Define if regcomp exists and functions */ +#define HAVE_REGCOMP 1 + +/* Define to 1 if you have the `regexec' function. */ +#define HAVE_REGEXEC 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_REGEXPR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_REGEX_H 1 + +/* Define to 1 if you have the `res_nclose' function. */ +#define HAVE_RES_NCLOSE 1 + +/* Define to 1 if you have the `res_ndestroy' function. */ +#define HAVE_RES_NDESTROY 1 + +/* Define to 1 if you have the `res_ninit' function. */ +#define HAVE_RES_NINIT 1 + +/* Define to 1 if you have the `res_nsearch' function. */ +#define HAVE_RES_NSEARCH 1 + +/* Define to 1 if you have the `res_search' function */ +#define HAVE_RES_SEARCH 1 + +/* Define to 1 if you have the `re_comp' function. */ +/* #undef HAVE_RE_COMP */ + +/* Define to 1 if you have the `re_exec' function. */ +/* #undef HAVE_RE_EXEC */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SASL_SASL_H */ + +/* Define if struct sockaddr contains sa_len */ +#define HAVE_SA_LEN 1 + +/* Define to 1 if you have the `setegid' function. */ +#define HAVE_SETEGID 1 + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `seteuid' function. */ +#define HAVE_SETEUID 1 + +/* Define if setluid provided in OSF/1 security library */ +/* #undef HAVE_SETLUID */ + +/* Define to 1 if you have the `setregid' function. */ +#define HAVE_SETREGID 1 + +/* Define to 1 if you have the `setresgid' function. */ +/* #undef HAVE_SETRESGID */ + +/* Define to 1 if you have the `setresuid' function. */ +/* #undef HAVE_SETRESUID */ + +/* Define to 1 if you have the `setreuid' function. */ +#define HAVE_SETREUID 1 + +/* Define to 1 if you have the `setsid' function. */ +#define HAVE_SETSID 1 + +/* Define to 1 if you have the `setvbuf' function. */ +#define HAVE_SETVBUF 1 + +/* Define if there is a socklen_t type. If not, probably use size_t */ +#define HAVE_SOCKLEN_T 1 + +/* Define to 1 if you have the `srand' function. */ +#define HAVE_SRAND 1 + +/* Define to 1 if you have the `srand48' function. */ +#define HAVE_SRAND48 1 + +/* Define to 1 if you have the `srandom' function. */ +#define HAVE_SRANDOM 1 + +/* Define to 1 if the system has the type `ssize_t'. */ +#define HAVE_SSIZE_T 1 + +/* Define to 1 if you have the `stat' function. */ +#define HAVE_STAT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `step' function. */ +/* #undef HAVE_STEP */ + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +#define HAVE_STRLCPY 1 + +/* Define to 1 if you have the `strptime' function. */ +#define HAVE_STRPTIME 1 + +/* Define to 1 if the system has the type `struct cmsghdr'. */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* Define if there is a struct if_laddrconf. */ +/* #undef HAVE_STRUCT_IF_LADDRCONF */ + +/* Define to 1 if the system has the type `struct in6_pktinfo'. */ +#define HAVE_STRUCT_IN6_PKTINFO 1 + +/* Define to 1 if the system has the type `struct in_pktinfo'. */ +#define HAVE_STRUCT_IN_PKTINFO 1 + +/* Define if there is a struct lifconf. */ +/* #undef HAVE_STRUCT_LIFCONF */ + +/* Define to 1 if the system has the type `struct rt_msghdr'. */ +#define HAVE_STRUCT_RT_MSGHDR 1 + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_MTIMENSEC */ + +/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 + +/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_BSWAP_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define if sys_errlist in libc */ +#define HAVE_SYS_ERRLIST 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define if tcl.h found */ +/* #undef HAVE_TCL_H */ + +/* Define if tcl/tcl.h found */ +/* #undef HAVE_TCL_TCL_H */ + +/* Define to 1 if you have the `timegm' function. */ +#define HAVE_TIMEGM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#define HAVE_UNSETENV 1 + +/* Define to 1 if the system has the type `u_char'. */ +#define HAVE_U_CHAR 1 + +/* Define to 1 if the system has the type `u_int'. */ +#define HAVE_U_INT 1 + +/* Define to 1 if the system has the type `u_int16_t'. */ +#define HAVE_U_INT16_T 1 + +/* Define to 1 if the system has the type `u_int32_t'. */ +#define HAVE_U_INT32_T 1 + +/* Define to 1 if the system has the type `u_int8_t'. */ +#define HAVE_U_INT8_T 1 + +/* Define to 1 if the system has the type `u_long'. */ +#define HAVE_U_LONG 1 + +/* Define to 1 if you have the `vasprintf' function. */ +#define HAVE_VASPRINTF 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `vsprintf' function. */ +#define HAVE_VSPRINTF 1 + +/* Define to 1 if the system has the type `__int128_t'. */ +#define HAVE___INT128_T 1 + +/* Define to 1 if the system has the type `__uint128_t'. */ +#define HAVE___UINT128_T 1 + +/* Define if errno.h declares perror */ +/* #undef HDR_HAS_PERROR */ + +/* May need to be defined to enable IPv6 support, for example on IRIX */ +/* #undef INET6 */ + +/* Define if MIT Project Athena default configuration should be used */ +/* #undef KRB5_ATHENA_COMPAT */ + +/* Define for DNS support of locating realms and KDCs */ +#undef KRB5_DNS_LOOKUP + +/* Define to enable DNS lookups of Kerberos realm names */ +/* #undef KRB5_DNS_LOOKUP_REALM */ + +/* Define if the KDC should return only vague error codes to clients */ +/* #undef KRBCONF_VAGUE_ERRORS */ + +/* define if the system header files are missing prototype for daemon() */ +#define NEED_DAEMON_PROTO 1 + +/* Define if in6addr_any is not defined in libc */ +#define NEED_INSIXADDR_ANY 1 + +/* define if the system header files are missing prototype for + ss_execute_command() */ +/* #undef NEED_SS_EXECUTE_COMMAND_PROTO */ + +/* define if the system header files are missing prototype for strptime() */ +/* #undef NEED_STRPTIME_PROTO */ + +/* define if the system header files are missing prototype for swab() */ +/* #undef NEED_SWAB_PROTO */ + +/* Define if need to declare sys_errlist */ +/* #undef NEED_SYS_ERRLIST */ + +/* define if the system header files are missing prototype for vasprintf() */ +/* #undef NEED_VASPRINTF_PROTO */ + +/* Define if the KDC should use no lookaside cache */ +/* #undef NOCACHE */ + +/* Define if references to pthread routines should be non-weak. */ +/* #undef NO_WEAK_PTHREADS */ + +/* Define if lex produes code with yylineno */ +/* #undef NO_YYLINENO */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "krb5-bugs@mit.edu" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Kerberos 5" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Kerberos 5 1.17.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "krb5" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.17.1" + +/* Define if setjmp indicates POSIX interface */ +#define POSIX_SETJMP 1 + +/* Define if POSIX signal handling is used */ +#define POSIX_SIGNALS 1 + +/* Define if POSIX signal handlers are used */ +#define POSIX_SIGTYPE 1 + +/* Define if termios.h exists and tcsetattr exists */ +#define POSIX_TERMIOS 1 + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define as return type of setrpcent */ +#define SETRPCENT_TYPE void + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* Define to use OpenSSL for SPAKE preauth */ +#define SPAKE_OPENSSL 1 + +/* Define for static plugin linkage */ +/* #undef STATIC_PLUGINS */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if strerror_r returns char *. */ +/* #undef STRERROR_R_CHAR_P */ + +/* Define if sys_errlist is defined in errno.h */ +#define SYS_ERRLIST_DECLARED 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if no TLS implementation is selected */ +/* #undef TLS_IMPL_NONE */ + +/* Define if TLS implementation is OpenSSL */ +#define TLS_IMPL_OPENSSL 1 + +/* Define if you have dirent.h functionality */ +#define USE_DIRENT_H 1 + +/* Define if dlopen should be used */ +#define USE_DLOPEN 1 + +/* Define if the keyring ccache should be enabled */ +/* #undef USE_KEYRING_CCACHE */ + +/* Define if link-time options for library finalization will be used */ +/* #undef USE_LINKER_FINI_OPTION */ + +/* Define if link-time options for library initialization will be used */ +/* #undef USE_LINKER_INIT_OPTION */ + +/* Define if sigprocmask should be used */ +#define USE_SIGPROCMASK 1 + +/* Define if wait takes int as a argument */ +#define WAIT_USES_INT 1 + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#define YYTEXT_POINTER 1 + +/* Define to enable extensions in glibc */ +#define _GNU_SOURCE 1 + +/* Define to enable C11 extensions */ +#define __STDC_WANT_LIB_EXT1__ 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define krb5_sigtype to type of signal handler */ +#define krb5_sigtype void + +/* Define to `int' if does not define. */ +/* #undef mode_t */ + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to `long' if does not define. */ +/* #undef time_t */ + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + + +#if defined(__GNUC__) && !defined(inline) +/* Silence gcc pedantic warnings about ANSI C. */ +# define inline __inline__ +#endif +#endif /* KRB5_AUTOCONF_H */ diff --git a/contrib/krb5-cmake/autoconf.h b/contrib/krb5-cmake/autoconf_linux.h similarity index 100% rename from contrib/krb5-cmake/autoconf.h rename to contrib/krb5-cmake/autoconf_linux.h diff --git a/contrib/mariadb-connector-c b/contrib/mariadb-connector-c index 21f451d4d31..f4476ee7311 160000 --- a/contrib/mariadb-connector-c +++ b/contrib/mariadb-connector-c @@ -1 +1 @@ -Subproject commit 21f451d4d3157ffed31ec60a8b76c407190e66bd +Subproject commit f4476ee7311b35b593750f6ae2cbdb62a4006374 diff --git a/contrib/nuraft-cmake/CMakeLists.txt b/contrib/nuraft-cmake/CMakeLists.txt index e5bb7f7d11b..83137fe73bf 100644 --- a/contrib/nuraft-cmake/CMakeLists.txt +++ b/contrib/nuraft-cmake/CMakeLists.txt @@ -30,7 +30,12 @@ set(SRCS add_library(nuraft ${SRCS}) -target_compile_definitions(nuraft PRIVATE USE_BOOST_ASIO=1 BOOST_ASIO_STANDALONE=1) + +if (NOT OPENSSL_SSL_LIBRARY OR NOT OPENSSL_CRYPTO_LIBRARY) + target_compile_definitions(nuraft PRIVATE USE_BOOST_ASIO=1 BOOST_ASIO_STANDALONE=1 SSL_LIBRARY_NOT_FOUND=1) +else() + target_compile_definitions(nuraft PRIVATE USE_BOOST_ASIO=1 BOOST_ASIO_STANDALONE=1) +endif() target_include_directories (nuraft SYSTEM PRIVATE ${LIBRARY_DIR}/include/libnuraft) # for some reason include "asio.h" directly without "boost/" prefix. diff --git a/contrib/poco b/contrib/poco index fbaaba4a02e..c55b91f394e 160000 --- a/contrib/poco +++ b/contrib/poco @@ -1 +1 @@ -Subproject commit fbaaba4a02e29987b8c584747a496c79528f125f +Subproject commit c55b91f394efa9c238c33957682501681ef9b716 diff --git a/debian/changelog b/debian/changelog index 53b36cae114..23d63b41099 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -clickhouse (21.3.1.1) unstable; urgency=low +clickhouse (21.4.1.1) unstable; urgency=low * Modified source code - -- clickhouse-release Mon, 01 Feb 2021 12:50:53 +0300 + -- clickhouse-release Sat, 06 Mar 2021 14:43:27 +0300 diff --git a/docker/client/Dockerfile b/docker/client/Dockerfile index 43921a4d3c4..8443eae691b 100644 --- a/docker/client/Dockerfile +++ b/docker/client/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:18.04 ARG repository="deb https://repo.clickhouse.tech/deb/stable/ main/" -ARG version=21.3.1.* +ARG version=21.4.1.* RUN apt-get update \ && apt-get install --yes --no-install-recommends \ diff --git a/docker/server/Dockerfile b/docker/server/Dockerfile index 8e39af5646c..295784a6184 100644 --- a/docker/server/Dockerfile +++ b/docker/server/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:20.04 ARG repository="deb https://repo.clickhouse.tech/deb/stable/ main/" -ARG version=21.3.1.* +ARG version=21.4.1.* ARG gosu_ver=1.10 # user/group precreated explicitly with fixed uid/gid on purpose. diff --git a/docker/server/README.md b/docker/server/README.md index d8e9204dffa..6f799d68185 100644 --- a/docker/server/README.md +++ b/docker/server/README.md @@ -56,7 +56,7 @@ $ echo 'SELECT version()' | curl 'http://localhost:8123/' --data-binary @- 20.12.3.3 ``` -### Volumes +### Volumes Typically you may want to mount the following folders inside your container to archieve persistency: @@ -76,7 +76,7 @@ You may also want to mount: * `/etc/clickhouse-server/usert.d/*.xml` - files with use settings adjustmenets * `/docker-entrypoint-initdb.d/` - folder with database initialization scripts (see below). -### Linux capabilities +### Linux capabilities ClickHouse has some advanced functionality which requite enabling several [linux capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html). @@ -113,10 +113,10 @@ $ docker run --rm -e CLICKHOUSE_UID=0 -e CLICKHOUSE_GID=0 --name clickhouse-serv ### How to create default database and user on starting -Sometimes you may want to create user (user named `default` is used by default) and database on image starting. You can do it using environment variables `CLICKHOUSE_DB`, `CLICKHOUSE_USER` and `CLICKHOUSE_PASSWORD`: +Sometimes you may want to create user (user named `default` is used by default) and database on image starting. You can do it using environment variables `CLICKHOUSE_DB`, `CLICKHOUSE_USER`, `CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT` and `CLICKHOUSE_PASSWORD`: ``` -$ docker run --rm -e CLICKHOUSE_DB=my_database -e CLICKHOUSE_USER=username -e CLICKHOUSE_PASSWORD=password -p 9000:9000/tcp yandex/clickhouse-server +$ docker run --rm -e CLICKHOUSE_DB=my_database -e CLICKHOUSE_USER=username -e CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1 -e CLICKHOUSE_PASSWORD=password -p 9000:9000/tcp yandex/clickhouse-server ``` ## How to extend this image diff --git a/docker/server/entrypoint.sh b/docker/server/entrypoint.sh index 549ff601c59..0138a165505 100755 --- a/docker/server/entrypoint.sh +++ b/docker/server/entrypoint.sh @@ -54,6 +54,7 @@ FORMAT_SCHEMA_PATH="$(clickhouse extract-from-config --config-file "$CLICKHOUSE_ CLICKHOUSE_USER="${CLICKHOUSE_USER:-default}" CLICKHOUSE_PASSWORD="${CLICKHOUSE_PASSWORD:-}" CLICKHOUSE_DB="${CLICKHOUSE_DB:-}" +CLICKHOUSE_ACCESS_MANAGEMENT="${CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT:-0}" for dir in "$DATA_DIR" \ "$ERROR_LOG_DIR" \ @@ -97,6 +98,7 @@ if [ -n "$CLICKHOUSE_USER" ] && [ "$CLICKHOUSE_USER" != "default" ] || [ -n "$CL ${CLICKHOUSE_PASSWORD} default + ${CLICKHOUSE_ACCESS_MANAGEMENT} diff --git a/docker/test/Dockerfile b/docker/test/Dockerfile index f151ae8fddf..e727d2a3ecf 100644 --- a/docker/test/Dockerfile +++ b/docker/test/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:18.04 ARG repository="deb https://repo.clickhouse.tech/deb/stable/ main/" -ARG version=21.3.1.* +ARG version=21.4.1.* RUN apt-get update && \ apt-get install -y apt-transport-https dirmngr && \ diff --git a/docker/test/fasttest/Dockerfile b/docker/test/fasttest/Dockerfile index 03b7b2fc53a..64be52d8e30 100644 --- a/docker/test/fasttest/Dockerfile +++ b/docker/test/fasttest/Dockerfile @@ -47,6 +47,7 @@ RUN apt-get update \ expect \ fakeroot \ git \ + gdb \ gperf \ lld-${LLVM_VERSION} \ llvm-${LLVM_VERSION} \ diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index a8aa852ca5b..649f9f812e1 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -70,6 +70,7 @@ function start_server --path "$FASTTEST_DATA" --user_files_path "$FASTTEST_DATA/user_files" --top_level_domains_path "$FASTTEST_DATA/top_level_domains" + --test_keeper_server.log_storage_path "$FASTTEST_DATA/coordination" ) clickhouse-server "${opts[@]}" &>> "$FASTTEST_OUTPUT/server.log" & server_pid=$! @@ -107,6 +108,18 @@ function start_server fi echo "ClickHouse server pid '$server_pid' started and responded" + + echo " +handle all noprint +handle SIGSEGV stop print +handle SIGBUS stop print +handle SIGABRT stop print +continue +thread apply all backtrace +continue +" > script.gdb + + gdb -batch -command script.gdb -p "$server_pid" & } function clone_root @@ -138,6 +151,7 @@ function clone_submodules cd "$FASTTEST_SOURCE" SUBMODULES_TO_UPDATE=( + contrib/abseil-cpp contrib/antlr4-runtime contrib/boost contrib/zlib-ng @@ -163,6 +177,7 @@ function clone_submodules contrib/xz contrib/dragonbox contrib/fast_float + contrib/NuRaft ) git submodule sync @@ -182,6 +197,7 @@ function run_cmake "-DENABLE_EMBEDDED_COMPILER=0" "-DENABLE_THINLTO=0" "-DUSE_UNWIND=1" + "-DENABLE_NURAFT=1" ) # TODO remove this? we don't use ccache anyway. An option would be to download it @@ -257,6 +273,7 @@ function run_tests 00929_multi_match_edit_distance 01681_hyperscan_debug_assertion + 01176_mysql_client_interactive # requires mysql client 01031_mutations_interpreter_and_context 01053_ssd_dictionary # this test mistakenly requires acces to /var/lib/clickhouse -- can't run this locally, disabled 01083_expressions_in_engine_arguments @@ -324,7 +341,7 @@ function run_tests # Look at DistributedFilesToInsert, so cannot run in parallel. 01460_DistributedFilesToInsert - 01541_max_memory_usage_for_user + 01541_max_memory_usage_for_user_long # Require python libraries like scipy, pandas and numpy 01322_ttest_scipy @@ -342,7 +359,7 @@ function run_tests 01666_blns ) - time clickhouse-test --hung-check -j 8 --order=random --use-skip-list --no-long --testname --shard --zookeeper --skip "${TESTS_TO_SKIP[@]}" -- "$FASTTEST_FOCUS" 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee "$FASTTEST_OUTPUT/test_log.txt" + (time clickhouse-test --hung-check -j 8 --order=random --use-skip-list --no-long --testname --shard --zookeeper --skip "${TESTS_TO_SKIP[@]}" -- "$FASTTEST_FOCUS" 2>&1 ||:) | ts '%Y-%m-%d %H:%M:%S' | tee "$FASTTEST_OUTPUT/test_log.txt" # substr is to remove semicolon after test name readarray -t FAILED_TESTS < <(awk '/\[ FAIL|TIMEOUT|ERROR \]/ { print substr($3, 1, length($3)-1) }' "$FASTTEST_OUTPUT/test_log.txt" | tee "$FASTTEST_OUTPUT/failed-parallel-tests.txt") @@ -359,7 +376,7 @@ function run_tests stop_server ||: # Clean the data so that there is no interference from the previous test run. - rm -rf "$FASTTEST_DATA"/{{meta,}data,user_files} ||: + rm -rf "$FASTTEST_DATA"/{{meta,}data,user_files,coordination} ||: start_server diff --git a/docker/test/integration/base/Dockerfile b/docker/test/integration/base/Dockerfile index 4963ff0094d..938d8d45ffd 100644 --- a/docker/test/integration/base/Dockerfile +++ b/docker/test/integration/base/Dockerfile @@ -18,7 +18,8 @@ RUN apt-get update \ curl \ tar \ krb5-user \ - iproute2 + iproute2 \ + lsof RUN rm -rf \ /var/lib/apt/lists/* \ /var/cache/debconf \ diff --git a/docker/test/integration/runner/Dockerfile b/docker/test/integration/runner/Dockerfile index 502dc3736b2..e0e5e36a3d6 100644 --- a/docker/test/integration/runner/Dockerfile +++ b/docker/test/integration/runner/Dockerfile @@ -58,7 +58,7 @@ RUN dockerd --version; docker --version RUN python3 -m pip install \ PyMySQL \ - aerospike \ + aerospike==4.0.0 \ avro \ cassandra-driver \ confluent-kafka==1.5.0 \ diff --git a/docker/test/integration/runner/compose/docker_compose_cassandra.yml b/docker/test/integration/runner/compose/docker_compose_cassandra.yml index 6567a352027..c5cdfac5ce7 100644 --- a/docker/test/integration/runner/compose/docker_compose_cassandra.yml +++ b/docker/test/integration/runner/compose/docker_compose_cassandra.yml @@ -4,4 +4,4 @@ services: image: cassandra restart: always ports: - - 9043:9042 + - 9043:9042 diff --git a/docker/test/integration/runner/compose/docker_compose_hdfs.yml b/docker/test/integration/runner/compose/docker_compose_hdfs.yml index b8cd7f64273..43dd1aa43d3 100644 --- a/docker/test/integration/runner/compose/docker_compose_hdfs.yml +++ b/docker/test/integration/runner/compose/docker_compose_hdfs.yml @@ -5,6 +5,6 @@ services: hostname: hdfs1 restart: always ports: - - 50075:50075 - - 50070:50070 + - 50075:50075 + - 50070:50070 entrypoint: /etc/bootstrap.sh -d diff --git a/docker/test/integration/runner/compose/docker_compose_kafka.yml b/docker/test/integration/runner/compose/docker_compose_kafka.yml index 219d977ffd9..b77542f7e11 100644 --- a/docker/test/integration/runner/compose/docker_compose_kafka.yml +++ b/docker/test/integration/runner/compose/docker_compose_kafka.yml @@ -5,42 +5,42 @@ services: image: zookeeper:3.4.9 hostname: kafka_zookeeper environment: - ZOO_MY_ID: 1 - ZOO_PORT: 2181 - ZOO_SERVERS: server.1=kafka_zookeeper:2888:3888 + ZOO_MY_ID: 1 + ZOO_PORT: 2181 + ZOO_SERVERS: server.1=kafka_zookeeper:2888:3888 security_opt: - - label:disable + - label:disable kafka1: image: confluentinc/cp-kafka:5.2.0 hostname: kafka1 ports: - - "9092:9092" + - "9092:9092" environment: - KAFKA_ADVERTISED_LISTENERS: INSIDE://localhost:9092,OUTSIDE://kafka1:19092 - KAFKA_LISTENERS: INSIDE://:9092,OUTSIDE://:19092 - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT - KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE - KAFKA_BROKER_ID: 1 - KAFKA_ZOOKEEPER_CONNECT: "kafka_zookeeper:2181" - KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO" - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_ADVERTISED_LISTENERS: INSIDE://localhost:9092,OUTSIDE://kafka1:19092 + KAFKA_LISTENERS: INSIDE://:9092,OUTSIDE://:19092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE + KAFKA_BROKER_ID: 1 + KAFKA_ZOOKEEPER_CONNECT: "kafka_zookeeper:2181" + KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO" + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 depends_on: - - kafka_zookeeper + - kafka_zookeeper security_opt: - - label:disable + - label:disable schema-registry: image: confluentinc/cp-schema-registry:5.2.0 hostname: schema-registry ports: - - "8081:8081" + - "8081:8081" environment: - SCHEMA_REGISTRY_HOST_NAME: schema-registry - SCHEMA_REGISTRY_KAFKASTORE_SECURITY_PROTOCOL: PLAINTEXT - SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: PLAINTEXT://kafka1:19092 + SCHEMA_REGISTRY_HOST_NAME: schema-registry + SCHEMA_REGISTRY_KAFKASTORE_SECURITY_PROTOCOL: PLAINTEXT + SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: PLAINTEXT://kafka1:19092 depends_on: - - kafka_zookeeper - - kafka1 + - kafka_zookeeper + - kafka1 security_opt: - - label:disable + - label:disable diff --git a/docker/test/integration/runner/compose/docker_compose_kerberized_hdfs.yml b/docker/test/integration/runner/compose/docker_compose_kerberized_hdfs.yml index f2a659bce58..e2e15975e22 100644 --- a/docker/test/integration/runner/compose/docker_compose_kerberized_hdfs.yml +++ b/docker/test/integration/runner/compose/docker_compose_kerberized_hdfs.yml @@ -8,22 +8,22 @@ services: hostname: kerberizedhdfs1 restart: always volumes: - - ${KERBERIZED_HDFS_DIR}/../../hdfs_configs/bootstrap.sh:/etc/bootstrap.sh:ro - - ${KERBERIZED_HDFS_DIR}/secrets:/usr/local/hadoop/etc/hadoop/conf - - ${KERBERIZED_HDFS_DIR}/secrets/krb_long.conf:/etc/krb5.conf:ro + - ${KERBERIZED_HDFS_DIR}/../../hdfs_configs/bootstrap.sh:/etc/bootstrap.sh:ro + - ${KERBERIZED_HDFS_DIR}/secrets:/usr/local/hadoop/etc/hadoop/conf + - ${KERBERIZED_HDFS_DIR}/secrets/krb_long.conf:/etc/krb5.conf:ro ports: - 1006:1006 - 50070:50070 - 9010:9010 depends_on: - - hdfskerberos + - hdfskerberos entrypoint: /etc/bootstrap.sh -d hdfskerberos: image: yandex/clickhouse-kerberos-kdc:${DOCKER_KERBEROS_KDC_TAG} hostname: hdfskerberos volumes: - - ${KERBERIZED_HDFS_DIR}/secrets:/tmp/keytab - - ${KERBERIZED_HDFS_DIR}/../../kerberos_image_config.sh:/config.sh - - /dev/urandom:/dev/random + - ${KERBERIZED_HDFS_DIR}/secrets:/tmp/keytab + - ${KERBERIZED_HDFS_DIR}/../../kerberos_image_config.sh:/config.sh + - /dev/urandom:/dev/random ports: [88, 749] diff --git a/docker/test/integration/runner/compose/docker_compose_kerberized_kafka.yml b/docker/test/integration/runner/compose/docker_compose_kerberized_kafka.yml index 6e1e11344bb..64a3ef3e956 100644 --- a/docker/test/integration/runner/compose/docker_compose_kerberized_kafka.yml +++ b/docker/test/integration/runner/compose/docker_compose_kerberized_kafka.yml @@ -6,54 +6,54 @@ services: # restart: always hostname: kafka_kerberized_zookeeper environment: - ZOOKEEPER_SERVER_ID: 1 - ZOOKEEPER_CLIENT_PORT: 2181 - ZOOKEEPER_SERVERS: "kafka_kerberized_zookeeper:2888:3888" - KAFKA_OPTS: "-Djava.security.auth.login.config=/etc/kafka/secrets/zookeeper_jaas.conf -Djava.security.krb5.conf=/etc/kafka/secrets/krb.conf -Dzookeeper.authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider -Dsun.security.krb5.debug=true" + ZOOKEEPER_SERVER_ID: 1 + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_SERVERS: "kafka_kerberized_zookeeper:2888:3888" + KAFKA_OPTS: "-Djava.security.auth.login.config=/etc/kafka/secrets/zookeeper_jaas.conf -Djava.security.krb5.conf=/etc/kafka/secrets/krb.conf -Dzookeeper.authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider -Dsun.security.krb5.debug=true" volumes: - - ${KERBERIZED_KAFKA_DIR}/secrets:/etc/kafka/secrets - - /dev/urandom:/dev/random + - ${KERBERIZED_KAFKA_DIR}/secrets:/etc/kafka/secrets + - /dev/urandom:/dev/random depends_on: - - kafka_kerberos + - kafka_kerberos security_opt: - - label:disable + - label:disable kerberized_kafka1: image: confluentinc/cp-kafka:5.2.0 # restart: always hostname: kerberized_kafka1 ports: - - "9092:9092" - - "9093:9093" + - "9092:9092" + - "9093:9093" environment: - KAFKA_LISTENERS: OUTSIDE://:19092,UNSECURED_OUTSIDE://:19093,UNSECURED_INSIDE://:9093 - KAFKA_ADVERTISED_LISTENERS: OUTSIDE://kerberized_kafka1:19092,UNSECURED_OUTSIDE://kerberized_kafka1:19093,UNSECURED_INSIDE://localhost:9093 - # KAFKA_LISTENERS: INSIDE://kerberized_kafka1:9092,OUTSIDE://kerberized_kafka1:19092 - # KAFKA_ADVERTISED_LISTENERS: INSIDE://localhost:9092,OUTSIDE://kerberized_kafka1:19092 - KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: GSSAPI - KAFKA_SASL_ENABLED_MECHANISMS: GSSAPI - KAFKA_SASL_KERBEROS_SERVICE_NAME: kafka - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: OUTSIDE:SASL_PLAINTEXT,UNSECURED_OUTSIDE:PLAINTEXT,UNSECURED_INSIDE:PLAINTEXT, - KAFKA_INTER_BROKER_LISTENER_NAME: OUTSIDE - KAFKA_BROKER_ID: 1 - KAFKA_ZOOKEEPER_CONNECT: "kafka_kerberized_zookeeper:2181" - KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO" - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 - KAFKA_OPTS: "-Djava.security.auth.login.config=/etc/kafka/secrets/broker_jaas.conf -Djava.security.krb5.conf=/etc/kafka/secrets/krb.conf -Dsun.security.krb5.debug=true" + KAFKA_LISTENERS: OUTSIDE://:19092,UNSECURED_OUTSIDE://:19093,UNSECURED_INSIDE://:9093 + KAFKA_ADVERTISED_LISTENERS: OUTSIDE://kerberized_kafka1:19092,UNSECURED_OUTSIDE://kerberized_kafka1:19093,UNSECURED_INSIDE://localhost:9093 + # KAFKA_LISTENERS: INSIDE://kerberized_kafka1:9092,OUTSIDE://kerberized_kafka1:19092 + # KAFKA_ADVERTISED_LISTENERS: INSIDE://localhost:9092,OUTSIDE://kerberized_kafka1:19092 + KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: GSSAPI + KAFKA_SASL_ENABLED_MECHANISMS: GSSAPI + KAFKA_SASL_KERBEROS_SERVICE_NAME: kafka + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: OUTSIDE:SASL_PLAINTEXT,UNSECURED_OUTSIDE:PLAINTEXT,UNSECURED_INSIDE:PLAINTEXT, + KAFKA_INTER_BROKER_LISTENER_NAME: OUTSIDE + KAFKA_BROKER_ID: 1 + KAFKA_ZOOKEEPER_CONNECT: "kafka_kerberized_zookeeper:2181" + KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO" + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_OPTS: "-Djava.security.auth.login.config=/etc/kafka/secrets/broker_jaas.conf -Djava.security.krb5.conf=/etc/kafka/secrets/krb.conf -Dsun.security.krb5.debug=true" volumes: - - ${KERBERIZED_KAFKA_DIR}/secrets:/etc/kafka/secrets - - /dev/urandom:/dev/random + - ${KERBERIZED_KAFKA_DIR}/secrets:/etc/kafka/secrets + - /dev/urandom:/dev/random depends_on: - - kafka_kerberized_zookeeper - - kafka_kerberos + - kafka_kerberized_zookeeper + - kafka_kerberos security_opt: - - label:disable + - label:disable kafka_kerberos: image: yandex/clickhouse-kerberos-kdc:${DOCKER_KERBEROS_KDC_TAG:-latest} hostname: kafka_kerberos volumes: - - ${KERBERIZED_KAFKA_DIR}/secrets:/tmp/keytab - - ${KERBERIZED_KAFKA_DIR}/../../kerberos_image_config.sh:/config.sh - - /dev/urandom:/dev/random + - ${KERBERIZED_KAFKA_DIR}/secrets:/tmp/keytab + - ${KERBERIZED_KAFKA_DIR}/../../kerberos_image_config.sh:/config.sh + - /dev/urandom:/dev/random ports: [88, 749] diff --git a/docker/test/integration/runner/compose/docker_compose_mongo.yml b/docker/test/integration/runner/compose/docker_compose_mongo.yml index 8c54544ed88..6c98fde2303 100644 --- a/docker/test/integration/runner/compose/docker_compose_mongo.yml +++ b/docker/test/integration/runner/compose/docker_compose_mongo.yml @@ -7,5 +7,5 @@ services: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: clickhouse ports: - - 27018:27017 + - 27018:27017 command: --profile=2 --verbose diff --git a/docker/test/integration/runner/compose/docker_compose_mysql.yml b/docker/test/integration/runner/compose/docker_compose_mysql.yml index 90daf8a4238..5b15d517f37 100644 --- a/docker/test/integration/runner/compose/docker_compose_mysql.yml +++ b/docker/test/integration/runner/compose/docker_compose_mysql.yml @@ -6,5 +6,5 @@ services: environment: MYSQL_ROOT_PASSWORD: clickhouse ports: - - 3308:3306 + - 3308:3306 command: --server_id=100 --log-bin='mysql-bin-1.log' --default-time-zone='+3:00' --gtid-mode="ON" --enforce-gtid-consistency diff --git a/docker/test/integration/runner/compose/docker_compose_mysql_5_7_for_materialize_mysql.yml b/docker/test/integration/runner/compose/docker_compose_mysql_5_7_for_materialize_mysql.yml index e7d762203ee..5aa13ba91c7 100644 --- a/docker/test/integration/runner/compose/docker_compose_mysql_5_7_for_materialize_mysql.yml +++ b/docker/test/integration/runner/compose/docker_compose_mysql_5_7_for_materialize_mysql.yml @@ -6,5 +6,9 @@ services: environment: MYSQL_ROOT_PASSWORD: clickhouse ports: - - 3308:3306 - command: --server_id=100 --log-bin='mysql-bin-1.log' --default-time-zone='+3:00' --gtid-mode="ON" --enforce-gtid-consistency + - 3308:3306 + command: --server_id=100 --log-bin='mysql-bin-1.log' + --default-time-zone='+3:00' + --gtid-mode="ON" + --enforce-gtid-consistency + --log-error-verbosity=3 diff --git a/docker/test/integration/runner/compose/docker_compose_mysql_8_0_for_materialize_mysql.yml b/docker/test/integration/runner/compose/docker_compose_mysql_8_0_for_materialize_mysql.yml index 918a2b5f80f..7c8a930c84e 100644 --- a/docker/test/integration/runner/compose/docker_compose_mysql_8_0_for_materialize_mysql.yml +++ b/docker/test/integration/runner/compose/docker_compose_mysql_8_0_for_materialize_mysql.yml @@ -6,5 +6,10 @@ services: environment: MYSQL_ROOT_PASSWORD: clickhouse ports: - - 33308:3306 - command: --server_id=100 --log-bin='mysql-bin-1.log' --default_authentication_plugin='mysql_native_password' --default-time-zone='+3:00' --gtid-mode="ON" --enforce-gtid-consistency + - 33308:3306 + command: --server_id=100 --log-bin='mysql-bin-1.log' + --default_authentication_plugin='mysql_native_password' + --default-time-zone='+3:00' + --gtid-mode="ON" + --enforce-gtid-consistency + --log-error-verbosity=3 diff --git a/docker/test/integration/runner/compose/docker_compose_mysql_client.yml b/docker/test/integration/runner/compose/docker_compose_mysql_client.yml index 802151c4d7b..5e4565d64c3 100644 --- a/docker/test/integration/runner/compose/docker_compose_mysql_client.yml +++ b/docker/test/integration/runner/compose/docker_compose_mysql_client.yml @@ -7,7 +7,7 @@ services: MYSQL_ALLOW_EMPTY_PASSWORD: 1 command: --federated --socket /var/run/mysqld/mysqld.sock healthcheck: - test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"] + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 1s timeout: 2s retries: 100 diff --git a/docker/test/integration/runner/compose/docker_compose_postgesql.yml b/docker/test/integration/runner/compose/docker_compose_postgesql.yml index 984f5f97384..90764188ddd 100644 --- a/docker/test/integration/runner/compose/docker_compose_postgesql.yml +++ b/docker/test/integration/runner/compose/docker_compose_postgesql.yml @@ -11,4 +11,4 @@ services: ports: - "5433:5433" environment: - POSTGRES_HOST_AUTH_METHOD: "trust" \ No newline at end of file + POSTGRES_HOST_AUTH_METHOD: "trust" diff --git a/docker/test/integration/runner/compose/docker_compose_postgres.yml b/docker/test/integration/runner/compose/docker_compose_postgres.yml index fff4fb1fa42..5657352e1b3 100644 --- a/docker/test/integration/runner/compose/docker_compose_postgres.yml +++ b/docker/test/integration/runner/compose/docker_compose_postgres.yml @@ -6,8 +6,8 @@ services: environment: POSTGRES_PASSWORD: mysecretpassword ports: - - 5432:5432 + - 5432:5432 networks: - default: - aliases: - - postgre-sql.local + default: + aliases: + - postgre-sql.local diff --git a/docker/test/integration/runner/compose/docker_compose_redis.yml b/docker/test/integration/runner/compose/docker_compose_redis.yml index 72df99ec59b..3d834aadaa4 100644 --- a/docker/test/integration/runner/compose/docker_compose_redis.yml +++ b/docker/test/integration/runner/compose/docker_compose_redis.yml @@ -4,5 +4,5 @@ services: image: redis restart: always ports: - - 6380:6379 + - 6380:6379 command: redis-server --requirepass "clickhouse" --databases 32 diff --git a/docker/test/integration/runner/compose/docker_compose_zookeeper.yml b/docker/test/integration/runner/compose/docker_compose_zookeeper.yml index 49e285b5515..1601d217a25 100644 --- a/docker/test/integration/runner/compose/docker_compose_zookeeper.yml +++ b/docker/test/integration/runner/compose/docker_compose_zookeeper.yml @@ -1,11 +1,11 @@ version: '2.3' services: zoo1: - image: zookeeper:3.4.12 + image: zookeeper:3.6.2 restart: always environment: ZOO_TICK_TIME: 500 - ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888 + ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 ZOO_MY_ID: 1 JVMFLAGS: -Dzookeeper.forceSync=no volumes: @@ -16,11 +16,11 @@ services: source: ${ZK_DATA_LOG1:-} target: /datalog zoo2: - image: zookeeper:3.4.12 + image: zookeeper:3.6.2 restart: always environment: ZOO_TICK_TIME: 500 - ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888 + ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888 ZOO_MY_ID: 2 JVMFLAGS: -Dzookeeper.forceSync=no volumes: @@ -31,11 +31,11 @@ services: source: ${ZK_DATA_LOG2:-} target: /datalog zoo3: - image: zookeeper:3.4.12 + image: zookeeper:3.6.2 restart: always environment: ZOO_TICK_TIME: 500 - ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888 + ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 ZOO_MY_ID: 3 JVMFLAGS: -Dzookeeper.forceSync=no volumes: diff --git a/docker/test/performance-comparison/compare.sh b/docker/test/performance-comparison/compare.sh index 9a0d8093a55..4d862cf987e 100755 --- a/docker/test/performance-comparison/compare.sh +++ b/docker/test/performance-comparison/compare.sh @@ -97,6 +97,7 @@ function configure rm -r right/db ||: rm -r db0/preprocessed_configs ||: rm -r db0/{data,metadata}/system ||: + rm db0/status ||: cp -al db0/ left/db/ cp -al db0/ right/db/ } @@ -357,6 +358,8 @@ mkdir analyze analyze/tmp ||: build_log_column_definitions # Split the raw test output into files suitable for analysis. +# To debug calculations only for a particular test, substitute a suitable +# wildcard here, e.g. `for test_file in modulo-raw.tsv`. for test_file in *-raw.tsv do test_name=$(basename "$test_file" "-raw.tsv") @@ -466,7 +469,13 @@ create view broken_queries as create table query_run_metrics_for_stats engine File( TSV, -- do not add header -- will parse with grep 'analyze/query-run-metrics-for-stats.tsv') - as select test, query_index, 0 run, version, metric_values + as select test, query_index, 0 run, version, + -- For debugging, add a filter for a particular metric like this: + -- arrayFilter(m, n -> n = 'client_time', metric_values, metric_names) + -- metric_values + -- Note that further reporting may break, because the metric names are + -- not filtered. + metric_values from query_run_metric_arrays where (test, query_index) not in broken_queries order by test, query_index, run, version @@ -584,8 +593,19 @@ create view query_metric_stats as -- Main statistics for queries -- query time as reported in query log. create table queries engine File(TSVWithNamesAndTypes, 'report/queries.tsv') as select - abs(diff) > report_threshold and abs(diff) > stat_threshold as changed_fail, - abs(diff) > report_threshold - 0.05 and abs(diff) > stat_threshold as changed_show, + -- It is important to have a non-strict inequality with stat_threshold + -- here. The randomization distribution is actually discrete, and when + -- the number of runs is small, the quantile we need (e.g. 0.99) turns + -- out to be the maximum value of the distribution. We can also hit this + -- maximum possible value with our test run, and this obviously means + -- that we have observed the difference to the best precision possible + -- for the given number of runs. If we use a strict equality here, we + -- will miss such cases. This happened in the wild and lead to some + -- uncaught regressions, because for the default 7 runs we do for PRs, + -- the randomization distribution has only 16 values, so the max quantile + -- is actually 0.9375. + abs(diff) > report_threshold and abs(diff) >= stat_threshold as changed_fail, + abs(diff) > report_threshold - 0.05 and abs(diff) >= stat_threshold as changed_show, not changed_fail and stat_threshold > report_threshold + 0.10 as unstable_fail, not changed_show and stat_threshold > report_threshold - 0.05 as unstable_show, diff --git a/docker/test/performance-comparison/config/config.d/user_files.xml b/docker/test/performance-comparison/config/config.d/user_files.xml new file mode 100644 index 00000000000..9dc8daab66b --- /dev/null +++ b/docker/test/performance-comparison/config/config.d/user_files.xml @@ -0,0 +1,10 @@ + + + /var/lib/clickhouse/user_files/ + + + users.xml + + + access/ + diff --git a/docker/test/performance-comparison/config/users.d/perf-comparison-tweaks-users.xml b/docker/test/performance-comparison/config/users.d/perf-comparison-tweaks-users.xml index f3609bcfcdb..41bc7f777bf 100644 --- a/docker/test/performance-comparison/config/users.d/perf-comparison-tweaks-users.xml +++ b/docker/test/performance-comparison/config/users.d/perf-comparison-tweaks-users.xml @@ -19,4 +19,9 @@ 12 + + + 1 + + diff --git a/docker/test/performance-comparison/eqmed.sql b/docker/test/performance-comparison/eqmed.sql index 139f0758798..d0111550ee6 100644 --- a/docker/test/performance-comparison/eqmed.sql +++ b/docker/test/performance-comparison/eqmed.sql @@ -1,4 +1,6 @@ --- input is table(test text, query text, run UInt32, version int, metrics Array(float)) +-- The input is table(test text, query text, run UInt32, version UInt8, metrics Array(float)). +-- Run like this: +-- clickhouse-local --queries-file eqmed.sql -S 'test text, query text, run UInt32, version UInt8, metrics Array(float)' --file analyze/tmp/modulo_0.tsv select arrayMap(x -> floor(x, 4), original_medians_array.medians_by_version[1] as l) l_rounded, arrayMap(x -> floor(x, 4), original_medians_array.medians_by_version[2] as r) r_rounded, @@ -8,14 +10,19 @@ select from ( -- quantiles of randomization distributions + -- note that for small number of runs, the exact quantile might not make + -- sense, because the last possible value of randomization distribution + -- might take a larger percentage of distirbution (i.e. the distribution + -- actually has discrete values, and the last step can be large). select quantileExactForEach(0.99)( arrayMap(x, y -> abs(x - y), metrics_by_label[1], metrics_by_label[2]) as d ) threshold - ---- uncomment to see what the distribution is really like - --, uniqExact(d.1) u + ---- Uncomment to see what the distribution is really like. This debug + ---- code only works for single (the first) metric. + --, uniqExact(d[1]) u --, arraySort(x->x.1, -- arrayZip( - -- (sumMap([d.1], [1]) as f).1, + -- (sumMap([d[1]], [1]) as f).1, -- f.2)) full_histogram from ( diff --git a/docker/test/split_build_smoke_test/Dockerfile b/docker/test/split_build_smoke_test/Dockerfile index c77db1c6c88..54a9eb17868 100644 --- a/docker/test/split_build_smoke_test/Dockerfile +++ b/docker/test/split_build_smoke_test/Dockerfile @@ -2,5 +2,6 @@ FROM yandex/clickhouse-binary-builder COPY run.sh /run.sh +COPY process_split_build_smoke_test_result.py / CMD /run.sh diff --git a/docker/test/split_build_smoke_test/process_split_build_smoke_test_result.py b/docker/test/split_build_smoke_test/process_split_build_smoke_test_result.py new file mode 100755 index 00000000000..58d6ba8c62a --- /dev/null +++ b/docker/test/split_build_smoke_test/process_split_build_smoke_test_result.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 + +import os +import logging +import argparse +import csv + +RESULT_LOG_NAME = "run.log" + +def process_result(result_folder): + + status = "success" + description = 'Server started and responded' + summary = [("Smoke test", "OK")] + with open(os.path.join(result_folder, RESULT_LOG_NAME), 'r') as run_log: + lines = run_log.read().split('\n') + if not lines or lines[0].strip() != 'OK': + status = "failure" + logging.info("Lines is not ok: %s", str('\n'.join(lines))) + summary = [("Smoke test", "FAIL")] + description = 'Server failed to respond, see result in logs' + + result_logs = [] + server_log_path = os.path.join(result_folder, "clickhouse-server.log") + stderr_log_path = os.path.join(result_folder, "stderr.log") + client_stderr_log_path = os.path.join(result_folder, "clientstderr.log") + + if os.path.exists(server_log_path): + result_logs.append(server_log_path) + + if os.path.exists(stderr_log_path): + result_logs.append(stderr_log_path) + + if os.path.exists(client_stderr_log_path): + result_logs.append(client_stderr_log_path) + + return status, description, summary, result_logs + + +def write_results(results_file, status_file, results, status): + with open(results_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerows(results) + with open(status_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerow(status) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') + parser = argparse.ArgumentParser(description="ClickHouse script for parsing results of split build smoke test") + parser.add_argument("--in-results-dir", default='/test_output/') + parser.add_argument("--out-results-file", default='/test_output/test_results.tsv') + parser.add_argument("--out-status-file", default='/test_output/check_status.tsv') + args = parser.parse_args() + + state, description, test_results, logs = process_result(args.in_results_dir) + logging.info("Result parsed") + status = (state, description) + write_results(args.out_results_file, args.out_status_file, test_results, status) + logging.info("Result written") diff --git a/docker/test/split_build_smoke_test/run.sh b/docker/test/split_build_smoke_test/run.sh index eac9848030e..b565d7a481e 100755 --- a/docker/test/split_build_smoke_test/run.sh +++ b/docker/test/split_build_smoke_test/run.sh @@ -5,16 +5,18 @@ set -x install_and_run_server() { mkdir /unpacked tar -xzf /package_folder/shared_build.tgz -C /unpacked --strip 1 - LD_LIBRARY_PATH=/unpacked /unpacked/clickhouse-server --config /unpacked/config/config.xml >/var/log/clickhouse-server/stderr.log 2>&1 & + LD_LIBRARY_PATH=/unpacked /unpacked/clickhouse-server --config /unpacked/config/config.xml >/test_output/stderr.log 2>&1 & } run_client() { for i in {1..100}; do sleep 1 - LD_LIBRARY_PATH=/unpacked /unpacked/clickhouse-client --query "select 'OK'" 2>/var/log/clickhouse-server/clientstderr.log && break + LD_LIBRARY_PATH=/unpacked /unpacked/clickhouse-client --query "select 'OK'" > /test_output/run.log 2> /test_output/clientstderr.log && break [[ $i == 100 ]] && echo 'FAIL' done } install_and_run_server run_client +mv /var/log/clickhouse-server/clickhouse-server.log /test_output/clickhouse-server.log +/process_split_build_smoke_test_result.py || echo -e "failure\tCannot parse results" > /test_output/check_status.tsv diff --git a/docker/test/sqlancer/Dockerfile b/docker/test/sqlancer/Dockerfile index 38a773e65ad..6bcdc3df5cd 100644 --- a/docker/test/sqlancer/Dockerfile +++ b/docker/test/sqlancer/Dockerfile @@ -1,7 +1,7 @@ # docker build -t yandex/clickhouse-sqlancer-test . FROM ubuntu:20.04 -RUN apt-get update --yes && env DEBIAN_FRONTEND=noninteractive apt-get install wget unzip git openjdk-14-jdk maven --yes --no-install-recommends +RUN apt-get update --yes && env DEBIAN_FRONTEND=noninteractive apt-get install wget unzip git openjdk-14-jdk maven python3 --yes --no-install-recommends RUN wget https://github.com/sqlancer/sqlancer/archive/master.zip -O /sqlancer.zip RUN mkdir /sqlancer && \ @@ -10,4 +10,5 @@ RUN mkdir /sqlancer && \ RUN cd /sqlancer/sqlancer-master && mvn package -DskipTests COPY run.sh / +COPY process_sqlancer_result.py / CMD ["/bin/bash", "/run.sh"] diff --git a/docker/test/sqlancer/process_sqlancer_result.py b/docker/test/sqlancer/process_sqlancer_result.py new file mode 100755 index 00000000000..411c1e18e19 --- /dev/null +++ b/docker/test/sqlancer/process_sqlancer_result.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 + +import os +import logging +import argparse +import csv + + +def process_result(result_folder): + status = "success" + summary = [] + paths = [] + tests = ["TLPWhere", "TLPGroupBy", "TLPHaving", "TLPWhereGroupBy", "TLPDistinct", "TLPAggregate"] + + for test in tests: + err_path = '{}/{}.err'.format(result_folder, test) + out_path = '{}/{}.out'.format(result_folder, test) + if not os.path.exists(err_path): + logging.info("No output err on path %s", err_path) + summary.append((test, "SKIPPED")) + elif not os.path.exists(out_path): + logging.info("No output log on path %s", out_path) + else: + paths.append(err_path) + paths.append(out_path) + with open(err_path, 'r') as f: + if 'AssertionError' in f.read(): + summary.append((test, "FAIL")) + else: + summary.append((test, "OK")) + + logs_path = '{}/logs.tar.gz'.format(result_folder) + if not os.path.exists(logs_path): + logging.info("No logs tar on path %s", logs_path) + else: + paths.append(logs_path) + stdout_path = '{}/stdout.log'.format(result_folder) + if not os.path.exists(stdout_path): + logging.info("No stdout log on path %s", stdout_path) + else: + paths.append(stdout_path) + stderr_path = '{}/stderr.log'.format(result_folder) + if not os.path.exists(stderr_path): + logging.info("No stderr log on path %s", stderr_path) + else: + paths.append(stderr_path) + + description = "SQLancer test run. See report" + + return status, description, summary, paths + + +def write_results(results_file, status_file, results, status): + with open(results_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerows(results) + with open(status_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerow(status) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') + parser = argparse.ArgumentParser(description="ClickHouse script for parsing results of sqlancer test") + parser.add_argument("--in-results-dir", default='/test_output/') + parser.add_argument("--out-results-file", default='/test_output/test_results.tsv') + parser.add_argument("--out-status-file", default='/test_output/check_status.tsv') + args = parser.parse_args() + + state, description, test_results, logs = process_result(args.in_results_dir) + logging.info("Result parsed") + status = (state, description) + write_results(args.out_results_file, args.out_status_file, test_results, status) + logging.info("Result written") diff --git a/docker/test/sqlancer/run.sh b/docker/test/sqlancer/run.sh index ffe0afd98a8..20e82603567 100755 --- a/docker/test/sqlancer/run.sh +++ b/docker/test/sqlancer/run.sh @@ -29,4 +29,5 @@ tail -n 1000 /var/log/clickhouse-server/stderr.log > /test_output/stderr.log tail -n 1000 /var/log/clickhouse-server/stdout.log > /test_output/stdout.log tail -n 1000 /var/log/clickhouse-server/clickhouse-server.log > /test_output/clickhouse-server.log +/process_sqlancer_result.py || echo -e "failure\tCannot parse results" > /test_output/check_status.tsv ls /test_output diff --git a/docker/test/stateful/run.sh b/docker/test/stateful/run.sh index f2fcefd604f..6b90a9e7e37 100755 --- a/docker/test/stateful/run.sh +++ b/docker/test/stateful/run.sh @@ -60,4 +60,16 @@ fi # more idiologically correct. read -ra ADDITIONAL_OPTIONS <<< "${ADDITIONAL_OPTIONS:-}" +if [[ -n "$USE_DATABASE_REPLICATED" ]] && [[ "$USE_DATABASE_REPLICATED" -eq 1 ]]; then + ADDITIONAL_OPTIONS+=('--replicated-database') +fi + clickhouse-test --testname --shard --zookeeper --no-stateless --hung-check --print-time "$SKIP_LIST_OPT" "${ADDITIONAL_OPTIONS[@]}" "$SKIP_TESTS_OPTION" 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee test_output/test_result.txt + +./process_functional_tests_result.py || echo -e "failure\tCannot parse results" > /test_output/check_status.tsv + +pigz < /var/log/clickhouse-server/clickhouse-server.log > /test_output/clickhouse-server.log.gz ||: +mv /var/log/clickhouse-server/stderr.log /test_output/ ||: +if [[ -n "$WITH_COVERAGE" ]] && [[ "$WITH_COVERAGE" -eq 1 ]]; then + tar -chf /test_output/clickhouse_coverage.tar.gz /profraw ||: +fi diff --git a/docker/test/stateless/Dockerfile b/docker/test/stateless/Dockerfile index b063f8d81f6..61d1b2f4849 100644 --- a/docker/test/stateless/Dockerfile +++ b/docker/test/stateless/Dockerfile @@ -3,6 +3,9 @@ FROM yandex/clickhouse-test-base ARG odbc_driver_url="https://github.com/ClickHouse/clickhouse-odbc/releases/download/v1.1.4.20200302/clickhouse-odbc-1.1.4-Linux.tar.gz" +RUN echo "deb [trusted=yes] http://repo.mysql.com/apt/ubuntu/ bionic mysql-5.7" >> /etc/apt/sources.list \ + && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8C718D3B5072E1F5 + RUN apt-get update -y \ && env DEBIAN_FRONTEND=noninteractive \ apt-get install --yes --no-install-recommends \ @@ -13,6 +16,7 @@ RUN apt-get update -y \ ncdu \ netcat-openbsd \ openssl \ + protobuf-compiler \ python3 \ python3-lxml \ python3-requests \ @@ -23,7 +27,8 @@ RUN apt-get update -y \ telnet \ tree \ unixodbc \ - wget + wget \ + mysql-client=5.7* RUN pip3 install numpy scipy pandas @@ -41,4 +46,5 @@ ENV NUM_TRIES=1 ENV MAX_RUN_TIME=0 COPY run.sh / +COPY process_functional_tests_result.py / CMD ["/bin/bash", "/run.sh"] diff --git a/docker/test/stateless/process_functional_tests_result.py b/docker/test/stateless/process_functional_tests_result.py new file mode 100755 index 00000000000..27210ef9b80 --- /dev/null +++ b/docker/test/stateless/process_functional_tests_result.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 + +import os +import logging +import argparse +import csv + +OK_SIGN = "[ OK " +FAIL_SING = "[ FAIL " +TIMEOUT_SING = "[ Timeout! " +UNKNOWN_SIGN = "[ UNKNOWN " +SKIPPED_SIGN = "[ SKIPPED " +HUNG_SIGN = "Found hung queries in processlist" + +def process_test_log(log_path): + total = 0 + skipped = 0 + unknown = 0 + failed = 0 + success = 0 + hung = False + test_results = [] + with open(log_path, 'r') as test_file: + for line in test_file: + line = line.strip() + if HUNG_SIGN in line: + hung = True + if any(sign in line for sign in (OK_SIGN, FAIL_SING, UNKNOWN_SIGN, SKIPPED_SIGN)): + test_name = line.split(' ')[2].split(':')[0] + + test_time = '' + try: + time_token = line.split(']')[1].strip().split()[0] + float(time_token) + test_time = time_token + except: + pass + + total += 1 + if TIMEOUT_SING in line: + failed += 1 + test_results.append((test_name, "Timeout", test_time)) + elif FAIL_SING in line: + failed += 1 + test_results.append((test_name, "FAIL", test_time)) + elif UNKNOWN_SIGN in line: + unknown += 1 + test_results.append((test_name, "FAIL", test_time)) + elif SKIPPED_SIGN in line: + skipped += 1 + test_results.append((test_name, "SKIPPED", test_time)) + else: + success += int(OK_SIGN in line) + test_results.append((test_name, "OK", test_time)) + return total, skipped, unknown, failed, success, hung, test_results + +def process_result(result_path): + test_results = [] + state = "success" + description = "" + files = os.listdir(result_path) + if files: + logging.info("Find files in result folder %s", ','.join(files)) + result_path = os.path.join(result_path, 'test_result.txt') + else: + result_path = None + description = "No output log" + state = "error" + + if result_path and os.path.exists(result_path): + total, skipped, unknown, failed, success, hung, test_results = process_test_log(result_path) + is_flacky_check = 1 < int(os.environ.get('NUM_TRIES', 1)) + # If no tests were run (success == 0) it indicates an error (e.g. server did not start or crashed immediately) + # But it's Ok for "flaky checks" - they can contain just one test for check which is marked as skipped. + if failed != 0 or unknown != 0 or (success == 0 and (not is_flacky_check)): + state = "failure" + + if hung: + description = "Some queries hung, " + state = "failure" + else: + description = "" + + description += "fail: {}, passed: {}".format(failed, success) + if skipped != 0: + description += ", skipped: {}".format(skipped) + if unknown != 0: + description += ", unknown: {}".format(unknown) + else: + state = "failure" + description = "Output log doesn't exist" + test_results = [] + + return state, description, test_results + + +def write_results(results_file, status_file, results, status): + with open(results_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerows(results) + with open(status_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerow(status) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') + parser = argparse.ArgumentParser(description="ClickHouse script for parsing results of functional tests") + parser.add_argument("--in-results-dir", default='/test_output/') + parser.add_argument("--out-results-file", default='/test_output/test_results.tsv') + parser.add_argument("--out-status-file", default='/test_output/check_status.tsv') + args = parser.parse_args() + + state, description, test_results = process_result(args.in_results_dir) + logging.info("Result parsed") + status = (state, description) + write_results(args.out_results_file, args.out_status_file, test_results, status) + logging.info("Result written") diff --git a/docker/test/stateless/run.sh b/docker/test/stateless/run.sh index 575be721a54..3119ae27c59 100755 --- a/docker/test/stateless/run.sh +++ b/docker/test/stateless/run.sh @@ -57,6 +57,10 @@ function run_tests() ADDITIONAL_OPTIONS+=('4') fi + if [[ -n "$USE_DATABASE_REPLICATED" ]] && [[ "$USE_DATABASE_REPLICATED" -eq 1 ]]; then + ADDITIONAL_OPTIONS+=('--replicated-database') + fi + clickhouse-test --testname --shard --zookeeper --hung-check --print-time \ --test-runs "$NUM_TRIES" \ "$SKIP_LIST_OPT" "${ADDITIONAL_OPTIONS[@]}" 2>&1 \ @@ -68,5 +72,12 @@ export -f run_tests timeout "$MAX_RUN_TIME" bash -c run_tests ||: +./process_functional_tests_result.py || echo -e "failure\tCannot parse results" > /test_output/check_status.tsv + +pigz < /var/log/clickhouse-server/clickhouse-server.log > /test_output/clickhouse-server.log.gz ||: +mv /var/log/clickhouse-server/stderr.log /test_output/ ||: +if [[ -n "$WITH_COVERAGE" ]] && [[ "$WITH_COVERAGE" -eq 1 ]]; then + tar -chf /test_output/clickhouse_coverage.tar.gz /profraw ||: +fi tar -chf /test_output/text_log_dump.tar /var/lib/clickhouse/data/system/text_log ||: tar -chf /test_output/query_log_dump.tar /var/lib/clickhouse/data/system/query_log ||: diff --git a/docker/test/stress/run.sh b/docker/test/stress/run.sh index 9da2f3d3ada..9ddf7421934 100755 --- a/docker/test/stress/run.sh +++ b/docker/test/stress/run.sh @@ -8,16 +8,23 @@ dpkg -i package_folder/clickhouse-server_*.deb dpkg -i package_folder/clickhouse-client_*.deb dpkg -i package_folder/clickhouse-test_*.deb +function configure() +{ + # install test configs + /usr/share/clickhouse-test/config/install.sh + + # for clickhouse-server (via service) + echo "ASAN_OPTIONS='malloc_context_size=10 verbosity=1 allocator_release_to_os_interval_ms=10000'" >> /etc/environment + # for clickhouse-client + export ASAN_OPTIONS='malloc_context_size=10 allocator_release_to_os_interval_ms=10000' + + # since we run clickhouse from root + sudo chown root: /var/lib/clickhouse +} + function stop() { - timeout 120 service clickhouse-server stop - - # Wait for process to disappear from processlist and also try to kill zombies. - while kill -9 "$(pidof clickhouse-server)" - do - echo "Killed clickhouse-server" - sleep 0.5 - done + clickhouse stop } function start() @@ -33,19 +40,30 @@ function start() tail -n1000 /var/log/clickhouse-server/clickhouse-server.log break fi - timeout 120 service clickhouse-server start + # use root to match with current uid + clickhouse start --user root >/var/log/clickhouse-server/stdout.log 2>/var/log/clickhouse-server/stderr.log sleep 0.5 counter=$((counter + 1)) done + + echo " +handle all noprint +handle SIGSEGV stop print +handle SIGBUS stop print +handle SIGABRT stop print +continue +thread apply all backtrace +detach +quit +" > script.gdb + + # FIXME Hung check may work incorrectly because of attached gdb + # 1. False positives are possible + # 2. We cannot attach another gdb to get stacktraces if some queries hung + gdb -batch -command script.gdb -p "$(cat /var/run/clickhouse-server/clickhouse-server.pid)" >> /test_output/gdb.log & } -# install test configs -/usr/share/clickhouse-test/config/install.sh - -# for clickhouse-server (via service) -echo "ASAN_OPTIONS='malloc_context_size=10 verbosity=1 allocator_release_to_os_interval_ms=10000'" >> /etc/environment -# for clickhouse-client -export ASAN_OPTIONS='malloc_context_size=10 allocator_release_to_os_interval_ms=10000' +configure start @@ -64,9 +82,55 @@ clickhouse-client --query "RENAME TABLE datasets.hits_v1 TO test.hits" clickhouse-client --query "RENAME TABLE datasets.visits_v1 TO test.visits" clickhouse-client --query "SHOW TABLES FROM test" -./stress --output-folder test_output --skip-func-tests "$SKIP_TESTS_OPTION" +./stress --hung-check --output-folder test_output --skip-func-tests "$SKIP_TESTS_OPTION" \ + && echo -e 'Test script exit code\tOK' >> /test_output/test_results.tsv \ + || echo -e 'Test script failed\tFAIL' >> /test_output/test_results.tsv stop start -clickhouse-client --query "SELECT 'Server successfuly started'" > /test_output/alive_check.txt || echo 'Server failed to start' > /test_output/alive_check.txt +clickhouse-client --query "SELECT 'Server successfully started', 'OK'" >> /test_output/test_results.tsv \ + || echo -e 'Server failed to start\tFAIL' >> /test_output/test_results.tsv + +[ -f /var/log/clickhouse-server/clickhouse-server.log ] || echo -e "Server log does not exist\tFAIL" +[ -f /var/log/clickhouse-server/stderr.log ] || echo -e "Stderr log does not exist\tFAIL" + +# Print Fatal log messages to stdout +zgrep -Fa " " /var/log/clickhouse-server/clickhouse-server.log + +# Grep logs for sanitizer asserts, crashes and other critical errors + +# Sanitizer asserts +zgrep -Fa "==================" /var/log/clickhouse-server/stderr.log >> /test_output/tmp +zgrep -Fa "WARNING" /var/log/clickhouse-server/stderr.log >> /test_output/tmp +zgrep -Fav "ASan doesn't fully support makecontext/swapcontext functions" > /dev/null \ + && echo -e 'Sanitizer assert (in stderr.log)\tFAIL' >> /test_output/test_results.tsv \ + || echo -e 'No sanitizer asserts\tOK' >> /test_output/test_results.tsv +rm -f /test_output/tmp + +# Logical errors +zgrep -Fa "Code: 49, e.displayText() = DB::Exception:" /var/log/clickhouse-server/clickhouse-server.log > /dev/null \ + && echo -e 'Logical error thrown (see clickhouse-server.log)\tFAIL' >> /test_output/test_results.tsv \ + || echo -e 'No logical errors\tOK' >> /test_output/test_results.tsv + +# Crash +zgrep -Fa "########################################" /var/log/clickhouse-server/clickhouse-server.log > /dev/null \ + && echo -e 'Killed by signal (in clickhouse-server.log)\tFAIL' >> /test_output/test_results.tsv \ + || echo -e 'Not crashed\tOK' >> /test_output/test_results.tsv + +# It also checks for OOM or crash without stacktrace (printed by watchdog) +zgrep -Fa " " /var/log/clickhouse-server/clickhouse-server.log > /dev/null \ + && echo -e 'Fatal message in clickhouse-server.log\tFAIL' >> /test_output/test_results.tsv \ + || echo -e 'No fatal messages in clickhouse-server.log\tOK' >> /test_output/test_results.tsv + +zgrep -Fa "########################################" /test_output/* > /dev/null \ + && echo -e 'Killed by signal (output files)\tFAIL' >> /test_output/test_results.tsv + +# Put logs into /test_output/ +pigz < /var/log/clickhouse-server/clickhouse-server.log > /test_output/clickhouse-server.log.gz +tar -chf /test_output/coordination.tar /var/lib/clickhouse/coordination ||: +mv /var/log/clickhouse-server/stderr.log /test_output/ + +# Write check result into check_status.tsv +clickhouse-local --structure "test String, res String" -q "SELECT 'failure', test FROM table WHERE res != 'OK' order by (lower(test) like '%hung%') LIMIT 1" < /test_output/test_results.tsv > /test_output/check_status.tsv +[ -s /test_output/check_status.tsv ] || echo -e "success\tNo errors found" > /test_output/check_status.tsv diff --git a/docker/test/stress/stress b/docker/test/stress/stress index 458f78fcdb4..a6f1ae19303 100755 --- a/docker/test/stress/stress +++ b/docker/test/stress/stress @@ -1,8 +1,9 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- from multiprocessing import cpu_count -from subprocess import Popen, check_call +from subprocess import Popen, call, STDOUT import os +import sys import shutil import argparse import logging @@ -22,12 +23,15 @@ def get_options(i): if 0 < i: options += " --order=random" - if i % 2 == 1: + if i % 3 == 1: options += " --db-engine=Ordinary" + if i % 3 == 2: + options += ''' --db-engine="Replicated('/test/db/test_{}', 's1', 'r1')"'''.format(i) + # If database name is not specified, new database is created for each functional test. # Run some threads with one database for all tests. - if i % 3 == 1: + if i % 2 == 1: options += " --database=test_{}".format(i) if i == 13: @@ -54,6 +58,27 @@ def run_func_test(cmd, output_prefix, num_processes, skip_tests_option, global_t time.sleep(0.5) return pipes +def prepare_for_hung_check(): + # FIXME this function should not exist, but... + + # We attach gdb to clickhouse-server before running tests + # to print stacktraces of all crashes even if clickhouse cannot print it for some reason. + # However, it obstruct checking for hung queries. + logging.info("Will terminate gdb (if any)") + call("kill -TERM $(pidof gdb)", shell=True, stderr=STDOUT) + + # Some tests execute SYSTEM STOP MERGES or similar queries. + # It may cause some ALTERs to hang. + # Possibly we should fix tests and forbid to use such queries without specifying table. + call("clickhouse client -q 'SYSTEM START MERGES'", shell=True, stderr=STDOUT) + call("clickhouse client -q 'SYSTEM START DISTRIBUTED SENDS'", shell=True, stderr=STDOUT) + call("clickhouse client -q 'SYSTEM START TTL MERGES'", shell=True, stderr=STDOUT) + call("clickhouse client -q 'SYSTEM START MOVES'", shell=True, stderr=STDOUT) + call("clickhouse client -q 'SYSTEM START FETCHES'", shell=True, stderr=STDOUT) + call("clickhouse client -q 'SYSTEM START REPLICATED SENDS'", shell=True, stderr=STDOUT) + call("clickhouse client -q 'SYSTEM START REPLICATION QUEUES'", shell=True, stderr=STDOUT) + + time.sleep(30) if __name__ == "__main__": logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') @@ -64,7 +89,8 @@ if __name__ == "__main__": parser.add_argument("--server-log-folder", default='/var/log/clickhouse-server') parser.add_argument("--output-folder") parser.add_argument("--global-time-limit", type=int, default=3600) - parser.add_argument("--num-parallel", default=cpu_count()); + parser.add_argument("--num-parallel", default=cpu_count()) + parser.add_argument('--hung-check', action='store_true', default=False) args = parser.parse_args() func_pipes = [] @@ -81,4 +107,16 @@ if __name__ == "__main__": logging.info("Finished %s from %s processes", len(retcodes), len(func_pipes)) time.sleep(5) + logging.info("All processes finished") + if args.hung_check: + prepare_for_hung_check() + logging.info("Checking if some queries hung") + cmd = "{} {} {}".format(args.test_cmd, "--hung-check", "00001_select_1") + res = call(cmd, shell=True, stderr=STDOUT) + hung_check_status = "No queries hung\tOK\n" + if res != 0: + logging.info("Hung check failed with exit code {}".format(res)) + hung_check_status = "Hung check failed\tFAIL\n" + open(os.path.join(args.output_folder, "test_results.tsv"), 'w+').write(hung_check_status) + logging.info("Stress test finished") diff --git a/docker/test/style/Dockerfile b/docker/test/style/Dockerfile index 74af8eafc17..86595a77a54 100644 --- a/docker/test/style/Dockerfile +++ b/docker/test/style/Dockerfile @@ -1,16 +1,15 @@ # docker build -t yandex/clickhouse-style-test . FROM ubuntu:20.04 -RUN apt-get update && env DEBIAN_FRONTEND=noninteractive apt-get install --yes shellcheck libxml2-utils git python3-pip pylint && pip3 install codespell +RUN apt-get update && env DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + shellcheck \ + libxml2-utils \ + git \ + python3-pip \ + pylint \ + yamllint \ + && pip3 install codespell - -# For |& syntax -SHELL ["bash", "-c"] - -CMD cd /ClickHouse/utils/check-style && \ - ./check-style -n |& tee /test_output/style_output.txt && \ - ./check-typos |& tee /test_output/typos_output.txt && \ - ./check-whitespaces -n |& tee /test_output/whitespaces_output.txt && \ - ./check-duplicate-includes.sh |& tee /test_output/duplicate_output.txt && \ - ./shellcheck-run.sh |& tee /test_output/shellcheck_output.txt && \ - true +COPY run.sh / +COPY process_style_check_result.py / +CMD ["/bin/bash", "/run.sh"] diff --git a/docker/test/style/process_style_check_result.py b/docker/test/style/process_style_check_result.py new file mode 100755 index 00000000000..61b1e0f05c5 --- /dev/null +++ b/docker/test/style/process_style_check_result.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 + +import os +import logging +import argparse +import csv + + +def process_result(result_folder): + status = "success" + description = "" + test_results = [] + + style_log_path = '{}/style_output.txt'.format(result_folder) + if not os.path.exists(style_log_path): + logging.info("No style check log on path %s", style_log_path) + return "exception", "No style check log", [] + elif os.stat(style_log_path).st_size != 0: + description += "Style check failed. " + test_results.append(("Style check", "FAIL")) + status = "failure" # Disabled for now + else: + test_results.append(("Style check", "OK")) + + typos_log_path = '{}/typos_output.txt'.format(result_folder) + if not os.path.exists(style_log_path): + logging.info("No typos check log on path %s", style_log_path) + return "exception", "No typos check log", [] + elif os.stat(typos_log_path).st_size != 0: + description += "Typos check failed. " + test_results.append(("Typos check", "FAIL")) + status = "failure" + else: + test_results.append(("Typos check", "OK")) + + whitespaces_log_path = '{}/whitespaces_output.txt'.format(result_folder) + if not os.path.exists(style_log_path): + logging.info("No whitespaces check log on path %s", style_log_path) + return "exception", "No whitespaces check log", [] + elif os.stat(whitespaces_log_path).st_size != 0: + description += "Whitespaces check failed. " + test_results.append(("Whitespaces check", "FAIL")) + status = "failure" + else: + test_results.append(("Whitespaces check", "OK")) + + duplicate_log_path = '{}/duplicate_output.txt'.format(result_folder) + if not os.path.exists(duplicate_log_path): + logging.info("No header duplicates check log on path %s", duplicate_log_path) + return "exception", "No header duplicates check log", [] + elif os.stat(duplicate_log_path).st_size != 0: + description += " Header duplicates check failed. " + test_results.append(("Header duplicates check", "FAIL")) + status = "failure" + else: + test_results.append(("Header duplicates check", "OK")) + + shellcheck_log_path = '{}/shellcheck_output.txt'.format(result_folder) + if not os.path.exists(shellcheck_log_path): + logging.info("No shellcheck log on path %s", shellcheck_log_path) + return "exception", "No shellcheck log", [] + elif os.stat(shellcheck_log_path).st_size != 0: + description += " Shellcheck check failed. " + test_results.append(("Shellcheck ", "FAIL")) + status = "failure" + else: + test_results.append(("Shellcheck", "OK")) + + if not description: + description += "Style check success" + + return status, description, test_results + + +def write_results(results_file, status_file, results, status): + with open(results_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerows(results) + with open(status_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerow(status) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') + parser = argparse.ArgumentParser(description="ClickHouse script for parsing results of style check") + parser.add_argument("--in-results-dir", default='/test_output/') + parser.add_argument("--out-results-file", default='/test_output/test_results.tsv') + parser.add_argument("--out-status-file", default='/test_output/check_status.tsv') + args = parser.parse_args() + + state, description, test_results = process_result(args.in_results_dir) + logging.info("Result parsed") + status = (state, description) + write_results(args.out_results_file, args.out_status_file, test_results, status) + logging.info("Result written") diff --git a/docker/test/style/run.sh b/docker/test/style/run.sh new file mode 100755 index 00000000000..424bfe71b15 --- /dev/null +++ b/docker/test/style/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +cd /ClickHouse/utils/check-style || echo -e "failure\tRepo not found" > /test_output/check_status.tsv +./check-style -n |& tee /test_output/style_output.txt +./check-typos |& tee /test_output/typos_output.txt +./check-whitespaces -n |& tee /test_output/whitespaces_output.txt +./check-duplicate-includes.sh |& tee /test_output/duplicate_output.txt +./shellcheck-run.sh |& tee /test_output/shellcheck_output.txt +/process_style_check_result.py || echo -e "failure\tCannot parse results" > /test_output/check_status.tsv diff --git a/docker/test/testflows/runner/Dockerfile b/docker/test/testflows/runner/Dockerfile index 4139fb9e044..10014851a82 100644 --- a/docker/test/testflows/runner/Dockerfile +++ b/docker/test/testflows/runner/Dockerfile @@ -61,6 +61,7 @@ RUN set -eux; \ COPY modprobe.sh /usr/local/bin/modprobe COPY dockerd-entrypoint.sh /usr/local/bin/ +COPY process_testflows_result.py /usr/local/bin/ RUN set -x \ && addgroup --system dockremap \ @@ -72,5 +73,5 @@ RUN set -x \ VOLUME /var/lib/docker EXPOSE 2375 ENTRYPOINT ["dockerd-entrypoint.sh"] -CMD ["sh", "-c", "python3 regression.py --no-color -o classic --local --clickhouse-binary-path ${CLICKHOUSE_TESTS_SERVER_BIN_PATH} --log test.log ${TESTFLOWS_OPTS}; cat test.log | tfs report results --format json > results.json"] +CMD ["sh", "-c", "python3 regression.py --no-color -o classic --local --clickhouse-binary-path ${CLICKHOUSE_TESTS_SERVER_BIN_PATH} --log test.log ${TESTFLOWS_OPTS}; cat test.log | tfs report results --format json > results.json; /usr/local/bin/process_testflows_result.py || echo -e 'failure\tCannot parse results' > check_status.tsv"] diff --git a/docker/test/testflows/runner/process_testflows_result.py b/docker/test/testflows/runner/process_testflows_result.py new file mode 100755 index 00000000000..37d0b6a69d1 --- /dev/null +++ b/docker/test/testflows/runner/process_testflows_result.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +import os +import logging +import argparse +import csv +import json + + +def process_result(result_folder): + json_path = os.path.join(result_folder, "results.json") + if not os.path.exists(json_path): + return "success", "No testflows in branch", None, [] + + test_binary_log = os.path.join(result_folder, "test.log") + with open(json_path) as source: + results = json.loads(source.read()) + + total_tests = 0 + total_ok = 0 + total_fail = 0 + total_other = 0 + test_results = [] + for test in results["tests"]: + test_name = test['test']['test_name'] + test_result = test['result']['result_type'].upper() + test_time = str(test['result']['message_rtime']) + total_tests += 1 + if test_result == "OK": + total_ok += 1 + elif test_result == "FAIL" or test_result == "ERROR": + total_fail += 1 + else: + total_other += 1 + + test_results.append((test_name, test_result, test_time)) + if total_fail != 0: + status = "failure" + else: + status = "success" + + description = "failed: {}, passed: {}, other: {}".format(total_fail, total_ok, total_other) + return status, description, test_results, [json_path, test_binary_log] + + +def write_results(results_file, status_file, results, status): + with open(results_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerows(results) + with open(status_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerow(status) + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') + parser = argparse.ArgumentParser(description="ClickHouse script for parsing results of Testflows tests") + parser.add_argument("--in-results-dir", default='./') + parser.add_argument("--out-results-file", default='./test_results.tsv') + parser.add_argument("--out-status-file", default='./check_status.tsv') + args = parser.parse_args() + + state, description, test_results, logs = process_result(args.in_results_dir) + logging.info("Result parsed") + status = (state, description) + write_results(args.out_results_file, args.out_status_file, test_results, status) + logging.info("Result written") + diff --git a/docker/test/unit/Dockerfile b/docker/test/unit/Dockerfile index f01ed613918..e2f4a691939 100644 --- a/docker/test/unit/Dockerfile +++ b/docker/test/unit/Dockerfile @@ -5,6 +5,6 @@ ENV TZ=Europe/Moscow RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN apt-get install gdb -CMD service zookeeper start && sleep 7 && /usr/share/zookeeper/bin/zkCli.sh -server localhost:2181 -create create /clickhouse_test ''; \ - gdb -q -ex 'set print inferior-events off' -ex 'set confirm off' -ex 'set print thread-events off' -ex run -ex bt -ex quit --args ./unit_tests_dbms | tee test_output/test_result.txt - +COPY run.sh / +COPY process_unit_tests_result.py / +CMD ["/bin/bash", "/run.sh"] diff --git a/docker/test/unit/process_unit_tests_result.py b/docker/test/unit/process_unit_tests_result.py new file mode 100755 index 00000000000..7219aa13b82 --- /dev/null +++ b/docker/test/unit/process_unit_tests_result.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 + +import os +import logging +import argparse +import csv + +OK_SIGN = 'OK ]' +FAILED_SIGN = 'FAILED ]' +SEGFAULT = 'Segmentation fault' +SIGNAL = 'received signal SIG' +PASSED = 'PASSED' + +def get_test_name(line): + elements = reversed(line.split(' ')) + for element in elements: + if '(' not in element and ')' not in element: + return element + raise Exception("No test name in line '{}'".format(line)) + +def process_result(result_folder): + summary = [] + total_counter = 0 + failed_counter = 0 + result_log_path = '{}/test_result.txt'.format(result_folder) + if not os.path.exists(result_log_path): + logging.info("No output log on path %s", result_log_path) + return "exception", "No output log", [] + + status = "success" + description = "" + passed = False + with open(result_log_path, 'r') as test_result: + for line in test_result: + if OK_SIGN in line: + logging.info("Found ok line: '%s'", line) + test_name = get_test_name(line.strip()) + logging.info("Test name: '%s'", test_name) + summary.append((test_name, "OK")) + total_counter += 1 + elif FAILED_SIGN in line and 'listed below' not in line and 'ms)' in line: + logging.info("Found fail line: '%s'", line) + test_name = get_test_name(line.strip()) + logging.info("Test name: '%s'", test_name) + summary.append((test_name, "FAIL")) + total_counter += 1 + failed_counter += 1 + elif SEGFAULT in line: + logging.info("Found segfault line: '%s'", line) + status = "failure" + description += "Segmentation fault. " + break + elif SIGNAL in line: + logging.info("Received signal line: '%s'", line) + status = "failure" + description += "Exit on signal. " + break + elif PASSED in line: + logging.info("PASSED record found: '%s'", line) + passed = True + + if not passed: + status = "failure" + description += "PASSED record not found. " + + if failed_counter != 0: + status = "failure" + + if not description: + description += "fail: {}, passed: {}".format(failed_counter, total_counter - failed_counter) + + return status, description, summary + + +def write_results(results_file, status_file, results, status): + with open(results_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerows(results) + with open(status_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerow(status) + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') + parser = argparse.ArgumentParser(description="ClickHouse script for parsing results of unit tests") + parser.add_argument("--in-results-dir", default='/test_output/') + parser.add_argument("--out-results-file", default='/test_output/test_results.tsv') + parser.add_argument("--out-status-file", default='/test_output/check_status.tsv') + args = parser.parse_args() + + state, description, test_results = process_result(args.in_results_dir) + logging.info("Result parsed") + status = (state, description) + write_results(args.out_results_file, args.out_status_file, test_results, status) + logging.info("Result written") + diff --git a/docker/test/unit/run.sh b/docker/test/unit/run.sh new file mode 100644 index 00000000000..abc35fa40d2 --- /dev/null +++ b/docker/test/unit/run.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -x + +service zookeeper start && sleep 7 && /usr/share/zookeeper/bin/zkCli.sh -server localhost:2181 -create create /clickhouse_test ''; +gdb -q -ex 'set print inferior-events off' -ex 'set confirm off' -ex 'set print thread-events off' -ex run -ex bt -ex quit --args ./unit_tests_dbms | tee test_output/test_result.txt +./process_unit_tests_result.py || echo -e "failure\tCannot parse results" > /test_output/check_status.tsv diff --git a/docs/_description_templates/template-data-type.md b/docs/_description_templates/template-data-type.md new file mode 100644 index 00000000000..5e560b9325d --- /dev/null +++ b/docs/_description_templates/template-data-type.md @@ -0,0 +1,29 @@ +--- +toc_priority: +toc_title: +--- + +# data_type_name {#data_type-name} + +Description. + +**Parameters** (Optional) + +- `x` — Description. [Type name](relative/path/to/type/dscr.md#type). +- `y` — Description. [Type name](relative/path/to/type/dscr.md#type). + +**Examples** + +```sql + +``` + +## Additional Info {#additional-info} (Optional) + +The name of an additional section can be any, for example, **Usage**. + +**See Also** (Optional) + +- [link](#) + +[Original article](https://clickhouse.tech/docs/en/data-types//) diff --git a/docs/_description_templates/template-engine.md b/docs/_description_templates/template-engine.md index 35181881134..490f490fc4e 100644 --- a/docs/_description_templates/template-engine.md +++ b/docs/_description_templates/template-engine.md @@ -58,6 +58,6 @@ Result: Follow up with any text to clarify the example. -## See Also {#see-also} +**See Also** - [link](#) diff --git a/docs/_description_templates/template-function.md b/docs/_description_templates/template-function.md index b69d7ed5309..3d4d921898a 100644 --- a/docs/_description_templates/template-function.md +++ b/docs/_description_templates/template-function.md @@ -12,16 +12,20 @@ Alias: ``. (Optional) More text (Optional). -**Parameters** (Optional) +**Arguments** (Optional) -- `x` — Description. [Type name](relative/path/to/type/dscr.md#type). -- `y` — Description. [Type name](relative/path/to/type/dscr.md#type). +- `x` — Description. Optional (only for optional arguments). Possible values: . Default value: . [Type name](relative/path/to/type/dscr.md#type). +- `y` — Description. Optional (only for optional arguments). Possible values: .Default value: . [Type name](relative/path/to/type/dscr.md#type). + +**Parameters** (Optional, only for parametric aggregate functions) + +- `z` — Description. Optional (only for optional parameters). Possible values: . Default value: . [Type name](relative/path/to/type/dscr.md#type). **Returned value(s)** -- Returned values list. +- Returned values list. -Type: [Type](relative/path/to/type/dscr.md#type). +Type: [Type name](relative/path/to/type/dscr.md#type). **Example** diff --git a/docs/_description_templates/template-server-setting.md b/docs/_description_templates/template-server-setting.md index 36a2bcacfba..0b37d46cf41 100644 --- a/docs/_description_templates/template-server-setting.md +++ b/docs/_description_templates/template-server-setting.md @@ -8,14 +8,14 @@ Possible value: ... Default value: ... -Settings: (Optional) +**Settings** (Optional) If the section contains several settings, list them here. Specify possible values and default values: - setting_1 — Description. - setting_2 — Description. -**Example:** +**Example** ```xml diff --git a/docs/_description_templates/template-statement.md b/docs/_description_templates/template-statement.md index 62ea51edf83..bca015a2ac6 100644 --- a/docs/_description_templates/template-statement.md +++ b/docs/_description_templates/template-statement.md @@ -1,14 +1,14 @@ -# Statement name (for example, SHOW USER) +# Statement name (for example, SHOW USER) {#statement-name-in-lower-case} Brief description of what the statement does. -Syntax: +**Syntax** ```sql Syntax of the statement. ``` -## Other necessary sections of the description (Optional) +## Other necessary sections of the description (Optional) {#anchor} Examples of descriptions with a complicated structure: @@ -17,7 +17,7 @@ Examples of descriptions with a complicated structure: - https://clickhouse.tech/docs/en/sql-reference/statements/select/join/ -## See Also (Optional) +**See Also** (Optional) Links to related topics as a list. diff --git a/docs/_description_templates/template-system-table.md b/docs/_description_templates/template-system-table.md index 3fdf9788d79..f2decc4bb6d 100644 --- a/docs/_description_templates/template-system-table.md +++ b/docs/_description_templates/template-system-table.md @@ -8,10 +8,14 @@ Columns: **Example** +Query: + ``` sql SELECT * FROM system.table_name ``` +Result: + ``` text Some output. It shouldn't be too long. ``` diff --git a/docs/en/commercial/cloud.md b/docs/en/commercial/cloud.md index 0490881c622..91d2061c0af 100644 --- a/docs/en/commercial/cloud.md +++ b/docs/en/commercial/cloud.md @@ -29,6 +29,17 @@ toc_title: Cloud - Cross-AZ scaling for performance and high availability - Built-in monitoring and SQL query editor +## Alibaba Cloud {#alibaba-cloud} + +Alibaba Cloud Managed Service for ClickHouse [China Site](https://www.aliyun.com/product/clickhouse) (Will be available at international site at May, 2021) provides the following key features: +- Highly reliable cloud disk storage engine based on Alibaba Cloud Apsara distributed system +- Expand capacity on demand without manual data migration +- Support single-node, single-replica, multi-node, and multi-replica architectures, and support hot and cold data tiering +- Support access allow-list, one-key recovery, multi-layer network security protection, cloud disk encryption +- Seamless integration with cloud log systems, databases, and data application tools +- Built-in monitoring and database management platform +- Professional database expert technical support and service + ## Tencent Cloud {#tencent-cloud} [Tencent Managed Service for ClickHouse](https://cloud.tencent.com/product/cdwch) provides the following key features: diff --git a/docs/en/development/build.md b/docs/en/development/build.md index f98329e748f..3181f26800d 100644 --- a/docs/en/development/build.md +++ b/docs/en/development/build.md @@ -170,7 +170,7 @@ $ ./release Normally all tools of the ClickHouse bundle, such as `clickhouse-server`, `clickhouse-client` etc., are linked into a single static executable, `clickhouse`. This executable must be re-linked on every change, which might be slow. Two common ways to improve linking time are to use `lld` linker, and use the 'split' build configuration, which builds a separate binary for every tool, and further splits the code into serveral shared libraries. To enable these tweaks, pass the following flags to `cmake`: ``` --DCMAKE_C_FLAGS="-fuse-ld=lld" -DCMAKE_CXX_FLAGS="-fuse-ld=lld" -DUSE_STATIC_LIBRARIES=0 -DSPLIT_SHARED_LIBRARIES=1 -DCLICKHOUSE_SPLIT_BINARY=1 +-DCMAKE_C_FLAGS="--ld-path=lld" -DCMAKE_CXX_FLAGS="--ld-path=lld" -DUSE_STATIC_LIBRARIES=0 -DSPLIT_SHARED_LIBRARIES=1 -DCLICKHOUSE_SPLIT_BINARY=1 ``` ## You Don’t Have to Build ClickHouse {#you-dont-have-to-build-clickhouse} diff --git a/docs/en/engines/table-engines/integrations/kafka.md b/docs/en/engines/table-engines/integrations/kafka.md index c519d6bb136..fb1df62bb15 100644 --- a/docs/en/engines/table-engines/integrations/kafka.md +++ b/docs/en/engines/table-engines/integrations/kafka.md @@ -38,20 +38,20 @@ SETTINGS Required parameters: -- `kafka_broker_list` – A comma-separated list of brokers (for example, `localhost:9092`). -- `kafka_topic_list` – A list of Kafka topics. -- `kafka_group_name` – A group of Kafka consumers. Reading margins are tracked for each group separately. If you don’t want messages to be duplicated in the cluster, use the same group name everywhere. -- `kafka_format` – Message format. Uses the same notation as the SQL `FORMAT` function, such as `JSONEachRow`. For more information, see the [Formats](../../../interfaces/formats.md) section. +- `kafka_broker_list` — A comma-separated list of brokers (for example, `localhost:9092`). +- `kafka_topic_list` — A list of Kafka topics. +- `kafka_group_name` — A group of Kafka consumers. Reading margins are tracked for each group separately. If you don’t want messages to be duplicated in the cluster, use the same group name everywhere. +- `kafka_format` — Message format. Uses the same notation as the SQL `FORMAT` function, such as `JSONEachRow`. For more information, see the [Formats](../../../interfaces/formats.md) section. Optional parameters: -- `kafka_row_delimiter` – Delimiter character, which ends the message. -- `kafka_schema` – Parameter that must be used if the format requires a schema definition. For example, [Cap’n Proto](https://capnproto.org/) requires the path to the schema file and the name of the root `schema.capnp:Message` object. -- `kafka_num_consumers` – The number of consumers per table. Default: `1`. Specify more consumers if the throughput of one consumer is insufficient. The total number of consumers should not exceed the number of partitions in the topic, since only one consumer can be assigned per partition. -- `kafka_max_block_size` - The maximum batch size (in messages) for poll (default: `max_block_size`). -- `kafka_skip_broken_messages` – Kafka message parser tolerance to schema-incompatible messages per block. Default: `0`. If `kafka_skip_broken_messages = N` then the engine skips *N* Kafka messages that cannot be parsed (a message equals a row of data). -- `kafka_commit_every_batch` - Commit every consumed and handled batch instead of a single commit after writing a whole block (default: `0`). -- `kafka_thread_per_consumer` - Provide independent thread for each consumer (default: `0`). When enabled, every consumer flush the data independently, in parallel (otherwise - rows from several consumers squashed to form one block). +- `kafka_row_delimiter` — Delimiter character, which ends the message. +- `kafka_schema` — Parameter that must be used if the format requires a schema definition. For example, [Cap’n Proto](https://capnproto.org/) requires the path to the schema file and the name of the root `schema.capnp:Message` object. +- `kafka_num_consumers` — The number of consumers per table. Default: `1`. Specify more consumers if the throughput of one consumer is insufficient. The total number of consumers should not exceed the number of partitions in the topic, since only one consumer can be assigned per partition. +- `kafka_max_block_size` — The maximum batch size (in messages) for poll (default: `max_block_size`). +- `kafka_skip_broken_messages` — Kafka message parser tolerance to schema-incompatible messages per block. Default: `0`. If `kafka_skip_broken_messages = N` then the engine skips *N* Kafka messages that cannot be parsed (a message equals a row of data). +- `kafka_commit_every_batch` — Commit every consumed and handled batch instead of a single commit after writing a whole block (default: `0`). +- `kafka_thread_per_consumer` — Provide independent thread for each consumer (default: `0`). When enabled, every consumer flush the data independently, in parallel (otherwise — rows from several consumers squashed to form one block). Examples: diff --git a/docs/en/engines/table-engines/integrations/rabbitmq.md b/docs/en/engines/table-engines/integrations/rabbitmq.md index b0901ee6f6e..4a0550275ca 100644 --- a/docs/en/engines/table-engines/integrations/rabbitmq.md +++ b/docs/en/engines/table-engines/integrations/rabbitmq.md @@ -59,10 +59,26 @@ Optional parameters: - `rabbitmq_max_block_size` - `rabbitmq_flush_interval_ms` -Required configuration: +Also format settings can be added along with rabbitmq-related settings. + +Example: + +``` sql + CREATE TABLE queue ( + key UInt64, + value UInt64, + date DateTime + ) ENGINE = RabbitMQ SETTINGS rabbitmq_host_port = 'localhost:5672', + rabbitmq_exchange_name = 'exchange1', + rabbitmq_format = 'JSONEachRow', + rabbitmq_num_consumers = 5, + date_time_input_format = 'best_effort'; +``` The RabbitMQ server configuration should be added using the ClickHouse config file. +Required configuration: + ``` xml root @@ -70,16 +86,12 @@ The RabbitMQ server configuration should be added using the ClickHouse config fi ``` -Example: +Additional configuration: -``` sql - CREATE TABLE queue ( - key UInt64, - value UInt64 - ) ENGINE = RabbitMQ SETTINGS rabbitmq_host_port = 'localhost:5672', - rabbitmq_exchange_name = 'exchange1', - rabbitmq_format = 'JSONEachRow', - rabbitmq_num_consumers = 5; +``` xml + + clickhouse + ``` ## Description {#description} @@ -105,6 +117,7 @@ Exchange type options: - `consistent_hash` - Data is evenly distributed between all bound tables (where the exchange name is the same). Note that this exchange type must be enabled with RabbitMQ plugin: `rabbitmq-plugins enable rabbitmq_consistent_hash_exchange`. Setting `rabbitmq_queue_base` may be used for the following cases: + - to let different tables share queues, so that multiple consumers could be registered for the same queues, which makes a better performance. If using `rabbitmq_num_consumers` and/or `rabbitmq_num_queues` settings, the exact match of queues is achieved in case these parameters are the same. - to be able to restore reading from certain durable queues when not all messages were successfully consumed. To resume consumption from one specific queue - set its name in `rabbitmq_queue_base` setting and do not specify `rabbitmq_num_consumers` and `rabbitmq_num_queues` (defaults to 1). To resume consumption from all queues, which were declared for a specific table - just specify the same settings: `rabbitmq_queue_base`, `rabbitmq_num_consumers`, `rabbitmq_num_queues`. By default, queue names will be unique to tables. - to reuse queues as they are declared durable and not auto-deleted. (Can be deleted via any of RabbitMQ CLI tools.) diff --git a/docs/en/engines/table-engines/integrations/s3.md b/docs/en/engines/table-engines/integrations/s3.md index d8cceb4d511..5858a0803e6 100644 --- a/docs/en/engines/table-engines/integrations/s3.md +++ b/docs/en/engines/table-engines/integrations/s3.md @@ -136,8 +136,7 @@ The following settings can be specified in configuration file for given endpoint - `access_key_id` and `secret_access_key` — Optional. Specifies credentials to use with given endpoint. - `use_environment_credentials` — Optional, default value is `false`. If set to `true`, S3 client will try to obtain credentials from environment variables and Amazon EC2 metadata for given endpoint. - `header` — Optional, can be speficied multiple times. Adds specified HTTP header to a request to given endpoint. - -This configuration also applies to S3 disks in `MergeTree` table engine family. +- `server_side_encryption_customer_key_base64` — Optional. If specified, required headers for accessing S3 objects with SSE-C encryption will be set. Example: @@ -149,6 +148,7 @@ Example: + ``` diff --git a/docs/en/engines/table-engines/mergetree-family/mergetree.md b/docs/en/engines/table-engines/mergetree-family/mergetree.md index c69da4197b8..52d9111dc90 100644 --- a/docs/en/engines/table-engines/mergetree-family/mergetree.md +++ b/docs/en/engines/table-engines/mergetree-family/mergetree.md @@ -701,6 +701,32 @@ The `default` storage policy implies using only one volume, which consists of on The number of threads performing background moves of data parts can be changed by [background_move_pool_size](../../../operations/settings/settings.md#background_move_pool_size) setting. +### Details {#details} + +In the case of `MergeTree` tables, data is getting to disk in different ways: + +- As a result of an insert (`INSERT` query). +- During background merges and [mutations](../../../sql-reference/statements/alter/index.md#alter-mutations). +- When downloading from another replica. +- As a result of partition freezing [ALTER TABLE … FREEZE PARTITION](../../../sql-reference/statements/alter/partition.md#alter_freeze-partition). + +In all these cases except for mutations and partition freezing, a part is stored on a volume and a disk according to the given storage policy: + +1. The first volume (in the order of definition) that has enough disk space for storing a part (`unreserved_space > current_part_size`) and allows for storing parts of a given size (`max_data_part_size_bytes > current_part_size`) is chosen. +2. Within this volume, that disk is chosen that follows the one, which was used for storing the previous chunk of data, and that has free space more than the part size (`unreserved_space - keep_free_space_bytes > current_part_size`). + +Under the hood, mutations and partition freezing make use of [hard links](https://en.wikipedia.org/wiki/Hard_link). Hard links between different disks are not supported, therefore in such cases the resulting parts are stored on the same disks as the initial ones. + +In the background, parts are moved between volumes on the basis of the amount of free space (`move_factor` parameter) according to the order the volumes are declared in the configuration file. +Data is never transferred from the last one and into the first one. One may use system tables [system.part_log](../../../operations/system-tables/part_log.md#system_tables-part-log) (field `type = MOVE_PART`) and [system.parts](../../../operations/system-tables/parts.md#system_tables-parts) (fields `path` and `disk`) to monitor background moves. Also, the detailed information can be found in server logs. + +User can force moving a part or a partition from one volume to another using the query [ALTER TABLE … MOVE PART\|PARTITION … TO VOLUME\|DISK …](../../../sql-reference/statements/alter/partition.md#alter_move-partition), all the restrictions for background operations are taken into account. The query initiates a move on its own and does not wait for background operations to be completed. User will get an error message if not enough free space is available or if any of the required conditions are not met. + +Moving data does not interfere with data replication. Therefore, different storage policies can be specified for the same table on different replicas. + +After the completion of background merges and mutations, old parts are removed only after a certain amount of time (`old_parts_lifetime`). +During this time, they are not moved to other volumes or disks. Therefore, until the parts are finally removed, they are still taken into account for evaluation of the occupied disk space. + ## Using S3 for Data Storage {#table_engine-mergetree-s3} `MergeTree` family table engines is able to store data to [S3](https://aws.amazon.com/s3/) using a disk with type `s3`. @@ -715,6 +741,7 @@ Configuration markup: https://storage.yandexcloud.net/my-bucket/root-path/ your_access_key_id your_secret_access_key + your_base64_encoded_customer_key http://proxy1 http://proxy2 @@ -750,7 +777,8 @@ Optional parameters: - `metadata_path` — Path on local FS to store metadata files for S3. Default value is `/var/lib/clickhouse/disks//`. - `cache_enabled` — Allows to cache mark and index files on local FS. Default value is `true`. - `cache_path` — Path on local FS where to store cached mark and index files. Default value is `/var/lib/clickhouse/disks//cache/`. -- `skip_access_check` — If true disk access checks will not be performed on disk start-up. Default value is `false`. +- `skip_access_check` — If true, disk access checks will not be performed on disk start-up. Default value is `false`. +- `server_side_encryption_customer_key_base64` — If specified, required headers for accessing S3 objects with SSE-C encryption will be set. S3 disk can be configured as `main` or `cold` storage: @@ -791,30 +819,4 @@ S3 disk can be configured as `main` or `cold` storage: In case of `cold` option a data can be moved to S3 if local disk free size will be smaller than `move_factor * disk_size` or by TTL move rule. -### Details {#details} - -In the case of `MergeTree` tables, data is getting to disk in different ways: - -- As a result of an insert (`INSERT` query). -- During background merges and [mutations](../../../sql-reference/statements/alter/index.md#alter-mutations). -- When downloading from another replica. -- As a result of partition freezing [ALTER TABLE … FREEZE PARTITION](../../../sql-reference/statements/alter/partition.md#alter_freeze-partition). - -In all these cases except for mutations and partition freezing, a part is stored on a volume and a disk according to the given storage policy: - -1. The first volume (in the order of definition) that has enough disk space for storing a part (`unreserved_space > current_part_size`) and allows for storing parts of a given size (`max_data_part_size_bytes > current_part_size`) is chosen. -2. Within this volume, that disk is chosen that follows the one, which was used for storing the previous chunk of data, and that has free space more than the part size (`unreserved_space - keep_free_space_bytes > current_part_size`). - -Under the hood, mutations and partition freezing make use of [hard links](https://en.wikipedia.org/wiki/Hard_link). Hard links between different disks are not supported, therefore in such cases the resulting parts are stored on the same disks as the initial ones. - -In the background, parts are moved between volumes on the basis of the amount of free space (`move_factor` parameter) according to the order the volumes are declared in the configuration file. -Data is never transferred from the last one and into the first one. One may use system tables [system.part_log](../../../operations/system-tables/part_log.md#system_tables-part-log) (field `type = MOVE_PART`) and [system.parts](../../../operations/system-tables/parts.md#system_tables-parts) (fields `path` and `disk`) to monitor background moves. Also, the detailed information can be found in server logs. - -User can force moving a part or a partition from one volume to another using the query [ALTER TABLE … MOVE PART\|PARTITION … TO VOLUME\|DISK …](../../../sql-reference/statements/alter/partition.md#alter_move-partition), all the restrictions for background operations are taken into account. The query initiates a move on its own and does not wait for background operations to be completed. User will get an error message if not enough free space is available or if any of the required conditions are not met. - -Moving data does not interfere with data replication. Therefore, different storage policies can be specified for the same table on different replicas. - -After the completion of background merges and mutations, old parts are removed only after a certain amount of time (`old_parts_lifetime`). -During this time, they are not moved to other volumes or disks. Therefore, until the parts are finally removed, they are still taken into account for evaluation of the occupied disk space. - [Original article](https://clickhouse.tech/docs/ru/operations/table_engines/mergetree/) diff --git a/docs/en/engines/table-engines/special/distributed.md b/docs/en/engines/table-engines/special/distributed.md index 7fffa962480..c47e0c27cd2 100644 --- a/docs/en/engines/table-engines/special/distributed.md +++ b/docs/en/engines/table-engines/special/distributed.md @@ -31,6 +31,12 @@ Also it accept the following settings: - `fsync_directories` - do the `fsync` for directories. Guarantees that the OS refreshed directory metadata after operations related to asynchronous inserts on Distributed table (after insert, after sending the data to shard, etc). +- `bytes_to_throw_insert` - if more than this number of compressed bytes will be pending for async INSERT, an exception will be thrown. 0 - do not throw. Default 0. + +- `bytes_to_delay_insert` - if more than this number of compressed bytes will be pending for async INSERT, the query will be delayed. 0 - do not delay. Default 0. + +- `max_delay_to_insert` - max delay of inserting data into Distributed table in seconds, if there are a lot of pending bytes for async send. Default 60. + !!! note "Note" **Durability settings** (`fsync_...`): @@ -39,6 +45,12 @@ Also it accept the following settings: - May significantly decrease the inserts' performance - Affect writing the data stored inside Distributed table folder into the **node which accepted your insert**. If you need to have guarantees of writing data to underlying MergeTree tables - see durability settings (`...fsync...`) in `system.merge_tree_settings` + For **Insert limit settings** (`..._insert`) see also: + + - [insert_distributed_sync](../../../operations/settings/settings.md#insert_distributed_sync) setting + - [prefer_localhost_replica](../../../operations/settings/settings.md#settings-prefer-localhost-replica) setting + - `bytes_to_throw_insert` handled before `bytes_to_delay_insert`, so you should not set it to the value less then `bytes_to_delay_insert` + Example: ``` sql @@ -61,19 +73,18 @@ Clusters are set like this: ``` xml + + - - - 1 diff --git a/docs/en/engines/table-engines/special/file.md b/docs/en/engines/table-engines/special/file.md index cda16c2a226..2acec40ef02 100644 --- a/docs/en/engines/table-engines/special/file.md +++ b/docs/en/engines/table-engines/special/file.md @@ -66,7 +66,8 @@ SELECT * FROM file_engine_table ## Usage in ClickHouse-local {#usage-in-clickhouse-local} -In [clickhouse-local](../../../operations/utilities/clickhouse-local.md) File engine accepts file path in addition to `Format`. Default input/output streams can be specified using numeric or human-readable names like `0` or `stdin`, `1` or `stdout`. +In [clickhouse-local](../../../operations/utilities/clickhouse-local.md) File engine accepts file path in addition to `Format`. Default input/output streams can be specified using numeric or human-readable names like `0` or `stdin`, `1` or `stdout`. It is possible to read and write compressed files based on an additional engine parameter or file extension (`gz`, `br` or `xz`). + **Example:** ``` bash diff --git a/docs/en/faq/operations/delete-old-data.md b/docs/en/faq/operations/delete-old-data.md index 5addc455602..fdf1f1f290e 100644 --- a/docs/en/faq/operations/delete-old-data.md +++ b/docs/en/faq/operations/delete-old-data.md @@ -39,4 +39,4 @@ More details on [manipulating partitions](../../sql-reference/statements/alter/p It’s rather radical to drop all data from a table, but in some cases it might be exactly what you need. -More details on [table truncation](../../sql-reference/statements/alter/partition.md#alter_drop-partition). +More details on [table truncation](../../sql-reference/statements/truncate.md). diff --git a/docs/en/getting-started/example-datasets/brown-benchmark.md b/docs/en/getting-started/example-datasets/brown-benchmark.md index b5ca23eddb9..c9b74a84a54 100644 --- a/docs/en/getting-started/example-datasets/brown-benchmark.md +++ b/docs/en/getting-started/example-datasets/brown-benchmark.md @@ -5,7 +5,7 @@ toc_title: Brown University Benchmark # Brown University Benchmark -MgBench - A new analytical benchmark for machine-generated log data, [Andrew Crotty](http://cs.brown.edu/people/acrotty/). +`MgBench` is a new analytical benchmark for machine-generated log data, [Andrew Crotty](http://cs.brown.edu/people/acrotty/). Download the data: ``` @@ -153,7 +153,7 @@ ORDER BY dt, hr; --- Q1.4: Over a 1-month period, how often was each server blocked on disk I/O? +-- Q1.4: Over 1 month, how often was each server blocked on disk I/O? SELECT machine_name, COUNT(*) AS spikes @@ -301,7 +301,7 @@ WHERE event_type = 'temperature' AND log_time >= '2019-11-29 17:00:00.000'; --- Q3.4: Over the past 6 months, how frequently was each door opened? +-- Q3.4: Over the past 6 months, how frequently were each door opened? SELECT device_name, device_floor, @@ -412,3 +412,5 @@ ORDER BY yr, ``` The data is also available for interactive queries in the [Playground](https://gh-api.clickhouse.tech/play?user=play), [example](https://gh-api.clickhouse.tech/play?user=play#U0VMRUNUIG1hY2hpbmVfbmFtZSwKICAgICAgIE1JTihjcHUpIEFTIGNwdV9taW4sCiAgICAgICBNQVgoY3B1KSBBUyBjcHVfbWF4LAogICAgICAgQVZHKGNwdSkgQVMgY3B1X2F2ZywKICAgICAgIE1JTihuZXRfaW4pIEFTIG5ldF9pbl9taW4sCiAgICAgICBNQVgobmV0X2luKSBBUyBuZXRfaW5fbWF4LAogICAgICAgQVZHKG5ldF9pbikgQVMgbmV0X2luX2F2ZywKICAgICAgIE1JTihuZXRfb3V0KSBBUyBuZXRfb3V0X21pbiwKICAgICAgIE1BWChuZXRfb3V0KSBBUyBuZXRfb3V0X21heCwKICAgICAgIEFWRyhuZXRfb3V0KSBBUyBuZXRfb3V0X2F2ZwpGUk9NICgKICBTRUxFQ1QgbWFjaGluZV9uYW1lLAogICAgICAgICBDT0FMRVNDRShjcHVfdXNlciwgMC4wKSBBUyBjcHUsCiAgICAgICAgIENPQUxFU0NFKGJ5dGVzX2luLCAwLjApIEFTIG5ldF9pbiwKICAgICAgICAgQ09BTEVTQ0UoYnl0ZXNfb3V0LCAwLjApIEFTIG5ldF9vdXQKICBGUk9NIG1nYmVuY2gubG9nczEKICBXSEVSRSBtYWNoaW5lX25hbWUgSU4gKCdhbmFuc2knLCdhcmFnb2cnLCd1cmQnKQogICAgQU5EIGxvZ190aW1lID49IFRJTUVTVEFNUCAnMjAxNy0wMS0xMSAwMDowMDowMCcKKSBBUyByCkdST1VQIEJZIG1hY2hpbmVfbmFtZQ==). + +[Original article](https://clickhouse.tech/docs/en/getting_started/example_datasets/brown-benchmark/) diff --git a/docs/en/getting-started/example-datasets/cell-towers.md b/docs/en/getting-started/example-datasets/cell-towers.md new file mode 100644 index 00000000000..76effdd4c62 --- /dev/null +++ b/docs/en/getting-started/example-datasets/cell-towers.md @@ -0,0 +1,133 @@ +--- +toc_priority: 21 +toc_title: Cell Towers +--- + +# Cell Towers + +This dataset is from [OpenCellid](https://www.opencellid.org/) - The world's largest Open Database of Cell Towers. + +As of 2021 it contains more than 40 million records about cell towers (GSM, LTE, UMTS, etc.) around the world with their geographical coordinates and metadata (country code, network, etc). + +OpenCelliD Project is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License, and we redistribute a snapshot of this dataset under the terms of the same license. The up to date version of the dataset is available to download after sign in. + + +## Get the Dataset + +Download the snapshot of the dataset from Feb 2021: [https://datasets.clickhouse.tech/cell_towers.csv.xz] (729 MB). + +Optionally validate the integrity: +``` +md5sum cell_towers.csv.xz +8cf986f4a0d9f12c6f384a0e9192c908 cell_towers.csv.xz +``` + +Decompress it with the following command: +``` +xz -d cell_towers.csv.xz +``` + +Create a table: + +``` +CREATE TABLE cell_towers +( + radio Enum8('' = 0, 'CDMA' = 1, 'GSM' = 2, 'LTE' = 3, 'NR' = 4, 'UMTS' = 5), + mcc UInt16, + net UInt16, + area UInt16, + cell UInt64, + unit Int16, + lon Float64, + lat Float64, + range UInt32, + samples UInt32, + changeable UInt8, + created DateTime, + updated DateTime, + averageSignal UInt8 +) +ENGINE = MergeTree ORDER BY (radio, mcc, net, created); +``` + +Insert the dataset: +``` +clickhouse-client --query "INSERT INTO cell_towers FORMAT CSVWithNames" < cell_towers.csv +``` + + +## Run some queries + +Number of cell towers by type: +``` +SELECT radio, count() AS c FROM cell_towers GROUP BY radio ORDER BY c DESC + +┌─radio─┬────────c─┐ +│ UMTS │ 20686487 │ +│ LTE │ 12101148 │ +│ GSM │ 9931312 │ +│ CDMA │ 556344 │ +│ NR │ 867 │ +└───────┴──────────┘ + +5 rows in set. Elapsed: 0.011 sec. Processed 43.28 million rows, 43.28 MB (3.83 billion rows/s., 3.83 GB/s.) +``` + +Cell towers by mobile country code (MCC): +``` +SELECT mcc, count() FROM cell_towers GROUP BY mcc ORDER BY count() DESC LIMIT 10 + +┌─mcc─┬─count()─┐ +│ 310 │ 5024650 │ +│ 262 │ 2622423 │ +│ 250 │ 1953176 │ +│ 208 │ 1891187 │ +│ 724 │ 1836150 │ +│ 404 │ 1729151 │ +│ 234 │ 1618924 │ +│ 510 │ 1353998 │ +│ 440 │ 1343355 │ +│ 311 │ 1332798 │ +└─────┴─────────┘ + +10 rows in set. Elapsed: 0.019 sec. Processed 43.28 million rows, 86.55 MB (2.33 billion rows/s., 4.65 GB/s.) +``` + +See the dictionary here: [https://en.wikipedia.org/wiki/Mobile_country_code](https://en.wikipedia.org/wiki/Mobile_country_code). + +So, the top countries are USA, Germany and Russia. + +You may want to create an [External Dictionary](../../sql-reference/dictionaries/external-dictionaries/external-dicts/) in ClickHouse to decode these values. + + +### Example of using `pointInPolygon` function + +Create a table where we will store polygons: + +``` +CREATE TEMPORARY TABLE moscow (polygon Array(Tuple(Float64, Float64))); +``` + +This is a rough shape of Moscow (without "new Moscow"): + +``` +INSERT INTO moscow VALUES ([(37.84172564285271, 55.78000432402266), (37.8381207618713, 55.775874525970494), (37.83979446823122, 55.775626746008065), (37.84243326983639, 55.77446586811748), (37.84262672750849, 55.771974101091104), (37.84153238623039, 55.77114545193181), (37.841124690460184, 55.76722010265554), (37.84239076983644, 55.76654891107098), (37.842283558197025, 55.76258709833121), (37.8421759312134, 55.758073999993734), (37.84198330422974, 55.75381499999371), (37.8416827275085, 55.749277102484484), (37.84157576190186, 55.74794544108413), (37.83897929098507, 55.74525257875241), (37.83739676451868, 55.74404373042019), (37.838732481460525, 55.74298009816793), (37.841183997352545, 55.743060321833575), (37.84097476190185, 55.73938799999373), (37.84048155819702, 55.73570799999372), (37.840095812164286, 55.73228210777237), (37.83983814285274, 55.73080491981639), (37.83846476321406, 55.729799917464675), (37.83835745269769, 55.72919751082619), (37.838636380279524, 55.72859509486539), (37.8395161005249, 55.727705075632784), (37.83897964285276, 55.722727886185154), (37.83862557539366, 55.72034817326636), (37.83559735744853, 55.71944437307499), (37.835370708803126, 55.71831419154461), (37.83738169402022, 55.71765218986692), (37.83823396494291, 55.71691750159089), (37.838056931213345, 55.71547311301385), (37.836812846557606, 55.71221445615604), (37.83522525396725, 55.709331054395555), (37.83269301586908, 55.70953687463627), (37.829667367706236, 55.70903403789297), (37.83311126588435, 55.70552351822608), (37.83058993121339, 55.70041317726053), (37.82983872750851, 55.69883771404813), (37.82934501586913, 55.69718947487017), (37.828926414016685, 55.69504441658371), (37.82876530422971, 55.69287499999378), (37.82894754100031, 55.690759754047335), (37.827697554878185, 55.68951421135665), (37.82447346292115, 55.68965045405069), (37.83136543914793, 55.68322046195302), (37.833554015869154, 55.67814012759211), (37.83544184655761, 55.67295011628339), (37.837480388885474, 55.6672498719639), (37.838960677246064, 55.66316274139358), (37.83926093121332, 55.66046999999383), (37.839025050262435, 55.65869897264431), (37.83670784390257, 55.65794084879904), (37.835656529083245, 55.65694309303843), (37.83704060449217, 55.65689306460552), (37.83696819873806, 55.65550363526252), (37.83760389616388, 55.65487847246661), (37.83687972750851, 55.65356745541324), (37.83515216004943, 55.65155951234079), (37.83312418518067, 55.64979413590619), (37.82801726983639, 55.64640836412121), (37.820614174591, 55.64164525405531), (37.818908190475426, 55.6421883258084), (37.81717543386075, 55.64112490388471), (37.81690987037274, 55.63916106913107), (37.815099354492155, 55.637925371757085), (37.808769150787356, 55.633798276884455), (37.80100123544311, 55.62873670012244), (37.79598013491824, 55.62554336109055), (37.78634567724606, 55.62033499605651), (37.78334147619623, 55.618768681480326), (37.77746201055901, 55.619855533402706), (37.77527329626457, 55.61909966711279), (37.77801986242668, 55.618770300976294), (37.778212973541216, 55.617257701952106), (37.77784818518065, 55.61574504433011), (37.77016867724609, 55.61148576294007), (37.760191219573976, 55.60599579539028), (37.75338926983641, 55.60227892751446), (37.746329965606634, 55.59920577639331), (37.73939925396728, 55.59631430313617), (37.73273665739439, 55.5935318803559), (37.7299954450912, 55.59350760316188), (37.7268679946899, 55.59469840523759), (37.72626726983634, 55.59229549697373), (37.7262673598022, 55.59081598950582), (37.71897193121335, 55.5877595845419), (37.70871550793456, 55.58393177431724), (37.700497489410374, 55.580917323756644), (37.69204305026244, 55.57778089778455), (37.68544477378839, 55.57815154690915), (37.68391050793454, 55.57472945079756), (37.678803592590306, 55.57328235936491), (37.6743402539673, 55.57255251445782), (37.66813862698363, 55.57216388774464), (37.617927457672096, 55.57505691895805), (37.60443099999999, 55.5757737568051), (37.599683515869145, 55.57749105910326), (37.59754177842709, 55.57796291823627), (37.59625834786988, 55.57906686095235), (37.59501783265684, 55.57746616444403), (37.593090671936025, 55.57671634534502), (37.587018007904, 55.577944600233785), (37.578692203704804, 55.57982895000019), (37.57327546607398, 55.58116294118248), (37.57385012109279, 55.581550362779), (37.57399562266922, 55.5820107079112), (37.5735356072979, 55.58226289171689), (37.57290393054962, 55.582393529795155), (37.57037722355653, 55.581919415056234), (37.5592298306885, 55.584471614867844), (37.54189249206543, 55.58867650795186), (37.5297256269836, 55.59158133551745), (37.517837865081766, 55.59443656218868), (37.51200186508174, 55.59635625174229), (37.506808949737554, 55.59907823904434), (37.49820432275389, 55.6062944994944), (37.494406071441674, 55.60967103463367), (37.494760001358024, 55.61066689753365), (37.49397137107085, 55.61220931698269), (37.49016528606031, 55.613417718449064), (37.48773249206542, 55.61530616333343), (37.47921386508177, 55.622640129112334), (37.470652153442394, 55.62993723476164), (37.46273446298218, 55.6368075123157), (37.46350692265317, 55.64068225239439), (37.46050283203121, 55.640794546982576), (37.457627470916734, 55.64118904154646), (37.450718034393326, 55.64690488145138), (37.44239252645875, 55.65397824729769), (37.434587576721185, 55.66053543155961), (37.43582144975277, 55.661693766520735), (37.43576786245721, 55.662755031737014), (37.430982915344174, 55.664610641628116), (37.428547447097685, 55.66778515273695), (37.42945134592044, 55.668633314343566), (37.42859571562949, 55.66948145750025), (37.4262836402282, 55.670813882451405), (37.418709037048295, 55.6811141674414), (37.41922139651101, 55.68235377885389), (37.419218771842885, 55.68359335082235), (37.417196501327446, 55.684375235224735), (37.41607020370478, 55.68540557585352), (37.415640857147146, 55.68686637150793), (37.414632153442334, 55.68903015131686), (37.413344899475064, 55.690896881757396), (37.41171432275391, 55.69264232162232), (37.40948282275393, 55.69455101638112), (37.40703674603271, 55.69638690385348), (37.39607169577025, 55.70451821283731), (37.38952706878662, 55.70942491932811), (37.387778313491815, 55.71149057784176), (37.39049275399779, 55.71419814298992), (37.385557272491454, 55.7155489617061), (37.38388335714726, 55.71849856042102), (37.378368238098155, 55.7292763261685), (37.37763597123337, 55.730845879211614), (37.37890062088197, 55.73167906388319), (37.37750451918789, 55.734703664681774), (37.375610832015965, 55.734851959522246), (37.3723813571472, 55.74105626086403), (37.37014935714723, 55.746115620904355), (37.36944173016362, 55.750883999993725), (37.36975304365541, 55.76335905525834), (37.37244070571134, 55.76432079697595), (37.3724259757175, 55.76636979670426), (37.369922155757884, 55.76735417953104), (37.369892695770275, 55.76823419316575), (37.370214730163575, 55.782312184391266), (37.370493611114505, 55.78436801120489), (37.37120164550783, 55.78596427165359), (37.37284851456452, 55.7874378183096), (37.37608325135799, 55.7886695054807), (37.3764587460632, 55.78947647305964), (37.37530000265506, 55.79146512926804), (37.38235915344241, 55.79899647809345), (37.384344043655396, 55.80113596939471), (37.38594269577028, 55.80322699999366), (37.38711208598329, 55.804919036911976), (37.3880239841309, 55.806610999993666), (37.38928977249147, 55.81001864976979), (37.39038389947512, 55.81348641242801), (37.39235781481933, 55.81983538336746), (37.393709457672124, 55.82417822811877), (37.394685720901464, 55.82792275755836), (37.39557615344238, 55.830447148154136), (37.39844478226658, 55.83167107969975), (37.40019761214057, 55.83151823557964), (37.400398790382326, 55.83264967594742), (37.39659544313046, 55.83322180909622), (37.39667059524539, 55.83402792148566), (37.39682089947515, 55.83638877400216), (37.39643489154053, 55.83861656112751), (37.3955338994751, 55.84072348043264), (37.392680272491454, 55.84502158126453), (37.39241188227847, 55.84659117913199), (37.392529730163616, 55.84816071336481), (37.39486835714723, 55.85288092980303), (37.39873052645878, 55.859893456073635), (37.40272161111449, 55.86441833633205), (37.40697072750854, 55.867579567544375), (37.410007082016016, 55.868369880337), (37.4120992989502, 55.86920843741314), (37.412668021163924, 55.87055369615854), (37.41482461111453, 55.87170587948249), (37.41862266137694, 55.873183961039565), (37.42413732540892, 55.874879126654704), (37.4312182698669, 55.875614937236705), (37.43111093783558, 55.8762723478417), (37.43332105622856, 55.87706546369396), (37.43385747619623, 55.87790681284802), (37.441303050262405, 55.88027084462084), (37.44747234260555, 55.87942070143253), (37.44716141796871, 55.88072960917233), (37.44769797085568, 55.88121221323979), (37.45204320500181, 55.882080694420715), (37.45673176190186, 55.882346110794586), (37.463383999999984, 55.88252729504517), (37.46682797486874, 55.88294937719063), (37.470014457672086, 55.88361266759345), (37.47751410450743, 55.88546991372396), (37.47860317658232, 55.88534929207307), (37.48165826025772, 55.882563306475106), (37.48316434442331, 55.8815803226785), (37.483831555817645, 55.882427612793315), (37.483182967125686, 55.88372791409729), (37.483092277908824, 55.88495581062434), (37.4855716508179, 55.8875561994203), (37.486440636245746, 55.887827444039566), (37.49014203439328, 55.88897899871799), (37.493210285705544, 55.890208937135604), (37.497512451065035, 55.891342397444696), (37.49780744510645, 55.89174030252967), (37.49940333499519, 55.89239745507079), (37.50018383334346, 55.89339220941865), (37.52421672750851, 55.903869074155224), (37.52977457672118, 55.90564076517974), (37.53503220370484, 55.90661661218259), (37.54042858064267, 55.90714113744566), (37.54320461007303, 55.905645048442985), (37.545686966066306, 55.906608607018505), (37.54743976120755, 55.90788552162358), (37.55796999999999, 55.90901557907218), (37.572711542327866, 55.91059395704873), (37.57942799999998, 55.91073854155573), (37.58502865872187, 55.91009969268444), (37.58739968913264, 55.90794809960554), (37.59131567193598, 55.908713267595054), (37.612687423278814, 55.902866854295375), (37.62348079629517, 55.90041967242986), (37.635797880950896, 55.898141151686396), (37.649487626983664, 55.89639275532968), (37.65619302513125, 55.89572360207488), (37.66294133862307, 55.895295577183965), (37.66874564418033, 55.89505457604897), (37.67375601586915, 55.89254677027454), (37.67744661901856, 55.8947775867987), (37.688347, 55.89450045676125), (37.69480554232789, 55.89422926332761), (37.70107096560668, 55.89322256101114), (37.705962965606716, 55.891763491662616), (37.711885134918205, 55.889110234998974), (37.71682005026245, 55.886577568759876), (37.7199315476074, 55.88458159806678), (37.72234560316464, 55.882281005794134), (37.72364385977171, 55.8809452036196), (37.725371142837474, 55.8809722706006), (37.727870902099546, 55.88037213862385), (37.73394330422971, 55.877941504088696), (37.745339592590376, 55.87208120378722), (37.75525267724611, 55.86703807949492), (37.76919976190188, 55.859821640197474), (37.827835219574, 55.82962968399116), (37.83341438888553, 55.82575289922351), (37.83652584655761, 55.82188784027888), (37.83809213491821, 55.81612575504693), (37.83605359521481, 55.81460347077685), (37.83632178569025, 55.81276696067908), (37.838623105812026, 55.811486181656385), (37.83912198147584, 55.807329380532785), (37.839079078033414, 55.80510270463816), (37.83965844708251, 55.79940712529036), (37.840581150787344, 55.79131399999368), (37.84172564285271, 55.78000432402266)]); +``` + +Check how many cell towers are in Moscow: + +``` +SELECT count() FROM cell_towers WHERE pointInPolygon((lon, lat), (SELECT * FROM moscow)) + +┌─count()─┐ +│ 310463 │ +└─────────┘ + +1 rows in set. Elapsed: 0.067 sec. Processed 43.28 million rows, 692.42 MB (645.83 million rows/s., 10.33 GB/s.) +``` + +The data is also available for interactive queries in the [Playground](https://gh-api.clickhouse.tech/play?user=play), [example](https://gh-api.clickhouse.tech/play?user=play#U0VMRUNUIG1jYywgY291bnQoKSBGUk9NIGNlbGxfdG93ZXJzIEdST1VQIEJZIG1jYyBPUkRFUiBCWSBjb3VudCgpIERFU0M=). + +Although you cannot create temporary tables there. + +[Original article](https://clickhouse.tech/docs/en/getting_started/example_datasets/cell-towers/) diff --git a/docs/en/getting-started/example-datasets/index.md b/docs/en/getting-started/example-datasets/index.md index 72f44d8caf1..53007c33306 100644 --- a/docs/en/getting-started/example-datasets/index.md +++ b/docs/en/getting-started/example-datasets/index.md @@ -20,5 +20,6 @@ The list of documented datasets: - [Terabyte of Click Logs from Criteo](../../getting-started/example-datasets/criteo.md) - [AMPLab Big Data Benchmark](../../getting-started/example-datasets/amplab-benchmark.md) - [Brown University Benchmark](../../getting-started/example-datasets/brown-benchmark.md) +- [Cell Towers](../../getting-started/example-datasets/cell-towers.md) [Original article](https://clickhouse.tech/docs/en/getting_started/example_datasets) diff --git a/docs/en/getting-started/example-datasets/ontime.md b/docs/en/getting-started/example-datasets/ontime.md index 6e46cddba52..83673cdceb6 100644 --- a/docs/en/getting-started/example-datasets/ontime.md +++ b/docs/en/getting-started/example-datasets/ontime.md @@ -15,17 +15,9 @@ This dataset can be obtained in two ways: Downloading data: ``` bash -for s in `seq 1987 2018` -do -for m in `seq 1 12` -do -wget https://transtats.bts.gov/PREZIP/On_Time_Reporting_Carrier_On_Time_Performance_1987_present_${s}_${m}.zip -done -done +echo https://transtats.bts.gov/PREZIP/On_Time_Reporting_Carrier_On_Time_Performance_1987_present_{1987..2021}_{1..12}.zip | xargs -P10 wget --no-check-certificate --continue ``` -(from https://github.com/Percona-Lab/ontime-airline-performance/blob/master/download.sh ) - Creating a table: ``` sql @@ -145,12 +137,14 @@ ORDER BY (Carrier, FlightDate) SETTINGS index_granularity = 8192; ``` -Loading data: +Loading data with multiple threads: ``` bash -$ for i in *.zip; do echo $i; unzip -cq $i '*.csv' | sed 's/\.00//g' | clickhouse-client --input_format_with_names_use_header=0 --host=example-perftest01j --query="INSERT INTO ontime FORMAT CSVWithNames"; done +ls -1 *.zip | xargs -I{} -P $(nproc) bash -c "echo {}; unzip -cq {} '*.csv' | sed 's/\.00//g' | clickhouse-client --input_format_with_names_use_header=0 --query='INSERT INTO ontime FORMAT CSVWithNames'" ``` +(if you will have memory shortage or other issues on your server, remove the `-P $(nproc)` part) + ## Download of Prepared Partitions {#download-of-prepared-partitions} ``` bash diff --git a/docs/en/getting-started/tutorial.md b/docs/en/getting-started/tutorial.md index 64363c963c5..fe697972dff 100644 --- a/docs/en/getting-started/tutorial.md +++ b/docs/en/getting-started/tutorial.md @@ -644,7 +644,7 @@ If there are no replicas at the moment on replicated table creation, a new first ``` sql CREATE TABLE tutorial.hits_replica (...) -ENGINE = ReplcatedMergeTree( +ENGINE = ReplicatedMergeTree( '/clickhouse_perftest/tables/{shard}/hits', '{replica}' ) diff --git a/docs/en/interfaces/formats.md b/docs/en/interfaces/formats.md index 11291d61300..33bf90a8b52 100644 --- a/docs/en/interfaces/formats.md +++ b/docs/en/interfaces/formats.md @@ -31,8 +31,8 @@ The supported formats are: | [JSONCompactString](#jsoncompactstring) | ✗ | ✔ | | [JSONEachRow](#jsoneachrow) | ✔ | ✔ | | [JSONEachRowWithProgress](#jsoneachrowwithprogress) | ✗ | ✔ | -| [JSONStringEachRow](#jsonstringeachrow) | ✔ | ✔ | -| [JSONStringEachRowWithProgress](#jsonstringeachrowwithprogress) | ✗ | ✔ | +| [JSONStringsEachRow](#jsonstringseachrow) | ✔ | ✔ | +| [JSONStringsEachRowWithProgress](#jsonstringseachrowwithprogress) | ✗ | ✔ | | [JSONCompactEachRow](#jsoncompacteachrow) | ✔ | ✔ | | [JSONCompactEachRowWithNamesAndTypes](#jsoncompacteachrowwithnamesandtypes) | ✔ | ✔ | | [JSONCompactStringEachRow](#jsoncompactstringeachrow) | ✔ | ✔ | @@ -612,7 +612,7 @@ Example: ``` ## JSONEachRow {#jsoneachrow} -## JSONStringEachRow {#jsonstringeachrow} +## JSONStringsEachRow {#jsonstringseachrow} ## JSONCompactEachRow {#jsoncompacteachrow} ## JSONCompactStringEachRow {#jsoncompactstringeachrow} @@ -627,9 +627,9 @@ When using these formats, ClickHouse outputs rows as separated, newline-delimite When inserting the data, you should provide a separate JSON value for each row. ## JSONEachRowWithProgress {#jsoneachrowwithprogress} -## JSONStringEachRowWithProgress {#jsonstringeachrowwithprogress} +## JSONStringsEachRowWithProgress {#jsonstringseachrowwithprogress} -Differs from `JSONEachRow`/`JSONStringEachRow` in that ClickHouse will also yield progress information as JSON values. +Differs from `JSONEachRow`/`JSONStringsEachRow` in that ClickHouse will also yield progress information as JSON values. ```json {"row":{"'hello'":"hello","multiply(42, number)":"0","range(5)":[0,1,2,3,4]}} diff --git a/docs/en/interfaces/http.md b/docs/en/interfaces/http.md index 310286e3d44..18533cfc6c2 100644 --- a/docs/en/interfaces/http.md +++ b/docs/en/interfaces/http.md @@ -148,28 +148,48 @@ $ echo 'DROP TABLE t' | curl 'http://localhost:8123/' --data-binary @- For successful requests that don’t return a data table, an empty response body is returned. -You can use the internal ClickHouse compression format when transmitting data. The compressed data has a non-standard format, and you will need to use the special `clickhouse-compressor` program to work with it (it is installed with the `clickhouse-client` package). To increase the efficiency of data insertion, you can disable server-side checksum verification by using the [http_native_compression_disable_checksumming_on_decompress](../operations/settings/settings.md#settings-http_native_compression_disable_checksumming_on_decompress) setting. -If you specified `compress=1` in the URL, the server compresses the data it sends you. -If you specified `decompress=1` in the URL, the server decompresses the same data that you pass in the `POST` method. +## Compression {#compression} -You can also choose to use [HTTP compression](https://en.wikipedia.org/wiki/HTTP_compression). To send a compressed `POST` request, append the request header `Content-Encoding: compression_method`. In order for ClickHouse to compress the response, you must append `Accept-Encoding: compression_method`. ClickHouse supports `gzip`, `br`, and `deflate` [compression methods](https://en.wikipedia.org/wiki/HTTP_compression#Content-Encoding_tokens). To enable HTTP compression, you must use the ClickHouse [enable_http_compression](../operations/settings/settings.md#settings-enable_http_compression) setting. You can configure the data compression level in the [http_zlib_compression_level](#settings-http_zlib_compression_level) setting for all the compression methods. +You can use compression to reduce network traffic when transmitting a large amount of data or for creating dumps that are immediately compressed. -You can use this to reduce network traffic when transmitting a large amount of data, or for creating dumps that are immediately compressed. +You can use the internal ClickHouse compression format when transmitting data. The compressed data has a non-standard format, and you need `clickhouse-compressor` program to work with it. It is installed with the `clickhouse-client` package. To increase the efficiency of data insertion, you can disable server-side checksum verification by using the [http_native_compression_disable_checksumming_on_decompress](../operations/settings/settings.md#settings-http_native_compression_disable_checksumming_on_decompress) setting. -Examples of sending data with compression: +If you specify `compress=1` in the URL, the server will compress the data it sends to you. If you specify `decompress=1` in the URL, the server will decompress the data which you pass in the `POST` method. -``` bash -#Sending data to the server: -$ curl -vsS "http://localhost:8123/?enable_http_compression=1" -d 'SELECT number FROM system.numbers LIMIT 10' -H 'Accept-Encoding: gzip' +You can also choose to use [HTTP compression](https://en.wikipedia.org/wiki/HTTP_compression). ClickHouse supports the following [compression methods](https://en.wikipedia.org/wiki/HTTP_compression#Content-Encoding_tokens): -#Sending data to the client: -$ echo "SELECT 1" | gzip -c | curl -sS --data-binary @- -H 'Content-Encoding: gzip' 'http://localhost:8123/' -``` +- `gzip` +- `br` +- `deflate` +- `xz` + +To send a compressed `POST` request, append the request header `Content-Encoding: compression_method`. +In order for ClickHouse to compress the response, enable compression with [enable_http_compression](../operations/settings/settings.md#settings-enable_http_compression) setting and append `Accept-Encoding: compression_method` header to the request. You can configure the data compression level in the [http_zlib_compression_level](../operations/settings/settings.md#settings-http_zlib_compression_level) setting for all compression methods. !!! note "Note" Some HTTP clients might decompress data from the server by default (with `gzip` and `deflate`) and you might get decompressed data even if you use the compression settings correctly. +**Examples** + +``` bash +# Sending compressed data to the server +$ echo "SELECT 1" | gzip -c | \ + curl -sS --data-binary @- -H 'Content-Encoding: gzip' 'http://localhost:8123/' +``` + +``` bash +# Receiving compressed data from the server +$ curl -vsS "http://localhost:8123/?enable_http_compression=1" \ + -H 'Accept-Encoding: gzip' --output result.gz -d 'SELECT number FROM system.numbers LIMIT 3' +$ zcat result.gz +0 +1 +2 +``` + +## Default Database {#default-database} + You can use the ‘database’ URL parameter or the ‘X-ClickHouse-Database’ header to specify the default database. ``` bash diff --git a/docs/en/introduction/distinctive-features.md b/docs/en/introduction/distinctive-features.md index 4a8f31b8d56..be7c2d2e7c1 100644 --- a/docs/en/introduction/distinctive-features.md +++ b/docs/en/introduction/distinctive-features.md @@ -7,9 +7,9 @@ toc_title: Distinctive Features ## True Column-Oriented Database Management System {#true-column-oriented-dbms} -In a true column-oriented DBMS, no extra data is stored with the values. Among other things, this means that constant-length values must be supported, to avoid storing their length “number” next to the values. As an example, a billion UInt8-type values should consume around 1 GB uncompressed, or this strongly affects the CPU use. It is essential to store data compactly (without any “garbage”) even when uncompressed, since the speed of decompression (CPU usage) depends mainly on the volume of uncompressed data. +In a real column-oriented DBMS, no extra data is stored with the values. Among other things, this means that constant-length values must be supported, to avoid storing their length “number” next to the values. For example, a billion UInt8-type values should consume around 1 GB uncompressed, or this strongly affects the CPU use. It is essential to store data compactly (without any “garbage”) even when uncompressed since the speed of decompression (CPU usage) depends mainly on the volume of uncompressed data. -It is worth noting because there are systems that can store values of different columns separately, but that can’t effectively process analytical queries due to their optimization for other scenarios. Examples are HBase, BigTable, Cassandra, and HyperTable. In these systems, you would get throughput around a hundred thousand rows per second, but not hundreds of millions of rows per second. +It is worth noting because there are systems that can store values of different columns separately, but that can’t effectively process analytical queries due to their optimization for other scenarios. Examples are HBase, BigTable, Cassandra, and HyperTable. You would get throughput around a hundred thousand rows per second in these systems, but not hundreds of millions of rows per second. It’s also worth noting that ClickHouse is a database management system, not a single database. ClickHouse allows creating tables and databases in runtime, loading data, and running queries without reconfiguring and restarting the server. diff --git a/docs/en/operations/caches.md b/docs/en/operations/caches.md index 7b096b76f75..ec7e4239a9d 100644 --- a/docs/en/operations/caches.md +++ b/docs/en/operations/caches.md @@ -8,18 +8,21 @@ toc_title: Caches When performing queries, ClichHouse uses different caches. Main cache types: + - `mark_cache` — Cache of marks used by table engines of the [MergeTree](../engines/table-engines/mergetree-family/mergetree.md) family. - `uncompressed_cache` — Cache of uncompressed data used by table engines of the [MergeTree](../engines/table-engines/mergetree-family/mergetree.md) family. Additional cache types: -- DNS cache -- [regexp](../interfaces/formats.md#data-format-regexp) cache -- compiled expressions cache -- [Avro format](../interfaces/formats.md#data-format-avro) schemas cache -- [dictionaries data cache](../sql-reference/dictionaries/index.md) + +- DNS cache. +- [Regexp](../interfaces/formats.md#data-format-regexp) cache. +- Compiled expressions cache. +- [Avro format](../interfaces/formats.md#data-format-avro) schemas cache. +- [Dictionaries](../sql-reference/dictionaries/index.md) data cache. Indirectly used: -- OS page cache + +- OS page cache. To drop cache, use [SYSTEM DROP ... CACHE](../sql-reference/statements/system.md) statements. diff --git a/docs/en/operations/external-authenticators/index.md b/docs/en/operations/external-authenticators/index.md new file mode 100644 index 00000000000..95f80f192f5 --- /dev/null +++ b/docs/en/operations/external-authenticators/index.md @@ -0,0 +1,13 @@ +--- +toc_folder_title: External User Authenticators and Directories +toc_priority: 48 +toc_title: Introduction +--- + +# External User Authenticators and Directories {#external-authenticators} + +ClickHouse supports authenticating and managing users using external services. + +The following external authenticators and directories are supported: + +- [LDAP](./ldap.md#external-authenticators-ldap) [Authenticator](./ldap.md#ldap-external-authenticator) and [Directory](./ldap.md#ldap-external-user-directory) diff --git a/docs/en/operations/external-authenticators/ldap.md b/docs/en/operations/external-authenticators/ldap.md new file mode 100644 index 00000000000..5c06ad7daed --- /dev/null +++ b/docs/en/operations/external-authenticators/ldap.md @@ -0,0 +1,154 @@ +# LDAP {#external-authenticators-ldap} + +LDAP server can be used to authenticate ClickHouse users. There are two different approaches for doing this: + +- use LDAP as an external authenticator for existing users, which are defined in `users.xml` or in local access control paths +- use LDAP as an external user directory and allow locally undefined users to be authenticated if they exist on the LDAP server + +For both of these approaches, an internally named LDAP server must be defined in the ClickHouse config so that other parts of config are able to refer to it. + +## LDAP Server Definition {#ldap-server-definition} + +To define LDAP server you must add `ldap_servers` section to the `config.xml`. For example, + +```xml + + + + + localhost + 636 + uid={user_name},ou=users,dc=example,dc=com + 300 + yes + tls1.2 + demand + /path/to/tls_cert_file + /path/to/tls_key_file + /path/to/tls_ca_cert_file + /path/to/tls_ca_cert_dir + ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:AES256-GCM-SHA384 + + + +``` + +Note, that you can define multiple LDAP servers inside the `ldap_servers` section using distinct names. + +Parameters: + +- `host` - LDAP server hostname or IP, this parameter is mandatory and cannot be empty. +- `port` - LDAP server port, default is `636` if `enable_tls` is set to `true`, `389` otherwise. +- `bind_dn` - template used to construct the DN to bind to. + - The resulting DN will be constructed by replacing all `{user_name}` substrings of the + template with the actual user name during each authentication attempt. +- `verification_cooldown` - a period of time, in seconds, after a successful bind attempt, + during which the user will be assumed to be successfully authenticated for all consecutive + requests without contacting the LDAP server. + - Specify `0` (the default) to disable caching and force contacting the LDAP server for each authentication request. +- `enable_tls` - flag to trigger use of secure connection to the LDAP server. + - Specify `no` for plain text `ldap://` protocol (not recommended). + - Specify `yes` for LDAP over SSL/TLS `ldaps://` protocol (recommended, the default). + - Specify `starttls` for legacy StartTLS protocol (plain text `ldap://` protocol, upgraded to TLS). +- `tls_minimum_protocol_version` - the minimum protocol version of SSL/TLS. + - Accepted values are: `ssl2`, `ssl3`, `tls1.0`, `tls1.1`, `tls1.2` (the default). +- `tls_require_cert` - SSL/TLS peer certificate verification behavior. + - Accepted values are: `never`, `allow`, `try`, `demand` (the default). +- `tls_cert_file` - path to certificate file. +- `tls_key_file` - path to certificate key file. +- `tls_ca_cert_file` - path to CA certificate file. +- `tls_ca_cert_dir` - path to the directory containing CA certificates. +- `tls_cipher_suite` - allowed cipher suite (in OpenSSL notation). + +## LDAP External Authenticator {#ldap-external-authenticator} + +A remote LDAP server can be used as a method for verifying passwords for locally defined users (users defined in `users.xml` or in local access control paths). In order to achieve this, specify previously defined LDAP server name instead of `password` or similar sections in the user definition. + +At each login attempt, ClickHouse will try to "bind" to the specified DN defined by the `bind_dn` parameter in the [LDAP server definition](#ldap-server-definition) using the provided credentials, and if successful, the user will be considered authenticated. This is often called a "simple bind" method. + +For example, + +```xml + + + + + + + + my_ldap_server + + + + +``` + +Note, that user `my_user` refers to `my_ldap_server`. This LDAP server must be configured in the main `config.xml` file as described previously. + +When SQL-driven [Access Control and Account Management](../access-rights.md#access-control) is enabled in ClickHouse, users that are authenticated by LDAP servers can also be created using the [CRATE USER](../../sql-reference/statements/create/user.md#create-user-statement) statement. + +```sql +CREATE USER my_user IDENTIFIED WITH ldap SERVER 'my_ldap_server' +``` + +## LDAP Exernal User Directory {#ldap-external-user-directory} + +In addition to the locally defined users, a remote LDAP server can be used as a source of user definitions. In order to achieve this, specify previously defined LDAP server name (see [LDAP Server Definition](#ldap-server-definition)) in an `ldap` section inside the `users_directories` section of the `config.xml` file. + +At each login attempt, ClickHouse will try to find the user definition locally and authenticate it as usual, but if the user is not defined, ClickHouse will assume it exists in the external LDAP directory, and will try to "bind" to the specified DN at the LDAP server using the provided credentials. If successful, the user will be considered existing and authenticated. The user will be assigned roles from the list specified in the `roles` section. Additionally, LDAP "search" can be performed and results can be transformed and treated as role names and then be assigned to the user if the `role_mapping` section is also configured. All this implies that the SQL-driven [Access Control and Account Management](../access-rights.md#access-control) is enabled and roles are created using the [CREATE ROLE](../../sql-reference/statements/create/role.md#create-role-statement) statement. + +Example (goes into `config.xml`): + +```xml + + + + + + my_ldap_server + + + + + + ou=groups,dc=example,dc=com + subtree + (&(objectClass=groupOfNames)(member={bind_dn})) + cn + clickhouse_ + + + + +``` + +Note that `my_ldap_server` referred in the `ldap` section inside the `user_directories` section must be a previously +defined LDAP server that is configured in the `config.xml` (see [LDAP Server Definition](#ldap-server-definition)). + +Parameters: + +- `server` - one of LDAP server names defined in the `ldap_servers` config section above. + This parameter is mandatory and cannot be empty. +- `roles` - section with a list of locally defined roles that will be assigned to each user retrieved from the LDAP server. + - If no roles are specified here or assigned during role mapping (below), user will not be able + to perform any actions after authentication. +- `role_mapping` - section with LDAP search parameters and mapping rules. + - When a user authenticates, while still bound to LDAP, an LDAP search is performed using `search_filter` + and the name of the logged in user. For each entry found during that search, the value of the specified + attribute is extracted. For each attribute value that has the specified prefix, the prefix is removed, + and the rest of the value becomes the name of a local role defined in ClickHouse, + which is expected to be created beforehand by the [CREATE ROLE](../../sql-reference/statements/create/role.md#create-role-statement) statement. + - There can be multiple `role_mapping` sections defined inside the same `ldap` section. All of them will be applied. + - `base_dn` - template used to construct the base DN for the LDAP search. + - The resulting DN will be constructed by replacing all `{user_name}` and `{bind_dn}` + substrings of the template with the actual user name and bind DN during each LDAP search. + - `scope` - scope of the LDAP search. + - Accepted values are: `base`, `one_level`, `children`, `subtree` (the default). + - `search_filter` - template used to construct the search filter for the LDAP search. + - The resulting filter will be constructed by replacing all `{user_name}`, `{bind_dn}`, and `{base_dn}` + substrings of the template with the actual user name, bind DN, and base DN during each LDAP search. + - Note, that the special characters must be escaped properly in XML. + - `attribute` - attribute name whose values will be returned by the LDAP search. + - `prefix` - prefix, that will be expected to be in front of each string in the original + list of strings returned by the LDAP search. Prefix will be removed from the original + strings and resulting strings will be treated as local role names. Empty, by default. diff --git a/docs/en/operations/opentelemetry.md b/docs/en/operations/opentelemetry.md index 2afeabc7956..74c9c6dd18f 100644 --- a/docs/en/operations/opentelemetry.md +++ b/docs/en/operations/opentelemetry.md @@ -5,74 +5,40 @@ toc_title: OpenTelemetry Support # [experimental] OpenTelemetry Support -[OpenTelemetry](https://opentelemetry.io/) is an open standard for collecting -traces and metrics from distributed application. ClickHouse has some support -for OpenTelemetry. +[OpenTelemetry](https://opentelemetry.io/) is an open standard for collecting traces and metrics from the distributed application. ClickHouse has some support for OpenTelemetry. !!! warning "Warning" -This is an experimental feature that will change in backwards-incompatible ways in the future releases. - + This is an experimental feature that will change in backwards-incompatible ways in future releases. ## Supplying Trace Context to ClickHouse -ClickHouse accepts trace context HTTP headers, as described by -the [W3C recommendation](https://www.w3.org/TR/trace-context/). -It also accepts trace context over native protocol that is used for -communication between ClickHouse servers or between the client and server. -For manual testing, trace context headers conforming to the Trace Context -recommendation can be supplied to `clickhouse-client` using -`--opentelemetry-traceparent` and `--opentelemetry-tracestate` flags. - -If no parent trace context is supplied, ClickHouse can start a new trace, with -probability controlled by the `opentelemetry_start_trace_probability` setting. +ClickHouse accepts trace context HTTP headers, as described by the [W3C recommendation](https://www.w3.org/TR/trace-context/). It also accepts trace context over a native protocol that is used for communication between ClickHouse servers or between the client and server. For manual testing, trace context headers conforming to the Trace Context recommendation can be supplied to `clickhouse-client` using `--opentelemetry-traceparent` and `--opentelemetry-tracestate` flags. +If no parent trace context is supplied, ClickHouse can start a new trace, with probability controlled by the [opentelemetry_start_trace_probability](../operations/settings/settings.md#opentelemetry-start-trace-probability) setting. ## Propagating the Trace Context The trace context is propagated to downstream services in the following cases: -* Queries to remote ClickHouse servers, such as when using `Distributed` table - engine. - -* `URL` table function. Trace context information is sent in HTTP headers. +* Queries to remote ClickHouse servers, such as when using [Distributed](../engines/table-engines/special/distributed.md) table engine. +* [url](../sql-reference/table-functions/url.md) table function. Trace context information is sent in HTTP headers. ## Tracing the ClickHouse Itself -ClickHouse creates _trace spans_ for each query and some of the query execution -stages, such as query planning or distributed queries. +ClickHouse creates `trace spans` for each query and some of the query execution stages, such as query planning or distributed queries. -To be useful, the tracing information has to be exported to a monitoring system -that supports OpenTelemetry, such as Jaeger or Prometheus. ClickHouse avoids -a dependency on a particular monitoring system, instead only providing the -tracing data through a system table. OpenTelemetry trace span information -[required by the standard](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/overview.md#span) -is stored in the `system.opentelemetry_span_log` table. +To be useful, the tracing information has to be exported to a monitoring system that supports OpenTelemetry, such as [Jaeger](https://jaegertracing.io/) or [Prometheus](https://prometheus.io/). ClickHouse avoids a dependency on a particular monitoring system, instead only providing the tracing data through a system table. OpenTelemetry trace span information [required by the standard](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/overview.md#span) is stored in the [system.opentelemetry_span_log](../operations/system-tables/opentelemetry_span_log.md) table. -The table must be enabled in the server configuration, see the `opentelemetry_span_log` -element in the default config file `config.xml`. It is enabled by default. +The table must be enabled in the server configuration, see the `opentelemetry_span_log` element in the default config file `config.xml`. It is enabled by default. -The table has the following columns: - -- `trace_id` -- `span_id` -- `parent_span_id` -- `operation_name` -- `start_time` -- `finish_time` -- `finish_date` -- `attribute.name` -- `attribute.values` - -The tags or attributes are saved as two parallel arrays, containing the keys -and values. Use `ARRAY JOIN` to work with them. +The tags or attributes are saved as two parallel arrays, containing the keys and values. Use [ARRAY JOIN](../sql-reference/statements/select/array-join.md) to work with them. ## Integration with monitoring systems -At the moment, there is no ready tool that can export the tracing data from -ClickHouse to a monitoring system. +At the moment, there is no ready tool that can export the tracing data from ClickHouse to a monitoring system. -For testing, it is possible to setup the export using a materialized view with the URL engine over the `system.opentelemetry_span_log` table, which would push the arriving log data to an HTTP endpoint of a trace collector. For example, to push the minimal span data to a Zipkin instance running at `http://localhost:9411`, in Zipkin v2 JSON format: +For testing, it is possible to setup the export using a materialized view with the [URL](../engines/table-engines/special/url.md) engine over the [system.opentelemetry_span_log](../operations/system-tables/opentelemetry_span_log.md) table, which would push the arriving log data to an HTTP endpoint of a trace collector. For example, to push the minimal span data to a Zipkin instance running at `http://localhost:9411`, in Zipkin v2 JSON format: ```sql CREATE MATERIALIZED VIEW default.zipkin_spans @@ -94,3 +60,5 @@ FROM system.opentelemetry_span_log ``` In case of any errors, the part of the log data for which the error has occurred will be silently lost. Check the server log for error messages if the data does not arrive. + +[Original article](https://clickhouse.tech/docs/en/operations/opentelemetry/) diff --git a/docs/en/operations/settings/settings-users.md b/docs/en/operations/settings/settings-users.md index 3e15d9e6dea..ee834dca98a 100644 --- a/docs/en/operations/settings/settings-users.md +++ b/docs/en/operations/settings/settings-users.md @@ -139,7 +139,7 @@ You can assign a quotas set for the user. For a detailed description of quotas c ### user_name/databases {#user-namedatabases} -In this section, you can you can limit rows that are returned by ClickHouse for `SELECT` queries made by the current user, thus implementing basic row-level security. +In this section, you can limit rows that are returned by ClickHouse for `SELECT` queries made by the current user, thus implementing basic row-level security. **Example** diff --git a/docs/en/operations/settings/settings.md b/docs/en/operations/settings/settings.md index c7ee48c11bf..3c343e09fd3 100644 --- a/docs/en/operations/settings/settings.md +++ b/docs/en/operations/settings/settings.md @@ -312,7 +312,7 @@ Enables or disables parsing enum values as enum ids for TSV input format. Possible values: - 0 — Enum values are parsed as values. -- 1 — Enum values are parsed as enum IDs +- 1 — Enum values are parsed as enum IDs. Default value: 0. @@ -1104,7 +1104,7 @@ The maximum number of replicas for each shard when executing a query. In limited - the sampling key is an expression that is expensive to calculate - the cluster's latency distribution has a long tail, so that querying more servers increases the query's overall latency -In addition, this setting will produce incorrect results when joins or subqueries are involved, and all tables don't meet certain conditions. See [Distributed Subqueries and max_parallel_replicas](../../sql-reference/operators/in.md/#max_parallel_replica-subqueries) for more details. +In addition, this setting will produce incorrect results when joins or subqueries are involved, and all tables don't meet certain conditions. See [Distributed Subqueries and max_parallel_replicas](../../sql-reference/operators/in.md#max_parallel_replica-subqueries) for more details. ## compile {#compile} @@ -1956,8 +1956,8 @@ Default value: 16. **See Also** -- [Kafka](../../engines/table-engines/integrations/kafka.md#kafka) engine -- [RabbitMQ](../../engines/table-engines/integrations/rabbitmq.md#rabbitmq-engine) engine +- [Kafka](../../engines/table-engines/integrations/kafka.md#kafka) engine. +- [RabbitMQ](../../engines/table-engines/integrations/rabbitmq.md#rabbitmq-engine) engine. ## validate_polygons {#validate_polygons} @@ -2592,6 +2592,18 @@ Possible values: Default value: `16`. +## opentelemetry_start_trace_probability {#opentelemetry-start-trace-probability} + +Sets the probability that the ClickHouse can start a trace for executed queries (if no parent [trace context](https://www.w3.org/TR/trace-context/) is supplied). + +Possible values: + +- 0 — The trace for all executed queries is disabled (if no parent trace context is supplied). +- Positive floating-point number in the range [0..1]. For example, if the setting value is `0,5`, ClickHouse can start a trace on average for half of the queries. +- 1 — The trace for all executed queries is enabled. + +Default value: `0`. + ## optimize_on_insert {#optimize-on-insert} Enables or disables data transformation before the insertion, as if merge was done on this block (according to table engine). @@ -2646,4 +2658,35 @@ Result: Note that this setting influences [Materialized view](../../sql-reference/statements/create/view.md#materialized) and [MaterializeMySQL](../../engines/database-engines/materialize-mysql.md) behaviour. +## engine_file_empty_if_not_exists {#engine-file-empty_if-not-exists} + +Allows to select data from a file engine table without file. + +Possible values: +- 0 — `SELECT` throws exception. +- 1 — `SELECT` returns empty result. + +Default value: `0`. + +## engine_file_truncate_on_insert {#engine-file-truncate-on-insert} + +Enables or disables truncate before insert in file engine tables. + +Possible values: +- 0 — Disabled. +- 1 — Enabled. + +Default value: `0`. + +## allow_experimental_geo_types {#allow-experimental-geo-types} + +Allows working with experimental [geo data types](../../sql-reference/data-types/geo.md). + +Possible values: + +- 0 — Working with geo data types is disabled. +- 1 — Working with geo data types is enabled. + +Default value: `0`. + [Original article](https://clickhouse.tech/docs/en/operations/settings/settings/) diff --git a/docs/en/operations/system-tables/distributed_ddl_queue.md b/docs/en/operations/system-tables/distributed_ddl_queue.md index c252458af8a..fa871d215b5 100644 --- a/docs/en/operations/system-tables/distributed_ddl_queue.md +++ b/docs/en/operations/system-tables/distributed_ddl_queue.md @@ -14,7 +14,7 @@ Columns: - `initiator` ([String](../../sql-reference/data-types/string.md)) — Node that executed the query. - `query_start_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — Query start time. - `query_finish_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — Query finish time. -- `query_duration_ms` ([UInt64](../../sql-reference/data-types/datetime64.md)) — Duration of query execution (in milliseconds). +- `query_duration_ms` ([UInt64](../../sql-reference/data-types/int-uint.md)) — Duration of query execution (in milliseconds). - `exception_code` ([Enum8](../../sql-reference/data-types/enum.md)) — Exception code from [ZooKeeper](../../operations/tips.md#zookeeper). **Example** diff --git a/docs/en/operations/system-tables/index.md b/docs/en/operations/system-tables/index.md index 5dc23aee686..e66f082167e 100644 --- a/docs/en/operations/system-tables/index.md +++ b/docs/en/operations/system-tables/index.md @@ -20,7 +20,7 @@ System tables: Most of system tables store their data in RAM. A ClickHouse server creates such system tables at the start. -Unlike other system tables, the system log tables [metric_log](../../operations/system-tables/metric_log.md), [query_log](../../operations/system-tables/query_log.md), [query_thread_log](../../operations/system-tables/query_thread_log.md), [trace_log](../../operations/system-tables/trace_log.md), [part_log](../../operations/system-tables/part_log.md), crash_log and [text_log](../../operations/system-tables/text_log.md) are served by [MergeTree](../../engines/table-engines/mergetree-family/mergetree.md) table engine and store their data in a storage filesystem by default. If you remove a table from a filesystem, the ClickHouse server creates the empty one again at the time of the next data writing. If system table schema changed in a new release, then ClickHouse renames the current table and creates a new one. +Unlike other system tables, the system log tables [metric_log](../../operations/system-tables/metric_log.md), [query_log](../../operations/system-tables/query_log.md), [query_thread_log](../../operations/system-tables/query_thread_log.md), [trace_log](../../operations/system-tables/trace_log.md), [part_log](../../operations/system-tables/part_log.md), [crash_log](../../operations/system-tables/crash-log.md) and [text_log](../../operations/system-tables/text_log.md) are served by [MergeTree](../../engines/table-engines/mergetree-family/mergetree.md) table engine and store their data in a filesystem by default. If you remove a table from a filesystem, the ClickHouse server creates the empty one again at the time of the next data writing. If system table schema changed in a new release, then ClickHouse renames the current table and creates a new one. System log tables can be customized by creating a config file with the same name as the table under `/etc/clickhouse-server/config.d/`, or setting corresponding elements in `/etc/clickhouse-server/config.xml`. Elements can be customized are: @@ -33,7 +33,7 @@ System log tables can be customized by creating a config file with the same name An example: -``` +```xml system diff --git a/docs/en/operations/system-tables/opentelemetry_span_log.md b/docs/en/operations/system-tables/opentelemetry_span_log.md new file mode 100644 index 00000000000..e45a989742c --- /dev/null +++ b/docs/en/operations/system-tables/opentelemetry_span_log.md @@ -0,0 +1,53 @@ +# system.opentelemetry_span_log {#system_tables-opentelemetry_span_log} + +Contains information about [trace spans](https://opentracing.io/docs/overview/spans/) for executed queries. + +Columns: + +- `trace_id` ([UUID](../../sql-reference/data-types/uuid.md) — ID of the trace for executed query. + +- `span_id` ([UInt64](../../sql-reference/data-types/int-uint.md)) — ID of the `trace span`. + +- `parent_span_id` ([UInt64](../../sql-reference/data-types/int-uint.md)) — ID of the parent `trace span`. + +- `operation_name` ([String](../../sql-reference/data-types/string.md)) — The name of the operation. + +- `start_time_us` ([UInt64](../../sql-reference/data-types/int-uint.md)) — The start time of the `trace span` (in microseconds). + +- `finish_time_us` ([UInt64](../../sql-reference/data-types/int-uint.md)) — The finish time of the `trace span` (in microseconds). + +- `finish_date` ([Date](../../sql-reference/data-types/date.md)) — The finish date of the `trace span`. + +- `attribute.names` ([Array](../../sql-reference/data-types/array.md)([String](../../sql-reference/data-types/string.md))) — [Attribute](https://opentelemetry.io/docs/go/instrumentation/#attributes) names depending on the `trace span`. They are filled in according to the recommendations in the [OpenTelemetry](https://opentelemetry.io/) standard. + +- `attribute.values` ([Array](../../sql-reference/data-types/array.md)([String](../../sql-reference/data-types/string.md))) — Attribute values depending on the `trace span`. They are filled in according to the recommendations in the `OpenTelemetry` standard. + +**Example** + +Query: + +``` sql +SELECT * FROM system.opentelemetry_span_log LIMIT 1 FORMAT Vertical; +``` + +Result: + +``` text +Row 1: +────── +trace_id: cdab0847-0d62-61d5-4d38-dd65b19a1914 +span_id: 701487461015578150 +parent_span_id: 2991972114672045096 +operation_name: DB::Block DB::InterpreterSelectQuery::getSampleBlockImpl() +start_time_us: 1612374594529090 +finish_time_us: 1612374594529108 +finish_date: 2021-02-03 +attribute.names: [] +attribute.values: [] +``` + +**See Also** + +- [OpenTelemetry](../../operations/opentelemetry.md) + +[Original article](https://clickhouse.tech/docs/en/operations/system_tables/opentelemetry_span_log) diff --git a/docs/en/operations/system-tables/part_log.md b/docs/en/operations/system-tables/part_log.md index 579fdaefb0a..3f9110349dd 100644 --- a/docs/en/operations/system-tables/part_log.md +++ b/docs/en/operations/system-tables/part_log.md @@ -17,7 +17,6 @@ The `system.part_log` table contains the following columns: - `event_date` ([Date](../../sql-reference/data-types/date.md)) — Event date. - `event_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — Event time. - `event_time_microseconds` ([DateTime64](../../sql-reference/data-types/datetime64.md)) — Event time with microseconds precision. - - `duration_ms` ([UInt64](../../sql-reference/data-types/int-uint.md)) — Duration. - `database` ([String](../../sql-reference/data-types/string.md)) — Name of the database the data part is in. - `table` ([String](../../sql-reference/data-types/string.md)) — Name of the table the data part is in. diff --git a/docs/en/operations/system-tables/settings.md b/docs/en/operations/system-tables/settings.md index a1db0a3d558..7034fe1204f 100644 --- a/docs/en/operations/system-tables/settings.md +++ b/docs/en/operations/system-tables/settings.md @@ -48,5 +48,6 @@ SELECT * FROM system.settings WHERE changed AND name='load_balancing' - [Settings](../../operations/settings/index.md#session-settings-intro) - [Permissions for Queries](../../operations/settings/permissions-for-queries.md#settings_readonly) - [Constraints on Settings](../../operations/settings/constraints-on-settings.md) +- [SHOW SETTINGS](../../sql-reference/statements/show.md#show-settings) statement [Original article](https://clickhouse.tech/docs/en/operations/system_tables/settings) diff --git a/docs/en/operations/system-tables/trace_log.md b/docs/en/operations/system-tables/trace_log.md index 2903e0d3bd7..b3b04795a60 100644 --- a/docs/en/operations/system-tables/trace_log.md +++ b/docs/en/operations/system-tables/trace_log.md @@ -52,4 +52,5 @@ trace: [371912858,371912789,371798468,371799717,371801313,3717 size: 5244400 ``` - [Original article](https://clickhouse.tech/docs/en/operations/system_tables/trace_log) \ No newline at end of file + [Original article](https://clickhouse.tech/docs/en/operations/system-tables/trace_log) + diff --git a/docs/en/operations/update.md b/docs/en/operations/update.md index edacf1ff973..9fa9c44e130 100644 --- a/docs/en/operations/update.md +++ b/docs/en/operations/update.md @@ -1,9 +1,9 @@ --- toc_priority: 47 -toc_title: ClickHouse Update +toc_title: ClickHouse Upgrade --- -# ClickHouse Update {#clickhouse-update} +# ClickHouse Upgrade {#clickhouse-upgrade} If ClickHouse was installed from `deb` packages, execute the following commands on the server: @@ -16,3 +16,19 @@ $ sudo service clickhouse-server restart If you installed ClickHouse using something other than the recommended `deb` packages, use the appropriate update method. ClickHouse does not support a distributed update. The operation should be performed consecutively on each separate server. Do not update all the servers on a cluster simultaneously, or the cluster will be unavailable for some time. + +The upgrade of older version of ClickHouse to specific version: + +As an example: + +`xx.yy.a.b` is a current stable version. The latest stable version could be found [here](https://github.com/ClickHouse/ClickHouse/releases) + +```bash +$ sudo apt-get update +$ sudo apt-get install clickhouse-server=xx.yy.a.b clickhouse-client=xx.yy.a.b clickhouse-common-static=xx.yy.a.b +$ sudo service clickhouse-server restart +``` + + + + diff --git a/docs/en/operations/utilities/clickhouse-local.md b/docs/en/operations/utilities/clickhouse-local.md index 04f9f3660b5..cfabf42bff1 100644 --- a/docs/en/operations/utilities/clickhouse-local.md +++ b/docs/en/operations/utilities/clickhouse-local.md @@ -91,6 +91,8 @@ $ clickhouse-local --query " Now let’s output memory user for each Unix user: +Query: + ``` bash $ ps aux | tail -n +2 | awk '{ printf("%s\t%s\n", $1, $4) }' \ | clickhouse-local --structure "user String, mem Float64" \ @@ -98,6 +100,8 @@ $ ps aux | tail -n +2 | awk '{ printf("%s\t%s\n", $1, $4) }' \ FROM table GROUP BY user ORDER BY memTotal DESC FORMAT Pretty" ``` +Result: + ``` text Read 186 rows, 4.15 KiB in 0.035 sec., 5302 rows/sec., 118.34 KiB/sec. ┏━━━━━━━━━━┳━━━━━━━━━━┓ diff --git a/docs/en/sql-reference/aggregate-functions/combinators.md b/docs/en/sql-reference/aggregate-functions/combinators.md index 431968bc629..015c90e90c7 100644 --- a/docs/en/sql-reference/aggregate-functions/combinators.md +++ b/docs/en/sql-reference/aggregate-functions/combinators.md @@ -72,7 +72,7 @@ If an aggregate function doesn’t have input values, with this combinator it re OrDefault(x) ``` -**Parameters** +**Arguments** - `x` — Aggregate function parameters. @@ -132,7 +132,7 @@ This combinator converts a result of an aggregate function to the [Nullable](../ OrNull(x) ``` -**Parameters** +**Arguments** - `x` — Aggregate function parameters. @@ -189,7 +189,7 @@ Lets you divide data into groups, and then separately aggregates the data in tho Resample(start, end, step)(, resampling_key) ``` -**Parameters** +**Arguments** - `start` — Starting value of the whole required interval for `resampling_key` values. - `stop` — Ending value of the whole required interval for `resampling_key` values. The whole interval doesn’t include the `stop` value `[start, stop)`. diff --git a/docs/en/sql-reference/aggregate-functions/parametric-functions.md b/docs/en/sql-reference/aggregate-functions/parametric-functions.md index 4b3bf12aa8c..c6c97b5428b 100644 --- a/docs/en/sql-reference/aggregate-functions/parametric-functions.md +++ b/docs/en/sql-reference/aggregate-functions/parametric-functions.md @@ -17,10 +17,13 @@ histogram(number_of_bins)(values) The functions uses [A Streaming Parallel Decision Tree Algorithm](http://jmlr.org/papers/volume11/ben-haim10a/ben-haim10a.pdf). The borders of histogram bins are adjusted as new data enters a function. In common case, the widths of bins are not equal. +**Arguments** + +`values` — [Expression](../../sql-reference/syntax.md#syntax-expressions) resulting in input values. + **Parameters** `number_of_bins` — Upper limit for the number of bins in the histogram. The function automatically calculates the number of bins. It tries to reach the specified number of bins, but if it fails, it uses fewer bins. -`values` — [Expression](../../sql-reference/syntax.md#syntax-expressions) resulting in input values. **Returned values** @@ -89,14 +92,16 @@ sequenceMatch(pattern)(timestamp, cond1, cond2, ...) !!! warning "Warning" Events that occur at the same second may lay in the sequence in an undefined order affecting the result. -**Parameters** - -- `pattern` — Pattern string. See [Pattern syntax](#sequence-function-pattern-syntax). +**Arguments** - `timestamp` — Column considered to contain time data. Typical data types are `Date` and `DateTime`. You can also use any of the supported [UInt](../../sql-reference/data-types/int-uint.md) data types. - `cond1`, `cond2` — Conditions that describe the chain of events. Data type: `UInt8`. You can pass up to 32 condition arguments. The function takes only the events described in these conditions into account. If the sequence contains data that isn’t described in a condition, the function skips them. +**Parameters** + +- `pattern` — Pattern string. See [Pattern syntax](#sequence-function-pattern-syntax). + **Returned values** - 1, if the pattern is matched. @@ -176,14 +181,16 @@ Counts the number of event chains that matched the pattern. The function searche sequenceCount(pattern)(timestamp, cond1, cond2, ...) ``` -**Parameters** - -- `pattern` — Pattern string. See [Pattern syntax](#sequence-function-pattern-syntax). +**Arguments** - `timestamp` — Column considered to contain time data. Typical data types are `Date` and `DateTime`. You can also use any of the supported [UInt](../../sql-reference/data-types/int-uint.md) data types. - `cond1`, `cond2` — Conditions that describe the chain of events. Data type: `UInt8`. You can pass up to 32 condition arguments. The function takes only the events described in these conditions into account. If the sequence contains data that isn’t described in a condition, the function skips them. +**Parameters** + +- `pattern` — Pattern string. See [Pattern syntax](#sequence-function-pattern-syntax). + **Returned values** - Number of non-overlapping event chains that are matched. @@ -239,14 +246,17 @@ The function works according to the algorithm: windowFunnel(window, [mode])(timestamp, cond1, cond2, ..., condN) ``` -**Parameters** +**Arguments** -- `window` — Length of the sliding window. The unit of `window` depends on the timestamp itself and varies. Determined using the expression `timestamp of cond2 <= timestamp of cond1 + window`. -- `mode` - It is an optional argument. - - `'strict'` - When the `'strict'` is set, the windowFunnel() applies conditions only for the unique values. - `timestamp` — Name of the column containing the timestamp. Data types supported: [Date](../../sql-reference/data-types/date.md), [DateTime](../../sql-reference/data-types/datetime.md#data_type-datetime) and other unsigned integer types (note that even though timestamp supports the `UInt64` type, it’s value can’t exceed the Int64 maximum, which is 2^63 - 1). - `cond` — Conditions or data describing the chain of events. [UInt8](../../sql-reference/data-types/int-uint.md). +**Parameters** + +- `window` — Length of the sliding window. The unit of `window` depends on the `timestamp` itself and varies. Determined using the expression `timestamp of cond2 <= timestamp of cond1 + window`. +- `mode` - It is an optional argument. + - `'strict'` - When the `'strict'` is set, the windowFunnel() applies conditions only for the unique values. + **Returned value** The maximum number of consecutive triggered conditions from the chain within the sliding time window. @@ -324,7 +334,7 @@ The conditions, except the first, apply in pairs: the result of the second will retention(cond1, cond2, ..., cond32); ``` -**Parameters** +**Arguments** - `cond` — an expression that returns a `UInt8` result (1 or 0). diff --git a/docs/en/sql-reference/aggregate-functions/reference/argmax.md b/docs/en/sql-reference/aggregate-functions/reference/argmax.md index 9899c731ce9..72aa607a751 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/argmax.md +++ b/docs/en/sql-reference/aggregate-functions/reference/argmax.md @@ -20,7 +20,7 @@ or argMax(tuple(arg, val)) ``` -**Parameters** +**Arguments** - `arg` — Argument. - `val` — Value. @@ -52,15 +52,15 @@ Input table: Query: ``` sql -SELECT argMax(user, salary), argMax(tuple(user, salary)) FROM salary; +SELECT argMax(user, salary), argMax(tuple(user, salary), salary), argMax(tuple(user, salary)) FROM salary; ``` Result: ``` text -┌─argMax(user, salary)─┬─argMax(tuple(user, salary))─┐ -│ director │ ('director',5000) │ -└──────────────────────┴─────────────────────────────┘ +┌─argMax(user, salary)─┬─argMax(tuple(user, salary), salary)─┬─argMax(tuple(user, salary))─┐ +│ director │ ('director',5000) │ ('director',5000) │ +└──────────────────────┴─────────────────────────────────────┴─────────────────────────────┘ ``` [Original article](https://clickhouse.tech/docs/en/sql-reference/aggregate-functions/reference/argmax/) diff --git a/docs/en/sql-reference/aggregate-functions/reference/argmin.md b/docs/en/sql-reference/aggregate-functions/reference/argmin.md index 2fe9a313260..7ddc38cd28a 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/argmin.md +++ b/docs/en/sql-reference/aggregate-functions/reference/argmin.md @@ -20,7 +20,7 @@ or argMin(tuple(arg, val)) ``` -**Parameters** +**Arguments** - `arg` — Argument. - `val` — Value. diff --git a/docs/en/sql-reference/aggregate-functions/reference/avg.md b/docs/en/sql-reference/aggregate-functions/reference/avg.md index e2e6aace734..cbd409ccab6 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/avg.md +++ b/docs/en/sql-reference/aggregate-functions/reference/avg.md @@ -9,31 +9,24 @@ Calculates the arithmetic mean. **Syntax** ``` sql -avgWeighted(x) +avg(x) ``` -**Parameter** +**Arguments** -- `x` — Values. - -`x` must be -[Integer](../../../sql-reference/data-types/int-uint.md), -[floating-point](../../../sql-reference/data-types/float.md), or -[Decimal](../../../sql-reference/data-types/decimal.md). +- `x` — input values, must be [Integer](../../../sql-reference/data-types/int-uint.md), [Float](../../../sql-reference/data-types/float.md), or [Decimal](../../../sql-reference/data-types/decimal.md). **Returned value** -- `NaN` if the supplied parameter is empty. -- Mean otherwise. - -**Return type** is always [Float64](../../../sql-reference/data-types/float.md). +- The arithmetic mean, always as [Float64](../../../sql-reference/data-types/float.md). +- `NaN` if the input parameter `x` is empty. **Example** Query: ``` sql -SELECT avg(x) FROM values('x Int8', 0, 1, 2, 3, 4, 5) +SELECT avg(x) FROM values('x Int8', 0, 1, 2, 3, 4, 5); ``` Result: @@ -46,11 +39,20 @@ Result: **Example** +Create a temp table: + Query: ``` sql CREATE table test (t UInt8) ENGINE = Memory; -SELECT avg(t) FROM test +``` + +Get the arithmetic mean: + +Query: + +``` +SELECT avg(t) FROM test; ``` Result: @@ -60,3 +62,5 @@ Result: │ nan │ └────────┘ ``` + +[Original article](https://clickhouse.tech/docs/en/sql-reference/aggregate-functions/reference/avg/) diff --git a/docs/en/sql-reference/aggregate-functions/reference/avgweighted.md b/docs/en/sql-reference/aggregate-functions/reference/avgweighted.md index 7b9c0de2755..2df09e560b4 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/avgweighted.md +++ b/docs/en/sql-reference/aggregate-functions/reference/avgweighted.md @@ -12,7 +12,7 @@ Calculates the [weighted arithmetic mean](https://en.wikipedia.org/wiki/Weighted avgWeighted(x, weight) ``` -**Parameters** +**Arguments** - `x` — Values. - `weight` — Weights of the values. diff --git a/docs/en/sql-reference/aggregate-functions/reference/count.md b/docs/en/sql-reference/aggregate-functions/reference/count.md index e5d31429e12..0a5aef2fe97 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/count.md +++ b/docs/en/sql-reference/aggregate-functions/reference/count.md @@ -10,7 +10,7 @@ ClickHouse supports the following syntaxes for `count`: - `count(expr)` or `COUNT(DISTINCT expr)`. - `count()` or `COUNT(*)`. The `count()` syntax is ClickHouse-specific. -**Parameters** +**Arguments** The function can take: diff --git a/docs/en/sql-reference/aggregate-functions/reference/grouparrayinsertat.md b/docs/en/sql-reference/aggregate-functions/reference/grouparrayinsertat.md index f4b8665a0a4..68456bf7844 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/grouparrayinsertat.md +++ b/docs/en/sql-reference/aggregate-functions/reference/grouparrayinsertat.md @@ -17,7 +17,7 @@ If in one query several values are inserted into the same position, the function - If a query is executed in a single thread, the first one of the inserted values is used. - If a query is executed in multiple threads, the resulting value is an undetermined one of the inserted values. -**Parameters** +**Arguments** - `x` — Value to be inserted. [Expression](../../../sql-reference/syntax.md#syntax-expressions) resulting in one of the [supported data types](../../../sql-reference/data-types/index.md). - `pos` — Position at which the specified element `x` is to be inserted. Index numbering in the array starts from zero. [UInt32](../../../sql-reference/data-types/int-uint.md#uint-ranges). diff --git a/docs/en/sql-reference/aggregate-functions/reference/grouparraymovingavg.md b/docs/en/sql-reference/aggregate-functions/reference/grouparraymovingavg.md index 1cd40c2002f..c732efecf58 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/grouparraymovingavg.md +++ b/docs/en/sql-reference/aggregate-functions/reference/grouparraymovingavg.md @@ -13,7 +13,7 @@ groupArrayMovingAvg(window_size)(numbers_for_summing) The function can take the window size as a parameter. If left unspecified, the function takes the window size equal to the number of rows in the column. -**Parameters** +**Arguments** - `numbers_for_summing` — [Expression](../../../sql-reference/syntax.md#syntax-expressions) resulting in a numeric data type value. - `window_size` — Size of the calculation window. diff --git a/docs/en/sql-reference/aggregate-functions/reference/grouparraymovingsum.md b/docs/en/sql-reference/aggregate-functions/reference/grouparraymovingsum.md index ef979cd5f6a..c3dfeda850e 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/grouparraymovingsum.md +++ b/docs/en/sql-reference/aggregate-functions/reference/grouparraymovingsum.md @@ -13,7 +13,7 @@ groupArrayMovingSum(window_size)(numbers_for_summing) The function can take the window size as a parameter. If left unspecified, the function takes the window size equal to the number of rows in the column. -**Parameters** +**Arguments** - `numbers_for_summing` — [Expression](../../../sql-reference/syntax.md#syntax-expressions) resulting in a numeric data type value. - `window_size` — Size of the calculation window. diff --git a/docs/en/sql-reference/aggregate-functions/reference/grouparraysample.md b/docs/en/sql-reference/aggregate-functions/reference/grouparraysample.md index 36fa6a9d661..df0b8120eef 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/grouparraysample.md +++ b/docs/en/sql-reference/aggregate-functions/reference/grouparraysample.md @@ -12,7 +12,7 @@ Creates an array of sample argument values. The size of the resulting array is l groupArraySample(max_size[, seed])(x) ``` -**Parameters** +**Arguments** - `max_size` — Maximum size of the resulting array. [UInt64](../../data-types/int-uint.md). - `seed` — Seed for the random number generator. Optional. [UInt64](../../data-types/int-uint.md). Default value: `123456`. diff --git a/docs/en/sql-reference/aggregate-functions/reference/groupbitand.md b/docs/en/sql-reference/aggregate-functions/reference/groupbitand.md index 9be73fd54ec..1275ad7536c 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/groupbitand.md +++ b/docs/en/sql-reference/aggregate-functions/reference/groupbitand.md @@ -10,7 +10,7 @@ Applies bitwise `AND` for series of numbers. groupBitAnd(expr) ``` -**Parameters** +**Arguments** `expr` – An expression that results in `UInt*` type. diff --git a/docs/en/sql-reference/aggregate-functions/reference/groupbitmap.md b/docs/en/sql-reference/aggregate-functions/reference/groupbitmap.md index 9367652db38..9317ef98783 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/groupbitmap.md +++ b/docs/en/sql-reference/aggregate-functions/reference/groupbitmap.md @@ -10,7 +10,7 @@ Bitmap or Aggregate calculations from a unsigned integer column, return cardinal groupBitmap(expr) ``` -**Parameters** +**Arguments** `expr` – An expression that results in `UInt*` type. diff --git a/docs/en/sql-reference/aggregate-functions/reference/groupbitmapand.md b/docs/en/sql-reference/aggregate-functions/reference/groupbitmapand.md index 7c0c89040bb..f59bb541a42 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/groupbitmapand.md +++ b/docs/en/sql-reference/aggregate-functions/reference/groupbitmapand.md @@ -10,7 +10,7 @@ Calculations the AND of a bitmap column, return cardinality of type UInt64, if a groupBitmapAnd(expr) ``` -**Parameters** +**Arguments** `expr` – An expression that results in `AggregateFunction(groupBitmap, UInt*)` type. diff --git a/docs/en/sql-reference/aggregate-functions/reference/groupbitmapor.md b/docs/en/sql-reference/aggregate-functions/reference/groupbitmapor.md index 894c6c90aab..a4d99fd29e3 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/groupbitmapor.md +++ b/docs/en/sql-reference/aggregate-functions/reference/groupbitmapor.md @@ -10,7 +10,7 @@ Calculations the OR of a bitmap column, return cardinality of type UInt64, if ad groupBitmapOr(expr) ``` -**Parameters** +**Arguments** `expr` – An expression that results in `AggregateFunction(groupBitmap, UInt*)` type. diff --git a/docs/en/sql-reference/aggregate-functions/reference/groupbitmapxor.md b/docs/en/sql-reference/aggregate-functions/reference/groupbitmapxor.md index 5d0ec0fb097..834f088d02f 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/groupbitmapxor.md +++ b/docs/en/sql-reference/aggregate-functions/reference/groupbitmapxor.md @@ -10,7 +10,7 @@ Calculations the XOR of a bitmap column, return cardinality of type UInt64, if a groupBitmapOr(expr) ``` -**Parameters** +**Arguments** `expr` – An expression that results in `AggregateFunction(groupBitmap, UInt*)` type. diff --git a/docs/en/sql-reference/aggregate-functions/reference/groupbitor.md b/docs/en/sql-reference/aggregate-functions/reference/groupbitor.md index 7383e620060..e427a9ad970 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/groupbitor.md +++ b/docs/en/sql-reference/aggregate-functions/reference/groupbitor.md @@ -10,7 +10,7 @@ Applies bitwise `OR` for series of numbers. groupBitOr(expr) ``` -**Parameters** +**Arguments** `expr` – An expression that results in `UInt*` type. diff --git a/docs/en/sql-reference/aggregate-functions/reference/groupbitxor.md b/docs/en/sql-reference/aggregate-functions/reference/groupbitxor.md index 01026012b91..4b8323f92db 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/groupbitxor.md +++ b/docs/en/sql-reference/aggregate-functions/reference/groupbitxor.md @@ -10,7 +10,7 @@ Applies bitwise `XOR` for series of numbers. groupBitXor(expr) ``` -**Parameters** +**Arguments** `expr` – An expression that results in `UInt*` type. diff --git a/docs/en/sql-reference/aggregate-functions/reference/initializeAggregation.md b/docs/en/sql-reference/aggregate-functions/reference/initializeAggregation.md index ea44d5f1ddd..313d6bf81f5 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/initializeAggregation.md +++ b/docs/en/sql-reference/aggregate-functions/reference/initializeAggregation.md @@ -13,7 +13,7 @@ Use it for tests or to process columns of types `AggregateFunction` and `Aggrega initializeAggregation (aggregate_function, column_1, column_2); ``` -**Parameters** +**Arguments** - `aggregate_function` — Name of the aggregation function. The state of this function — the creating one. [String](../../../sql-reference/data-types/string.md#string). - `column_n` — The column to translate it into the function as it's argument. [String](../../../sql-reference/data-types/string.md#string). diff --git a/docs/en/sql-reference/aggregate-functions/reference/kurtpop.md b/docs/en/sql-reference/aggregate-functions/reference/kurtpop.md index 65e7e31b9b4..db402c99663 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/kurtpop.md +++ b/docs/en/sql-reference/aggregate-functions/reference/kurtpop.md @@ -10,7 +10,7 @@ Computes the [kurtosis](https://en.wikipedia.org/wiki/Kurtosis) of a sequence. kurtPop(expr) ``` -**Parameters** +**Arguments** `expr` — [Expression](../../../sql-reference/syntax.md#syntax-expressions) returning a number. diff --git a/docs/en/sql-reference/aggregate-functions/reference/kurtsamp.md b/docs/en/sql-reference/aggregate-functions/reference/kurtsamp.md index 224bbbdb9e7..4bb9f76763b 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/kurtsamp.md +++ b/docs/en/sql-reference/aggregate-functions/reference/kurtsamp.md @@ -12,7 +12,7 @@ It represents an unbiased estimate of the kurtosis of a random variable if passe kurtSamp(expr) ``` -**Parameters** +**Arguments** `expr` — [Expression](../../../sql-reference/syntax.md#syntax-expressions) returning a number. diff --git a/docs/en/sql-reference/aggregate-functions/reference/mannwhitneyutest.md b/docs/en/sql-reference/aggregate-functions/reference/mannwhitneyutest.md index 012df7052aa..dc5fc45b878 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/mannwhitneyutest.md +++ b/docs/en/sql-reference/aggregate-functions/reference/mannwhitneyutest.md @@ -16,6 +16,11 @@ mannWhitneyUTest[(alternative[, continuity_correction])](sample_data, sample_ind Values of both samples are in the `sample_data` column. If `sample_index` equals to 0 then the value in that row belongs to the sample from the first population. Otherwise it belongs to the sample from the second population. The null hypothesis is that two populations are stochastically equal. Also one-sided hypothesises can be tested. This test does not assume that data have normal distribution. +**Arguments** + +- `sample_data` — sample data. [Integer](../../../sql-reference/data-types/int-uint.md), [Float](../../../sql-reference/data-types/float.md) or [Decimal](../../../sql-reference/data-types/decimal.md). +- `sample_index` — sample index. [Integer](../../../sql-reference/data-types/int-uint.md). + **Parameters** - `alternative` — alternative hypothesis. (Optional, default: `'two-sided'`.) [String](../../../sql-reference/data-types/string.md). @@ -23,13 +28,11 @@ The null hypothesis is that two populations are stochastically equal. Also one-s - `'greater'`; - `'less'`. - `continuity_correction` - if not 0 then continuity correction in the normal approximation for the p-value is applied. (Optional, default: 1.) [UInt64](../../../sql-reference/data-types/int-uint.md). -- `sample_data` — sample data. [Integer](../../../sql-reference/data-types/int-uint.md), [Float](../../../sql-reference/data-types/float.md) or [Decimal](../../../sql-reference/data-types/decimal.md). -- `sample_index` — sample index. [Integer](../../../sql-reference/data-types/int-uint.md). - **Returned values** [Tuple](../../../sql-reference/data-types/tuple.md) with two elements: + - calculated U-statistic. [Float64](../../../sql-reference/data-types/float.md). - calculated p-value. [Float64](../../../sql-reference/data-types/float.md). diff --git a/docs/en/sql-reference/aggregate-functions/reference/quantile.md b/docs/en/sql-reference/aggregate-functions/reference/quantile.md index 77f858a1735..d625ef4cfd9 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/quantile.md +++ b/docs/en/sql-reference/aggregate-functions/reference/quantile.md @@ -18,7 +18,7 @@ quantile(level)(expr) Alias: `median`. -**Parameters** +**Arguments** - `level` — Level of quantile. Optional parameter. Constant floating-point number from 0 to 1. We recommend using a `level` value in the range of `[0.01, 0.99]`. Default value: 0.5. At `level=0.5` the function calculates [median](https://en.wikipedia.org/wiki/Median). - `expr` — Expression over the column values resulting in numeric [data types](../../../sql-reference/data-types/index.md#data_types), [Date](../../../sql-reference/data-types/date.md) or [DateTime](../../../sql-reference/data-types/datetime.md). diff --git a/docs/en/sql-reference/aggregate-functions/reference/quantiledeterministic.md b/docs/en/sql-reference/aggregate-functions/reference/quantiledeterministic.md index 6046447dd10..a20ac26f599 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/quantiledeterministic.md +++ b/docs/en/sql-reference/aggregate-functions/reference/quantiledeterministic.md @@ -18,7 +18,7 @@ quantileDeterministic(level)(expr, determinator) Alias: `medianDeterministic`. -**Parameters** +**Arguments** - `level` — Level of quantile. Optional parameter. Constant floating-point number from 0 to 1. We recommend using a `level` value in the range of `[0.01, 0.99]`. Default value: 0.5. At `level=0.5` the function calculates [median](https://en.wikipedia.org/wiki/Median). - `expr` — Expression over the column values resulting in numeric [data types](../../../sql-reference/data-types/index.md#data_types), [Date](../../../sql-reference/data-types/date.md) or [DateTime](../../../sql-reference/data-types/datetime.md). diff --git a/docs/en/sql-reference/aggregate-functions/reference/quantileexact.md b/docs/en/sql-reference/aggregate-functions/reference/quantileexact.md index a39f724f368..06ef7ccfbd3 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/quantileexact.md +++ b/docs/en/sql-reference/aggregate-functions/reference/quantileexact.md @@ -18,7 +18,7 @@ quantileExact(level)(expr) Alias: `medianExact`. -**Parameters** +**Arguments** - `level` — Level of quantile. Optional parameter. Constant floating-point number from 0 to 1. We recommend using a `level` value in the range of `[0.01, 0.99]`. Default value: 0.5. At `level=0.5` the function calculates [median](https://en.wikipedia.org/wiki/Median). - `expr` — Expression over the column values resulting in numeric [data types](../../../sql-reference/data-types/index.md#data_types), [Date](../../../sql-reference/data-types/date.md) or [DateTime](../../../sql-reference/data-types/datetime.md). @@ -77,7 +77,7 @@ quantileExact(level)(expr) Alias: `medianExactLow`. -**Parameters** +**Arguments** - `level` — Level of quantile. Optional parameter. Constant floating-point number from 0 to 1. We recommend using a `level` value in the range of `[0.01, 0.99]`. Default value: 0.5. At `level=0.5` the function calculates [median](https://en.wikipedia.org/wiki/Median). - `expr` — Expression over the column values resulting in numeric [data types](../../../sql-reference/data-types/index.md#data_types), [Date](../../../sql-reference/data-types/date.md) or [DateTime](../../../sql-reference/data-types/datetime.md). @@ -128,7 +128,7 @@ quantileExactHigh(level)(expr) Alias: `medianExactHigh`. -**Parameters** +**Arguments** - `level` — Level of quantile. Optional parameter. Constant floating-point number from 0 to 1. We recommend using a `level` value in the range of `[0.01, 0.99]`. Default value: 0.5. At `level=0.5` the function calculates [median](https://en.wikipedia.org/wiki/Median). - `expr` — Expression over the column values resulting in numeric [data types](../../../sql-reference/data-types/index.md#data_types), [Date](../../../sql-reference/data-types/date.md) or [DateTime](../../../sql-reference/data-types/datetime.md). diff --git a/docs/en/sql-reference/aggregate-functions/reference/quantileexactweighted.md b/docs/en/sql-reference/aggregate-functions/reference/quantileexactweighted.md index 3251f8298a6..210f44e7587 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/quantileexactweighted.md +++ b/docs/en/sql-reference/aggregate-functions/reference/quantileexactweighted.md @@ -18,7 +18,7 @@ quantileExactWeighted(level)(expr, weight) Alias: `medianExactWeighted`. -**Parameters** +**Arguments** - `level` — Level of quantile. Optional parameter. Constant floating-point number from 0 to 1. We recommend using a `level` value in the range of `[0.01, 0.99]`. Default value: 0.5. At `level=0.5` the function calculates [median](https://en.wikipedia.org/wiki/Median). - `expr` — Expression over the column values resulting in numeric [data types](../../../sql-reference/data-types/index.md#data_types), [Date](../../../sql-reference/data-types/date.md) or [DateTime](../../../sql-reference/data-types/datetime.md). diff --git a/docs/en/sql-reference/aggregate-functions/reference/quantiletdigest.md b/docs/en/sql-reference/aggregate-functions/reference/quantiletdigest.md index bda98ea338d..dcc665a68af 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/quantiletdigest.md +++ b/docs/en/sql-reference/aggregate-functions/reference/quantiletdigest.md @@ -20,7 +20,7 @@ quantileTDigest(level)(expr) Alias: `medianTDigest`. -**Parameters** +**Arguments** - `level` — Level of quantile. Optional parameter. Constant floating-point number from 0 to 1. We recommend using a `level` value in the range of `[0.01, 0.99]`. Default value: 0.5. At `level=0.5` the function calculates [median](https://en.wikipedia.org/wiki/Median). - `expr` — Expression over the column values resulting in numeric [data types](../../../sql-reference/data-types/index.md#data_types), [Date](../../../sql-reference/data-types/date.md) or [DateTime](../../../sql-reference/data-types/datetime.md). diff --git a/docs/en/sql-reference/aggregate-functions/reference/quantiletdigestweighted.md b/docs/en/sql-reference/aggregate-functions/reference/quantiletdigestweighted.md index 309cbe95e95..56ef598f7e7 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/quantiletdigestweighted.md +++ b/docs/en/sql-reference/aggregate-functions/reference/quantiletdigestweighted.md @@ -20,7 +20,7 @@ quantileTDigest(level)(expr) Alias: `medianTDigest`. -**Parameters** +**Arguments** - `level` — Level of quantile. Optional parameter. Constant floating-point number from 0 to 1. We recommend using a `level` value in the range of `[0.01, 0.99]`. Default value: 0.5. At `level=0.5` the function calculates [median](https://en.wikipedia.org/wiki/Median). - `expr` — Expression over the column values resulting in numeric [data types](../../../sql-reference/data-types/index.md#data_types), [Date](../../../sql-reference/data-types/date.md) or [DateTime](../../../sql-reference/data-types/datetime.md). diff --git a/docs/en/sql-reference/aggregate-functions/reference/quantiletiming.md b/docs/en/sql-reference/aggregate-functions/reference/quantiletiming.md index 867e8b87e74..58ce6495a96 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/quantiletiming.md +++ b/docs/en/sql-reference/aggregate-functions/reference/quantiletiming.md @@ -18,7 +18,7 @@ quantileTiming(level)(expr) Alias: `medianTiming`. -**Parameters** +**Arguments** - `level` — Level of quantile. Optional parameter. Constant floating-point number from 0 to 1. We recommend using a `level` value in the range of `[0.01, 0.99]`. Default value: 0.5. At `level=0.5` the function calculates [median](https://en.wikipedia.org/wiki/Median). diff --git a/docs/en/sql-reference/aggregate-functions/reference/quantiletimingweighted.md b/docs/en/sql-reference/aggregate-functions/reference/quantiletimingweighted.md index 817cd831d85..fb3b9dbf4d2 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/quantiletimingweighted.md +++ b/docs/en/sql-reference/aggregate-functions/reference/quantiletimingweighted.md @@ -18,7 +18,7 @@ quantileTimingWeighted(level)(expr, weight) Alias: `medianTimingWeighted`. -**Parameters** +**Arguments** - `level` — Level of quantile. Optional parameter. Constant floating-point number from 0 to 1. We recommend using a `level` value in the range of `[0.01, 0.99]`. Default value: 0.5. At `level=0.5` the function calculates [median](https://en.wikipedia.org/wiki/Median). diff --git a/docs/en/sql-reference/aggregate-functions/reference/rankCorr.md b/docs/en/sql-reference/aggregate-functions/reference/rankCorr.md index dc23029f239..55ee1b8289b 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/rankCorr.md +++ b/docs/en/sql-reference/aggregate-functions/reference/rankCorr.md @@ -8,7 +8,7 @@ Computes a rank correlation coefficient. rankCorr(x, y) ``` -**Parameters** +**Arguments** - `x` — Arbitrary value. [Float32](../../../sql-reference/data-types/float.md#float32-float64) or [Float64](../../../sql-reference/data-types/float.md#float32-float64). - `y` — Arbitrary value. [Float32](../../../sql-reference/data-types/float.md#float32-float64) or [Float64](../../../sql-reference/data-types/float.md#float32-float64). diff --git a/docs/en/sql-reference/aggregate-functions/reference/skewpop.md b/docs/en/sql-reference/aggregate-functions/reference/skewpop.md index d15a5ffdd47..b9dfc390f9d 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/skewpop.md +++ b/docs/en/sql-reference/aggregate-functions/reference/skewpop.md @@ -10,7 +10,7 @@ Computes the [skewness](https://en.wikipedia.org/wiki/Skewness) of a sequence. skewPop(expr) ``` -**Parameters** +**Arguments** `expr` — [Expression](../../../sql-reference/syntax.md#syntax-expressions) returning a number. diff --git a/docs/en/sql-reference/aggregate-functions/reference/skewsamp.md b/docs/en/sql-reference/aggregate-functions/reference/skewsamp.md index cb323f4b142..f7a6df8f507 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/skewsamp.md +++ b/docs/en/sql-reference/aggregate-functions/reference/skewsamp.md @@ -12,7 +12,7 @@ It represents an unbiased estimate of the skewness of a random variable if passe skewSamp(expr) ``` -**Parameters** +**Arguments** `expr` — [Expression](../../../sql-reference/syntax.md#syntax-expressions) returning a number. diff --git a/docs/en/sql-reference/aggregate-functions/reference/studentttest.md b/docs/en/sql-reference/aggregate-functions/reference/studentttest.md index f868e976039..a1d7ae33fe1 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/studentttest.md +++ b/docs/en/sql-reference/aggregate-functions/reference/studentttest.md @@ -16,7 +16,7 @@ studentTTest(sample_data, sample_index) Values of both samples are in the `sample_data` column. If `sample_index` equals to 0 then the value in that row belongs to the sample from the first population. Otherwise it belongs to the sample from the second population. The null hypothesis is that means of populations are equal. Normal distribution with equal variances is assumed. -**Parameters** +**Arguments** - `sample_data` — sample data. [Integer](../../../sql-reference/data-types/int-uint.md), [Float](../../../sql-reference/data-types/float.md) or [Decimal](../../../sql-reference/data-types/decimal.md). - `sample_index` — sample index. [Integer](../../../sql-reference/data-types/int-uint.md). @@ -24,6 +24,7 @@ The null hypothesis is that means of populations are equal. Normal distribution **Returned values** [Tuple](../../../sql-reference/data-types/tuple.md) with two elements: + - calculated t-statistic. [Float64](../../../sql-reference/data-types/float.md). - calculated p-value. [Float64](../../../sql-reference/data-types/float.md). diff --git a/docs/en/sql-reference/aggregate-functions/reference/topk.md b/docs/en/sql-reference/aggregate-functions/reference/topk.md index 004a67d33af..b3e79803ba1 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/topk.md +++ b/docs/en/sql-reference/aggregate-functions/reference/topk.md @@ -16,7 +16,7 @@ This function doesn’t provide a guaranteed result. In certain situations, erro We recommend using the `N < 10` value; performance is reduced with large `N` values. Maximum value of `N = 65536`. -**Parameters** +**Arguments** - ‘N’ is the number of elements to return. diff --git a/docs/en/sql-reference/aggregate-functions/reference/topkweighted.md b/docs/en/sql-reference/aggregate-functions/reference/topkweighted.md index b597317f44e..02b9f77ea6f 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/topkweighted.md +++ b/docs/en/sql-reference/aggregate-functions/reference/topkweighted.md @@ -12,7 +12,7 @@ Similar to `topK` but takes one additional argument of integer type - `weight`. topKWeighted(N)(x, weight) ``` -**Parameters** +**Arguments** - `N` — The number of elements to return. diff --git a/docs/en/sql-reference/aggregate-functions/reference/uniq.md b/docs/en/sql-reference/aggregate-functions/reference/uniq.md index 81d1ec6761e..7ba2cdc6cb8 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/uniq.md +++ b/docs/en/sql-reference/aggregate-functions/reference/uniq.md @@ -10,7 +10,7 @@ Calculates the approximate number of different values of the argument. uniq(x[, ...]) ``` -**Parameters** +**Arguments** The function takes a variable number of parameters. Parameters can be `Tuple`, `Array`, `Date`, `DateTime`, `String`, or numeric types. diff --git a/docs/en/sql-reference/aggregate-functions/reference/uniqcombined.md b/docs/en/sql-reference/aggregate-functions/reference/uniqcombined.md index c52486bc38f..4434686ae61 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/uniqcombined.md +++ b/docs/en/sql-reference/aggregate-functions/reference/uniqcombined.md @@ -12,7 +12,7 @@ uniqCombined(HLL_precision)(x[, ...]) The `uniqCombined` function is a good choice for calculating the number of different values. -**Parameters** +**Arguments** The function takes a variable number of parameters. Parameters can be `Tuple`, `Array`, `Date`, `DateTime`, `String`, or numeric types. diff --git a/docs/en/sql-reference/aggregate-functions/reference/uniqexact.md b/docs/en/sql-reference/aggregate-functions/reference/uniqexact.md index 9a6224533c8..eee675016ee 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/uniqexact.md +++ b/docs/en/sql-reference/aggregate-functions/reference/uniqexact.md @@ -14,7 +14,7 @@ Use the `uniqExact` function if you absolutely need an exact result. Otherwise u The `uniqExact` function uses more memory than `uniq`, because the size of the state has unbounded growth as the number of different values increases. -**Parameters** +**Arguments** The function takes a variable number of parameters. Parameters can be `Tuple`, `Array`, `Date`, `DateTime`, `String`, or numeric types. diff --git a/docs/en/sql-reference/aggregate-functions/reference/uniqhll12.md b/docs/en/sql-reference/aggregate-functions/reference/uniqhll12.md index fcddc22cc46..5b23ea81eae 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/uniqhll12.md +++ b/docs/en/sql-reference/aggregate-functions/reference/uniqhll12.md @@ -10,7 +10,7 @@ Calculates the approximate number of different argument values, using the [Hyper uniqHLL12(x[, ...]) ``` -**Parameters** +**Arguments** The function takes a variable number of parameters. Parameters can be `Tuple`, `Array`, `Date`, `DateTime`, `String`, or numeric types. diff --git a/docs/en/sql-reference/aggregate-functions/reference/welchttest.md b/docs/en/sql-reference/aggregate-functions/reference/welchttest.md index 3fe1c9d58b9..b391fb1d979 100644 --- a/docs/en/sql-reference/aggregate-functions/reference/welchttest.md +++ b/docs/en/sql-reference/aggregate-functions/reference/welchttest.md @@ -16,7 +16,7 @@ welchTTest(sample_data, sample_index) Values of both samples are in the `sample_data` column. If `sample_index` equals to 0 then the value in that row belongs to the sample from the first population. Otherwise it belongs to the sample from the second population. The null hypothesis is that means of populations are equal. Normal distribution is assumed. Populations may have unequal variance. -**Parameters** +**Arguments** - `sample_data` — sample data. [Integer](../../../sql-reference/data-types/int-uint.md), [Float](../../../sql-reference/data-types/float.md) or [Decimal](../../../sql-reference/data-types/decimal.md). - `sample_index` — sample index. [Integer](../../../sql-reference/data-types/int-uint.md). @@ -24,6 +24,7 @@ The null hypothesis is that means of populations are equal. Normal distribution **Returned values** [Tuple](../../../sql-reference/data-types/tuple.md) with two elements: + - calculated t-statistic. [Float64](../../../sql-reference/data-types/float.md). - calculated p-value. [Float64](../../../sql-reference/data-types/float.md). diff --git a/docs/en/sql-reference/data-types/datetime.md b/docs/en/sql-reference/data-types/datetime.md index 07a6e38a5fa..d95abe57510 100644 --- a/docs/en/sql-reference/data-types/datetime.md +++ b/docs/en/sql-reference/data-types/datetime.md @@ -19,15 +19,17 @@ Resolution: 1 second. ## Usage Remarks {#usage-remarks} -The point in time is saved as a [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time), regardless of the time zone or daylight saving time. Additionally, the `DateTime` type can store time zone that is the same for the entire column, that affects how the values of the `DateTime` type values are displayed in text format and how the values specified as strings are parsed (‘2020-01-01 05:00:01’). The time zone is not stored in the rows of the table (or in resultset), but is stored in the column metadata. -A list of supported time zones can be found in the [IANA Time Zone Database](https://www.iana.org/time-zones). -The `tzdata` package, containing [IANA Time Zone Database](https://www.iana.org/time-zones), should be installed in the system. Use the `timedatectl list-timezones` command to list timezones known by a local system. +The point in time is saved as a [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time), regardless of the time zone or daylight saving time. The time zone affects how the values of the `DateTime` type values are displayed in text format and how the values specified as strings are parsed (‘2020-01-01 05:00:01’). -You can explicitly set a time zone for `DateTime`-type columns when creating a table. If the time zone isn’t set, ClickHouse uses the value of the [timezone](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone) parameter in the server settings or the operating system settings at the moment of the ClickHouse server start. +Timezone agnostic unix timestamp is stored in tables, and the timezone is used to transform it to text format or back during data import/export or to make calendar calculations on the values (example: `toDate`, `toHour` functions et cetera). The time zone is not stored in the rows of the table (or in resultset), but is stored in the column metadata. + +A list of supported time zones can be found in the [IANA Time Zone Database](https://www.iana.org/time-zones) and also can be queried by `SELECT * FROM system.time_zones`. + +You can explicitly set a time zone for `DateTime`-type columns when creating a table. Example: `DateTime('UTC')`. If the time zone isn’t set, ClickHouse uses the value of the [timezone](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone) parameter in the server settings or the operating system settings at the moment of the ClickHouse server start. The [clickhouse-client](../../interfaces/cli.md) applies the server time zone by default if a time zone isn’t explicitly set when initializing the data type. To use the client time zone, run `clickhouse-client` with the `--use_client_time_zone` parameter. -ClickHouse outputs values depending on the value of the [date\_time\_output\_format](../../operations/settings/settings.md#settings-date_time_output_format) setting. `YYYY-MM-DD hh:mm:ss` text format by default. Additionaly you can change the output with the [formatDateTime](../../sql-reference/functions/date-time-functions.md#formatdatetime) function. +ClickHouse outputs values depending on the value of the [date_time_output_format](../../operations/settings/settings.md#settings-date_time_output_format) setting. `YYYY-MM-DD hh:mm:ss` text format by default. Additionaly you can change the output with the [formatDateTime](../../sql-reference/functions/date-time-functions.md#formatdatetime) function. When inserting data into ClickHouse, you can use different formats of date and time strings, depending on the value of the [date_time_input_format](../../operations/settings/settings.md#settings-date_time_input_format) setting. @@ -114,6 +116,24 @@ FROM dt └─────────────────────┴─────────────────────┘ ``` +As timezone conversion only changes the metadata, the operation has no computation cost. + + +## Limitations on timezones support + +Some timezones may not be supported completely. There are a few cases: + +If the offset from UTC is not a multiple of 15 minutes, the calculation of hours and minutes can be incorrect. For example, the time zone in Monrovia, Liberia has offset UTC -0:44:30 before 7 Jan 1972. If you are doing calculations on the historical time in Monrovia timezone, the time processing functions may give incorrect results. The results after 7 Jan 1972 will be correct nevertheless. + +If the time transition (due to daylight saving time or for other reasons) was performed at a point of time that is not a multiple of 15 minutes, you can also get incorrect results at this specific day. + +Non-monotonic calendar dates. For example, in Happy Valley - Goose Bay, the time was transitioned one hour backwards at 00:01:00 7 Nov 2010 (one minute after midnight). So after 6th Nov has ended, people observed a whole one minute of 7th Nov, then time was changed back to 23:01 6th Nov and after another 59 minutes the 7th Nov started again. ClickHouse does not (yet) support this kind of fun. During these days the results of time processing functions may be slightly incorrect. + +Similar issue exists for Casey Antarctic station in year 2010. They changed time three hours back at 5 Mar, 02:00. If you are working in antarctic station, please don't afraid to use ClickHouse. Just make sure you set timezone to UTC or be aware of inaccuracies. + +Time shifts for multiple days. Some pacific islands changed their timezone offset from UTC+14 to UTC-12. That's alright but some inaccuracies may present if you do calculations with their timezone for historical time points at the days of conversion. + + ## See Also {#see-also} - [Type conversion functions](../../sql-reference/functions/type-conversion-functions.md) diff --git a/docs/en/sql-reference/data-types/geo.md b/docs/en/sql-reference/data-types/geo.md new file mode 100644 index 00000000000..9ed328e0de6 --- /dev/null +++ b/docs/en/sql-reference/data-types/geo.md @@ -0,0 +1,106 @@ +--- +toc_priority: 62 +toc_title: Geo +--- + +# Geo Data Types {#geo-data-types} + +Clickhouse supports data types for representing geographical objects — locations, lands, etc. + +!!! warning "Warning" + Currently geo data types are an experimental feature. To work with them you must set `allow_experimental_geo_types = 1`. + +**See Also** +- [Representing simple geographical features](https://en.wikipedia.org/wiki/GeoJSON). +- [allow_experimental_geo_types](../../operations/settings/settings.md#allow-experimental-geo-types) setting. + +## Point {#point-data-type} + +`Point` is represented by its X and Y coordinates, stored as a [Tuple](tuple.md)([Float64](float.md), [Float64](float.md)). + +**Example** + +Query: + +```sql +SET allow_experimental_geo_types = 1; +CREATE TABLE geo_point (p Point) ENGINE = Memory(); +INSERT INTO geo_point VALUES((10, 10)); +SELECT p, toTypeName(p) FROM geo_point; +``` +Result: + +``` text +┌─p─────┬─toTypeName(p)─┐ +│ (10,10) │ Point │ +└───────┴───────────────┘ +``` + +## Ring {#ring-data-type} + +`Ring` is a simple polygon without holes stored as an array of points: [Array](array.md)([Point](#point-data-type)). + +**Example** + +Query: + +```sql +SET allow_experimental_geo_types = 1; +CREATE TABLE geo_ring (r Ring) ENGINE = Memory(); +INSERT INTO geo_ring VALUES([(0, 0), (10, 0), (10, 10), (0, 10)]); +SELECT r, toTypeName(r) FROM geo_ring; +``` +Result: + +``` text +┌─r─────────────────────────────┬─toTypeName(r)─┐ +│ [(0,0),(10,0),(10,10),(0,10)] │ Ring │ +└───────────────────────────────┴───────────────┘ +``` + +## Polygon {#polygon-data-type} + +`Polygon` is a polygon with holes stored as an array of rings: [Array](array.md)([Ring](#ring-data-type)). First element of outer array is the outer shape of polygon and all the following elements are holes. + +**Example** + +This is a polygon with one hole: + +```sql +SET allow_experimental_geo_types = 1; +CREATE TABLE geo_polygon (pg Polygon) ENGINE = Memory(); +INSERT INTO geo_polygon VALUES([[(20, 20), (50, 20), (50, 50), (20, 50)], [(30, 30), (50, 50), (50, 30)]]); +SELECT pg, toTypeName(pg) FROM geo_polygon; +``` + +Result: + +``` text +┌─pg────────────────────────────────────────────────────────────┬─toTypeName(pg)─┐ +│ [[(20,20),(50,20),(50,50),(20,50)],[(30,30),(50,50),(50,30)]] │ Polygon │ +└───────────────────────────────────────────────────────────────┴────────────────┘ +``` + +## MultiPolygon {#multipolygon-data-type} + +`MultiPolygon` consists of multiple polygons and is stored as an array of polygons: [Array](array.md)([Polygon](#polygon-data-type)). + +**Example** + +This multipolygon consists of two separate polygons — the first one without holes, and the second with one hole: + +```sql +SET allow_experimental_geo_types = 1; +CREATE TABLE geo_multipolygon (mpg MultiPolygon) ENGINE = Memory(); +INSERT INTO geo_multipolygon VALUES([[[(0, 0), (10, 0), (10, 10), (0, 10)]], [[(20, 20), (50, 20), (50, 50), (20, 50)],[(30, 30), (50, 50), (50, 30)]]]); +SELECT mpg, toTypeName(mpg) FROM geo_multipolygon; +``` +Result: + +``` text +┌─mpg─────────────────────────────────────────────────────────────────────────────────────────────┬─toTypeName(mpg)─┐ +│ [[[(0,0),(10,0),(10,10),(0,10)]],[[(20,20),(50,20),(50,50),(20,50)],[(30,30),(50,50),(50,30)]]] │ MultiPolygon │ +└─────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────┘ +``` + +[Original article](https://clickhouse.tech/docs/en/data-types/geo/) diff --git a/docs/en/sql-reference/data-types/map.md b/docs/en/sql-reference/data-types/map.md new file mode 100644 index 00000000000..58634e5b669 --- /dev/null +++ b/docs/en/sql-reference/data-types/map.md @@ -0,0 +1,83 @@ +--- +toc_priority: 65 +toc_title: Map(key, value) +--- + +# Map(key, value) {#data_type-map} + +`Map(key, value)` data type stores `key:value` pairs. + +**Parameters** +- `key` — The key part of the pair. [String](../../sql-reference/data-types/string.md) or [Integer](../../sql-reference/data-types/int-uint.md). +- `value` — The value part of the pair. [String](../../sql-reference/data-types/string.md), [Integer](../../sql-reference/data-types/int-uint.md) or [Array](../../sql-reference/data-types/array.md). + +!!! warning "Warning" + Currently `Map` data type is an experimental feature. To work with it you must set `allow_experimental_map_type = 1`. + +To get the value from an `a Map('key', 'value')` column, use `a['key']` syntax. This lookup works now with a linear complexity. + +**Examples** + +Consider the table: + +``` sql +CREATE TABLE table_map (a Map(String, UInt64)) ENGINE=Memory; +INSERT INTO table_map VALUES ({'key1':1, 'key2':10}), ({'key1':2,'key2':20}), ({'key1':3,'key2':30}); +``` + +Select all `key2` values: + +```sql +SELECT a['key2'] FROM table_map; +``` +Result: + +```text +┌─arrayElement(a, 'key2')─┐ +│ 10 │ +│ 20 │ +│ 30 │ +└─────────────────────────┘ +``` + +If there's no such `key` in the `Map()` column, the query returns zeros for numerical values, empty strings or empty arrays. + +```sql +INSERT INTO table_map VALUES ({'key3':100}), ({}); +SELECT a['key3'] FROM table_map; +``` + +Result: + +```text +┌─arrayElement(a, 'key3')─┐ +│ 100 │ +│ 0 │ +└─────────────────────────┘ +┌─arrayElement(a, 'key3')─┐ +│ 0 │ +│ 0 │ +│ 0 │ +└─────────────────────────┘ +``` + +## Convert Tuple to Map Type {#map-and-tuple} + +You can cast `Tuple()` as `Map()` using [CAST](../../sql-reference/functions/type-conversion-functions.md#type_conversion_function-cast) function: + +``` sql +SELECT CAST(([1, 2, 3], ['Ready', 'Steady', 'Go']), 'Map(UInt8, String)') AS map; +``` + +``` text +┌─map───────────────────────────┐ +│ {1:'Ready',2:'Steady',3:'Go'} │ +└───────────────────────────────┘ +``` + +**See Also** + +- [map()](../../sql-reference/functions/tuple-map-functions.md#function-map) function +- [CAST()](../../sql-reference/functions/type-conversion-functions.md#type_conversion_function-cast) function + +[Original article](https://clickhouse.tech/docs/en/data-types/map/) diff --git a/docs/en/sql-reference/data-types/simpleaggregatefunction.md b/docs/en/sql-reference/data-types/simpleaggregatefunction.md index 2d2746f85d3..244779c5ca8 100644 --- a/docs/en/sql-reference/data-types/simpleaggregatefunction.md +++ b/docs/en/sql-reference/data-types/simpleaggregatefunction.md @@ -21,7 +21,11 @@ The following aggregate functions are supported: - [`argMin`](../../sql-reference/aggregate-functions/reference/argmin.md) - [`argMax`](../../sql-reference/aggregate-functions/reference/argmax.md) -Values of the `SimpleAggregateFunction(func, Type)` look and stored the same way as `Type`, so you do not need to apply functions with `-Merge`/`-State` suffixes. `SimpleAggregateFunction` has better performance than `AggregateFunction` with same aggregation function. + +!!! note "Note" + Values of the `SimpleAggregateFunction(func, Type)` look and stored the same way as `Type`, so you do not need to apply functions with `-Merge`/`-State` suffixes. + + `SimpleAggregateFunction` has better performance than `AggregateFunction` with same aggregation function. **Parameters** @@ -31,11 +35,7 @@ Values of the `SimpleAggregateFunction(func, Type)` look and stored the same way **Example** ``` sql -CREATE TABLE t -( - column1 SimpleAggregateFunction(sum, UInt64), - column2 SimpleAggregateFunction(any, String) -) ENGINE = ... +CREATE TABLE simple (id UInt64, val SimpleAggregateFunction(sum, Double)) ENGINE=AggregatingMergeTree ORDER BY id; ``` [Original article](https://clickhouse.tech/docs/en/data_types/simpleaggregatefunction/) diff --git a/docs/en/sql-reference/functions/array-functions.md b/docs/en/sql-reference/functions/array-functions.md index d5b357795d7..c9c418d57a4 100644 --- a/docs/en/sql-reference/functions/array-functions.md +++ b/docs/en/sql-reference/functions/array-functions.md @@ -61,7 +61,7 @@ Combines arrays passed as arguments. arrayConcat(arrays) ``` -**Parameters** +**Arguments** - `arrays` – Arbitrary number of arguments of [Array](../../sql-reference/data-types/array.md) type. **Example** @@ -111,7 +111,7 @@ Checks whether one array is a subset of another. hasAll(set, subset) ``` -**Parameters** +**Arguments** - `set` – Array of any type with a set of elements. - `subset` – Array of any type with elements that should be tested to be a subset of `set`. @@ -149,7 +149,7 @@ Checks whether two arrays have intersection by some elements. hasAny(array1, array2) ``` -**Parameters** +**Arguments** - `array1` – Array of any type with a set of elements. - `array2` – Array of any type with a set of elements. @@ -191,7 +191,7 @@ For Example: - `hasSubstr([1,2,3,4], [2,3])` returns 1. However, `hasSubstr([1,2,3,4], [3,2])` will return `0`. - `hasSubstr([1,2,3,4], [1,2,3])` returns 1. However, `hasSubstr([1,2,3,4], [1,2,4])` will return `0`. -**Parameters** +**Arguments** - `array1` – Array of any type with a set of elements. - `array2` – Array of any type with a set of elements. @@ -369,7 +369,7 @@ Removes the last item from the array. arrayPopBack(array) ``` -**Parameters** +**Arguments** - `array` – Array. @@ -393,7 +393,7 @@ Removes the first item from the array. arrayPopFront(array) ``` -**Parameters** +**Arguments** - `array` – Array. @@ -417,7 +417,7 @@ Adds one item to the end of the array. arrayPushBack(array, single_value) ``` -**Parameters** +**Arguments** - `array` – Array. - `single_value` – A single value. Only numbers can be added to an array with numbers, and only strings can be added to an array of strings. When adding numbers, ClickHouse automatically sets the `single_value` type for the data type of the array. For more information about the types of data in ClickHouse, see “[Data types](../../sql-reference/data-types/index.md#data_types)”. Can be `NULL`. The function adds a `NULL` element to an array, and the type of array elements converts to `Nullable`. @@ -442,7 +442,7 @@ Adds one element to the beginning of the array. arrayPushFront(array, single_value) ``` -**Parameters** +**Arguments** - `array` – Array. - `single_value` – A single value. Only numbers can be added to an array with numbers, and only strings can be added to an array of strings. When adding numbers, ClickHouse automatically sets the `single_value` type for the data type of the array. For more information about the types of data in ClickHouse, see “[Data types](../../sql-reference/data-types/index.md#data_types)”. Can be `NULL`. The function adds a `NULL` element to an array, and the type of array elements converts to `Nullable`. @@ -467,7 +467,7 @@ Changes the length of the array. arrayResize(array, size[, extender]) ``` -**Parameters:** +**Arguments:** - `array` — Array. - `size` — Required length of the array. @@ -509,7 +509,7 @@ Returns a slice of the array. arraySlice(array, offset[, length]) ``` -**Parameters** +**Arguments** - `array` – Array of data. - `offset` – Indent from the edge of the array. A positive value indicates an offset on the left, and a negative value is an indent on the right. Numbering of the array items begins with 1. @@ -751,7 +751,7 @@ Calculates the difference between adjacent array elements. Returns an array wher arrayDifference(array) ``` -**Parameters** +**Arguments** - `array` – [Array](https://clickhouse.tech/docs/en/data_types/array/). @@ -803,7 +803,7 @@ Takes an array, returns an array containing the distinct elements only. arrayDistinct(array) ``` -**Parameters** +**Arguments** - `array` – [Array](https://clickhouse.tech/docs/en/data_types/array/). @@ -871,7 +871,7 @@ Applies an aggregate function to array elements and returns its result. The name arrayReduce(agg_func, arr1, arr2, ..., arrN) ``` -**Parameters** +**Arguments** - `agg_func` — The name of an aggregate function which should be a constant [string](../../sql-reference/data-types/string.md). - `arr` — Any number of [array](../../sql-reference/data-types/array.md) type columns as the parameters of the aggregation function. @@ -936,7 +936,7 @@ Applies an aggregate function to array elements in given ranges and returns an a arrayReduceInRanges(agg_func, ranges, arr1, arr2, ..., arrN) ``` -**Parameters** +**Arguments** - `agg_func` — The name of an aggregate function which should be a constant [string](../../sql-reference/data-types/string.md). - `ranges` — The ranges to aggretate which should be an [array](../../sql-reference/data-types/array.md) of [tuples](../../sql-reference/data-types/tuple.md) which containing the index and the length of each range. @@ -1007,7 +1007,7 @@ flatten(array_of_arrays) Alias: `flatten`. -**Parameters** +**Arguments** - `array_of_arrays` — [Array](../../sql-reference/data-types/array.md) of arrays. For example, `[[1,2,3], [4,5]]`. @@ -1033,7 +1033,7 @@ Removes consecutive duplicate elements from an array. The order of result values arrayCompact(arr) ``` -**Parameters** +**Arguments** `arr` — The [array](../../sql-reference/data-types/array.md) to inspect. @@ -1069,7 +1069,7 @@ Combines multiple arrays into a single array. The resulting array contains the c arrayZip(arr1, arr2, ..., arrN) ``` -**Parameters** +**Arguments** - `arrN` — [Array](../../sql-reference/data-types/array.md). @@ -1107,7 +1107,7 @@ Calculate AUC (Area Under the Curve, which is a concept in machine learning, see arrayAUC(arr_scores, arr_labels) ``` -**Parameters** +**Arguments** - `arr_scores` — scores prediction model gives. - `arr_labels` — labels of samples, usually 1 for positive sample and 0 for negtive sample. @@ -1302,7 +1302,7 @@ Note that the `arrayMin` is a [higher-order function](../../sql-reference/functi arrayMin([func,] arr) ``` -**Parameters** +**Arguments** - `func` — Function. [Expression](../../sql-reference/data-types/special-data-types/expression.md). - `arr` — Array. [Array](../../sql-reference/data-types/array.md). @@ -1357,7 +1357,7 @@ Note that the `arrayMax` is a [higher-order function](../../sql-reference/functi arrayMax([func,] arr) ``` -**Parameters** +**Arguments** - `func` — Function. [Expression](../../sql-reference/data-types/special-data-types/expression.md). - `arr` — Array. [Array](../../sql-reference/data-types/array.md). @@ -1412,7 +1412,7 @@ Note that the `arraySum` is a [higher-order function](../../sql-reference/functi arraySum([func,] arr) ``` -**Parameters** +**Arguments** - `func` — Function. [Expression](../../sql-reference/data-types/special-data-types/expression.md). - `arr` — Array. [Array](../../sql-reference/data-types/array.md). @@ -1467,7 +1467,7 @@ Note that the `arrayAvg` is a [higher-order function](../../sql-reference/functi arrayAvg([func,] arr) ``` -**Parameters** +**Arguments** - `func` — Function. [Expression](../../sql-reference/data-types/special-data-types/expression.md). - `arr` — Array. [Array](../../sql-reference/data-types/array.md). diff --git a/docs/en/sql-reference/functions/bit-functions.md b/docs/en/sql-reference/functions/bit-functions.md index 57c2ae42ada..a3d0c82d8ab 100644 --- a/docs/en/sql-reference/functions/bit-functions.md +++ b/docs/en/sql-reference/functions/bit-functions.md @@ -35,7 +35,7 @@ Takes any integer and converts it into [binary form](https://en.wikipedia.org/wi SELECT bitTest(number, index) ``` -**Parameters** +**Arguments** - `number` – integer number. - `index` – position of bit. @@ -100,7 +100,7 @@ The conjuction for bitwise operations: SELECT bitTestAll(number, index1, index2, index3, index4, ...) ``` -**Parameters** +**Arguments** - `number` – integer number. - `index1`, `index2`, `index3`, `index4` – positions of bit. For example, for set of positions (`index1`, `index2`, `index3`, `index4`) is true if and only if all of its positions are true (`index1` ⋀ `index2`, ⋀ `index3` ⋀ `index4`). @@ -165,7 +165,7 @@ The disjunction for bitwise operations: SELECT bitTestAny(number, index1, index2, index3, index4, ...) ``` -**Parameters** +**Arguments** - `number` – integer number. - `index1`, `index2`, `index3`, `index4` – positions of bit. @@ -220,7 +220,7 @@ Calculates the number of bits set to one in the binary representation of a numbe bitCount(x) ``` -**Parameters** +**Arguments** - `x` — [Integer](../../sql-reference/data-types/int-uint.md) or [floating-point](../../sql-reference/data-types/float.md) number. The function uses the value representation in memory. It allows supporting floating-point numbers. diff --git a/docs/en/sql-reference/functions/bitmap-functions.md b/docs/en/sql-reference/functions/bitmap-functions.md index a66098beffb..bfff70576f2 100644 --- a/docs/en/sql-reference/functions/bitmap-functions.md +++ b/docs/en/sql-reference/functions/bitmap-functions.md @@ -21,7 +21,7 @@ Build a bitmap from unsigned integer array. bitmapBuild(array) ``` -**Parameters** +**Arguments** - `array` – unsigned integer array. @@ -45,7 +45,7 @@ Convert bitmap to integer array. bitmapToArray(bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -69,7 +69,7 @@ Return subset in specified range (not include the range_end). bitmapSubsetInRange(bitmap, range_start, range_end) ``` -**Parameters** +**Arguments** - `bitmap` – [Bitmap object](#bitmap_functions-bitmapbuild). - `range_start` – range start point. Type: [UInt32](../../sql-reference/data-types/int-uint.md). @@ -97,7 +97,7 @@ Creates a subset of bitmap with n elements taken between `range_start` and `card bitmapSubsetLimit(bitmap, range_start, cardinality_limit) ``` -**Parameters** +**Arguments** - `bitmap` – [Bitmap object](#bitmap_functions-bitmapbuild). - `range_start` – The subset starting point. Type: [UInt32](../../sql-reference/data-types/int-uint.md). @@ -133,7 +133,7 @@ Checks whether the bitmap contains an element. bitmapContains(haystack, needle) ``` -**Parameters** +**Arguments** - `haystack` – [Bitmap object](#bitmap_functions-bitmapbuild), where the function searches. - `needle` – Value that the function searches. Type: [UInt32](../../sql-reference/data-types/int-uint.md). @@ -167,7 +167,7 @@ bitmapHasAny(bitmap1, bitmap2) If you are sure that `bitmap2` contains strictly one element, consider using the [bitmapContains](#bitmap_functions-bitmapcontains) function. It works more efficiently. -**Parameters** +**Arguments** - `bitmap*` – bitmap object. @@ -197,7 +197,7 @@ If the second argument is an empty bitmap then returns 1. bitmapHasAll(bitmap,bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -221,7 +221,7 @@ Retrun bitmap cardinality of type UInt64. bitmapCardinality(bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -243,7 +243,7 @@ Retrun the smallest value of type UInt64 in the set, UINT32_MAX if the set is em bitmapMin(bitmap) -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -263,7 +263,7 @@ Retrun the greatest value of type UInt64 in the set, 0 if the set is empty. bitmapMax(bitmap) -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -283,7 +283,7 @@ Transform an array of values in a bitmap to another array of values, the result bitmapTransform(bitmap, from_array, to_array) -**Parameters** +**Arguments** - `bitmap` – bitmap object. - `from_array` – UInt32 array. For idx in range \[0, from_array.size()), if bitmap contains from_array\[idx\], then replace it with to_array\[idx\]. Note that the result depends on array ordering if there are common elements between from_array and to_array. @@ -307,7 +307,7 @@ Two bitmap and calculation, the result is a new bitmap. bitmapAnd(bitmap,bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -331,7 +331,7 @@ Two bitmap or calculation, the result is a new bitmap. bitmapOr(bitmap,bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -355,7 +355,7 @@ Two bitmap xor calculation, the result is a new bitmap. bitmapXor(bitmap,bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -379,7 +379,7 @@ Two bitmap andnot calculation, the result is a new bitmap. bitmapAndnot(bitmap,bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -403,7 +403,7 @@ Two bitmap and calculation, return cardinality of type UInt64. bitmapAndCardinality(bitmap,bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -427,7 +427,7 @@ Two bitmap or calculation, return cardinality of type UInt64. bitmapOrCardinality(bitmap,bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -451,7 +451,7 @@ Two bitmap xor calculation, return cardinality of type UInt64. bitmapXorCardinality(bitmap,bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. @@ -475,7 +475,7 @@ Two bitmap andnot calculation, return cardinality of type UInt64. bitmapAndnotCardinality(bitmap,bitmap) ``` -**Parameters** +**Arguments** - `bitmap` – bitmap object. diff --git a/docs/en/sql-reference/functions/conditional-functions.md b/docs/en/sql-reference/functions/conditional-functions.md index 446a4729ff2..2d57cbb3bd5 100644 --- a/docs/en/sql-reference/functions/conditional-functions.md +++ b/docs/en/sql-reference/functions/conditional-functions.md @@ -17,7 +17,7 @@ SELECT if(cond, then, else) If the condition `cond` evaluates to a non-zero value, returns the result of the expression `then`, and the result of the expression `else`, if present, is skipped. If the `cond` is zero or `NULL`, then the result of the `then` expression is skipped and the result of the `else` expression, if present, is returned. -**Parameters** +**Arguments** - `cond` – The condition for evaluation that can be zero or not. The type is UInt8, Nullable(UInt8) or NULL. - `then` - The expression to return if condition is met. @@ -117,7 +117,7 @@ Allows you to write the [CASE](../../sql-reference/operators/index.md#operator_c Syntax: `multiIf(cond_1, then_1, cond_2, then_2, ..., else)` -**Parameters:** +**Arguments:** - `cond_N` — The condition for the function to return `then_N`. - `then_N` — The result of the function when executed. diff --git a/docs/en/sql-reference/functions/date-time-functions.md b/docs/en/sql-reference/functions/date-time-functions.md index 4a73bdb2546..304371f44eb 100644 --- a/docs/en/sql-reference/functions/date-time-functions.md +++ b/docs/en/sql-reference/functions/date-time-functions.md @@ -61,40 +61,58 @@ int32samoa: 1546300800 Converts a date or date with time to a UInt16 number containing the year number (AD). +Alias: `YEAR`. + ## toQuarter {#toquarter} Converts a date or date with time to a UInt8 number containing the quarter number. +Alias: `QUARTER`. + ## toMonth {#tomonth} Converts a date or date with time to a UInt8 number containing the month number (1-12). +Alias: `MONTH`. + ## toDayOfYear {#todayofyear} Converts a date or date with time to a UInt16 number containing the number of the day of the year (1-366). +Alias: `DAYOFYEAR`. + ## toDayOfMonth {#todayofmonth} Converts a date or date with time to a UInt8 number containing the number of the day of the month (1-31). +Aliases: `DAYOFMONTH`, `DAY`. + ## toDayOfWeek {#todayofweek} Converts a date or date with time to a UInt8 number containing the number of the day of the week (Monday is 1, and Sunday is 7). +Alias: `DAYOFWEEK`. + ## toHour {#tohour} Converts a date with time to a UInt8 number containing the number of the hour in 24-hour time (0-23). This function assumes that if clocks are moved ahead, it is by one hour and occurs at 2 a.m., and if clocks are moved back, it is by one hour and occurs at 3 a.m. (which is not always true – even in Moscow the clocks were twice changed at a different time). +Alias: `HOUR`. + ## toMinute {#tominute} Converts a date with time to a UInt8 number containing the number of the minute of the hour (0-59). +Alias: `MINUTE`. + ## toSecond {#tosecond} Converts a date with time to a UInt8 number containing the number of the second in the minute (0-59). Leap seconds are not accounted for. +Alias: `SECOND`. + ## toUnixTimestamp {#to-unix-timestamp} For DateTime argument: converts value to the number with type UInt32 -- Unix Timestamp (https://en.wikipedia.org/wiki/Unix_time). @@ -186,7 +204,7 @@ Truncates sub-seconds. toStartOfSecond(value[, timezone]) ``` -**Parameters** +**Arguments** - `value` — Date and time. [DateTime64](../../sql-reference/data-types/datetime64.md). - `timezone` — [Timezone](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone) for the returned value (optional). If not specified, the function uses the timezone of the `value` parameter. [String](../../sql-reference/data-types/string.md). @@ -328,7 +346,7 @@ For mode values with a meaning of “contains January 1”, the week contains Ja toWeek(date, [, mode][, Timezone]) ``` -**Parameters** +**Arguments** - `date` – Date or DateTime. - `mode` – Optional parameter, Range of values is \[0,9\], default is 0. @@ -378,7 +396,7 @@ date_trunc(unit, value[, timezone]) Alias: `dateTrunc`. -**Parameters** +**Arguments** - `unit` — The type of interval to truncate the result. [String Literal](../syntax.md#syntax-string-literal). Possible values: @@ -431,13 +449,13 @@ Result: └─────────────────────┴────────────────────────────────────────────┘ ``` -**See also** +**See Also** - [toStartOfInterval](#tostartofintervaltime-or-data-interval-x-unit-time-zone) ## date\_add {#date_add} -Adds specified date/time interval to the provided date. +Adds the time interval or date interval to the provided date or date with time. **Syntax** @@ -447,25 +465,39 @@ date_add(unit, value, date) Aliases: `dateAdd`, `DATE_ADD`. -**Parameters** +**Arguments** - `unit` — The type of interval to add. [String](../../sql-reference/data-types/string.md). + Possible values: - Supported values: second, minute, hour, day, week, month, quarter, year. -- `value` - Value in specified unit - [Int](../../sql-reference/data-types/int-uint.md) -- `date` — [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). - + - `second` + - `minute` + - `hour` + - `day` + - `week` + - `month` + - `quarter` + - `year` + +- `value` — Value of interval to add. [Int](../../sql-reference/data-types/int-uint.md). +- `date` — The date or date with time to which `value` is added. [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). **Returned value** -Returns Date or DateTime with `value` expressed in `unit` added to `date`. +Date or date with time obtained by adding `value`, expressed in `unit`, to `date`. + +Type: [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). **Example** +Query: + ```sql -select date_add(YEAR, 3, toDate('2018-01-01')); +SELECT date_add(YEAR, 3, toDate('2018-01-01')); ``` +Result: + ```text ┌─plus(toDate('2018-01-01'), toIntervalYear(3))─┐ │ 2021-01-01 │ @@ -474,7 +506,7 @@ select date_add(YEAR, 3, toDate('2018-01-01')); ## date\_diff {#date_diff} -Returns the difference between two Date or DateTime values. +Returns the difference between two dates or dates with time values. **Syntax** @@ -482,25 +514,33 @@ Returns the difference between two Date or DateTime values. date_diff('unit', startdate, enddate, [timezone]) ``` -Aliases: `dateDiff`, `DATE_DIFF`. +Aliases: `dateDiff`, `DATE_DIFF`. -**Parameters** +**Arguments** -- `unit` — The type of interval for result [String](../../sql-reference/data-types/string.md). +- `unit` — The type of interval for result. [String](../../sql-reference/data-types/string.md). + Possible values: - Supported values: second, minute, hour, day, week, month, quarter, year. + - `second` + - `minute` + - `hour` + - `day` + - `week` + - `month` + - `quarter` + - `year` - `startdate` — The first time value to subtract (the subtrahend). [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). - `enddate` — The second time value to subtract from (the minuend). [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). -- `timezone` — Optional parameter. If specified, it is applied to both `startdate` and `enddate`. If not specified, timezones of `startdate` and `enddate` are used. If they are not the same, the result is unspecified. +- `timezone` — [Timezone name](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone) (optional). If specified, it is applied to both `startdate` and `enddate`. If not specified, timezones of `startdate` and `enddate` are used. If they are not the same, the result is unspecified. [String](../../sql-reference/data-types/string.md). **Returned value** Difference between `enddate` and `startdate` expressed in `unit`. -Type: `int`. +Type: [Int](../../sql-reference/data-types/int-uint.md). **Example** @@ -520,7 +560,7 @@ Result: ## date\_sub {#date_sub} -Subtracts a time/date interval from the provided date. +Subtracts the time interval or date interval from the provided date or date with time. **Syntax** @@ -528,19 +568,30 @@ Subtracts a time/date interval from the provided date. date_sub(unit, value, date) ``` -Aliases: `dateSub`, `DATE_SUB`. +Aliases: `dateSub`, `DATE_SUB`. -**Parameters** +**Arguments** - `unit` — The type of interval to subtract. [String](../../sql-reference/data-types/string.md). + Possible values: - Supported values: second, minute, hour, day, week, month, quarter, year. -- `value` - Value in specified unit - [Int](../../sql-reference/data-types/int-uint.md) -- `date` — [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md) to subtract value from. + - `second` + - `minute` + - `hour` + - `day` + - `week` + - `month` + - `quarter` + - `year` + +- `value` — Value of interval to subtract. [Int](../../sql-reference/data-types/int-uint.md). +- `date` — The date or date with time from which `value` is subtracted. [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). **Returned value** -Returns Date or DateTime with `value` expressed in `unit` subtracted from `date`. +Date or date with time obtained by subtracting `value`, expressed in `unit`, from `date`. + +Type: [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). **Example** @@ -570,24 +621,38 @@ timestamp_add(date, INTERVAL value unit) Aliases: `timeStampAdd`, `TIMESTAMP_ADD`. -**Parameters** +**Arguments** -- `date` — Date or Date with time - [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). -- `value` - Value in specified unit - [Int](../../sql-reference/data-types/int-uint.md) +- `date` — Date or date with time. [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). +- `value` — Value of interval to add. [Int](../../sql-reference/data-types/int-uint.md). - `unit` — The type of interval to add. [String](../../sql-reference/data-types/string.md). + Possible values: - Supported values: second, minute, hour, day, week, month, quarter, year. + - `second` + - `minute` + - `hour` + - `day` + - `week` + - `month` + - `quarter` + - `year` **Returned value** -Returns Date or DateTime with the specified `value` expressed in `unit` added to `date`. +Date or date with time with the specified `value` expressed in `unit` added to `date`. + +Type: [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). **Example** +Query: + ```sql select timestamp_add(toDate('2018-01-01'), INTERVAL 3 MONTH); ``` +Result: + ```text ┌─plus(toDate('2018-01-01'), toIntervalMonth(3))─┐ │ 2018-04-01 │ @@ -596,7 +661,7 @@ select timestamp_add(toDate('2018-01-01'), INTERVAL 3 MONTH); ## timestamp\_sub {#timestamp_sub} -Returns the difference between two dates in the specified unit. +Subtracts the time interval from the provided date or date with time. **Syntax** @@ -606,24 +671,39 @@ timestamp_sub(unit, value, date) Aliases: `timeStampSub`, `TIMESTAMP_SUB`. -**Parameters** +**Arguments** -- `unit` — The type of interval to add. [String](../../sql-reference/data-types/string.md). +- `unit` — The type of interval to subtract. [String](../../sql-reference/data-types/string.md). + Possible values: - Supported values: second, minute, hour, day, week, month, quarter, year. -- `value` - Value in specified unit - [Int](../../sql-reference/data-types/int-uint.md). -- `date`- [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). + - `second` + - `minute` + - `hour` + - `day` + - `week` + - `month` + - `quarter` + - `year` + +- `value` — Value of interval to subtract. [Int](../../sql-reference/data-types/int-uint.md). +- `date` — Date or date with time. [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). **Returned value** -Difference between `date` and the specified `value` expressed in `unit`. +Date or date with time obtained by subtracting `value`, expressed in `unit`, from `date`. + +Type: [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). **Example** +Query: + ```sql select timestamp_sub(MONTH, 5, toDateTime('2018-12-18 01:02:03')); ``` +Result: + ```text ┌─minus(toDateTime('2018-12-18 01:02:03'), toIntervalMonth(5))─┐ │ 2018-07-18 01:02:03 │ @@ -640,7 +720,7 @@ Returns the current date and time. now([timezone]) ``` -**Parameters** +**Arguments** - `timezone` — [Timezone name](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone) for the returned value (optional). [String](../../sql-reference/data-types/string.md). @@ -753,7 +833,7 @@ This is necessary for searching for pageviews in the corresponding session. ## formatDateTime {#formatdatetime} -Function formats a Time according given Format string. N.B.: Format is a constant expression, e.g. you can not have multiple formats for single result column. +Formats a Time according to the given Format string. Format is a constant expression, so you cannot have multiple formats for a single result column. **Syntax** @@ -812,31 +892,32 @@ Result: └────────────────────────────────────────────┘ ``` -[Original article](https://clickhouse.tech/docs/en/query_language/functions/date_time_functions/) - ## FROM\_UNIXTIME {#fromunixfime} -When there is only single argument of integer type, it act in the same way as `toDateTime` and return [DateTime](../../sql-reference/data-types/datetime.md). -type. +Function converts Unix timestamp to a calendar date and a time of a day. When there is only a single argument of [Integer](../../sql-reference/data-types/int-uint.md) type, it acts in the same way as [toDateTime](../../sql-reference/functions/type-conversion-functions.md#todatetime) and return [DateTime](../../sql-reference/data-types/datetime.md) type. -For example: +**Example:** + +Query: ```sql -SELECT FROM_UNIXTIME(423543535) +SELECT FROM_UNIXTIME(423543535); ``` +Result: + ```text ┌─FROM_UNIXTIME(423543535)─┐ │ 1983-06-04 10:58:55 │ └──────────────────────────┘ ``` -When there are two arguments, first is integer or DateTime, second is constant format string, it act in the same way as `formatDateTime` and return `String` type. +When there are two arguments: first is an [Integer](../../sql-reference/data-types/int-uint.md) or [DateTime](../../sql-reference/data-types/datetime.md), second is a constant format string — it acts in the same way as [formatDateTime](#formatdatetime) and return [String](../../sql-reference/data-types/string.md#string) type. For example: ```sql -SELECT FROM_UNIXTIME(1234334543, '%Y-%m-%d %R:%S') AS DateTime +SELECT FROM_UNIXTIME(1234334543, '%Y-%m-%d %R:%S') AS DateTime; ``` ```text @@ -855,7 +936,7 @@ Converts a [Proleptic Gregorian calendar](https://en.wikipedia.org/wiki/Prolepti toModifiedJulianDay(date) ``` -**Parameters** +**Arguments** - `date` — Date in text form. [String](../../sql-reference/data-types/string.md) or [FixedString](../../sql-reference/data-types/fixedstring.md). @@ -891,7 +972,7 @@ Similar to [toModifiedJulianDay()](#tomodifiedjulianday), but instead of raising toModifiedJulianDayOrNull(date) ``` -**Parameters** +**Arguments** - `date` — Date in text form. [String](../../sql-reference/data-types/string.md) or [FixedString](../../sql-reference/data-types/fixedstring.md). @@ -927,7 +1008,7 @@ Converts a [Modified Julian Day](https://en.wikipedia.org/wiki/Julian_day#Varian fromModifiedJulianDay(day) ``` -**Parameters** +**Arguments** - `day` — Modified Julian Day number. [Any integral types](../../sql-reference/data-types/int-uint.md). @@ -963,7 +1044,7 @@ Similar to [fromModifiedJulianDayOrNull()](#frommodifiedjuliandayornull), but in fromModifiedJulianDayOrNull(day) ``` -**Parameters** +**Arguments** - `day` — Modified Julian Day number. [Any integral types](../../sql-reference/data-types/int-uint.md). @@ -988,3 +1069,5 @@ Result: │ 2020-01-01 │ └────────────────────────────────────┘ ``` + +[Original article](https://clickhouse.tech/docs/en/query_language/functions/date_time_functions/) diff --git a/docs/en/sql-reference/functions/encoding-functions.md b/docs/en/sql-reference/functions/encoding-functions.md index bc3f5ca4345..c1013ebb0e1 100644 --- a/docs/en/sql-reference/functions/encoding-functions.md +++ b/docs/en/sql-reference/functions/encoding-functions.md @@ -15,7 +15,7 @@ Returns the string with the length as the number of passed arguments and each by char(number_1, [number_2, ..., number_n]); ``` -**Parameters** +**Arguments** - `number_1, number_2, ..., number_n` — Numerical arguments interpreted as integers. Types: [Int](../../sql-reference/data-types/int-uint.md), [Float](../../sql-reference/data-types/float.md). @@ -75,6 +75,8 @@ Result: Returns a string containing the argument’s hexadecimal representation. +Alias: `HEX`. + **Syntax** ``` sql @@ -107,7 +109,7 @@ For `String` and `FixedString`, all bytes are simply encoded as two hexadecimal Values of floating point and Decimal types are encoded as their representation in memory. As we support little endian architecture, they are encoded in little endian. Zero leading/trailing bytes are not omitted. -**Parameters** +**Arguments** - `arg` — A value to convert to hexadecimal. Types: [String](../../sql-reference/data-types/string.md), [UInt](../../sql-reference/data-types/int-uint.md), [Float](../../sql-reference/data-types/float.md), [Decimal](../../sql-reference/data-types/decimal.md), [Date](../../sql-reference/data-types/date.md) or [DateTime](../../sql-reference/data-types/datetime.md). diff --git a/docs/en/sql-reference/functions/encryption-functions.md b/docs/en/sql-reference/functions/encryption-functions.md index 9e360abfe26..df27685dcb3 100644 --- a/docs/en/sql-reference/functions/encryption-functions.md +++ b/docs/en/sql-reference/functions/encryption-functions.md @@ -31,7 +31,7 @@ This function encrypts data using these modes: encrypt('mode', 'plaintext', 'key' [, iv, aad]) ``` -**Parameters** +**Arguments** - `mode` — Encryption mode. [String](../../sql-reference/data-types/string.md#string). - `plaintext` — Text thats need to be encrypted. [String](../../sql-reference/data-types/string.md#string). @@ -55,7 +55,7 @@ CREATE TABLE encryption_test `comment` String, `secret` String ) -ENGINE = Memory +ENGINE = Memory; ``` Insert some data (please avoid storing the keys/ivs in the database as this undermines the whole concept of encryption), also storing 'hints' is unsafe too and used only for illustrative purposes: @@ -110,7 +110,7 @@ Result: Compatible with mysql encryption and resulting ciphertext can be decrypted with [AES_DECRYPT](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_aes-decrypt) function. -Will produce same ciphertext as `encrypt` on equal inputs. But when `key` or `iv` are longer than they should normally be, `aes_encrypt_mysql` will stick to what MySQL's `aes_encrypt` does: 'fold' `key` and ignore excess bits of `IV`. +Will produce the same ciphertext as `encrypt` on equal inputs. But when `key` or `iv` are longer than they should normally be, `aes_encrypt_mysql` will stick to what MySQL's `aes_encrypt` does: 'fold' `key` and ignore excess bits of `iv`. Supported encryption modes: @@ -127,18 +127,17 @@ Supported encryption modes: aes_encrypt_mysql('mode', 'plaintext', 'key' [, iv]) ``` -**Parameters** +**Arguments** - `mode` — Encryption mode. [String](../../sql-reference/data-types/string.md#string). - `plaintext` — Text that needs to be encrypted. [String](../../sql-reference/data-types/string.md#string). - `key` — Encryption key. If key is longer than required by mode, MySQL-specific key folding is performed. [String](../../sql-reference/data-types/string.md#string). -- `iv` — Initialization vector. Optinal, only first 16 bytes are taken into account [String](../../sql-reference/data-types/string.md#string). +- `iv` — Initialization vector. Optional, only first 16 bytes are taken into account [String](../../sql-reference/data-types/string.md#string). **Returned value** - Ciphertext binary string. [String](../../sql-reference/data-types/string.md#string). - **Examples** Given equal input `encrypt` and `aes_encrypt_mysql` produce the same ciphertext: @@ -157,7 +156,6 @@ Result: └───────────────────┘ ``` - But `encrypt` fails when `key` or `iv` is longer than expected: Query: @@ -238,7 +236,7 @@ This function decrypts ciphertext into a plaintext using these modes: decrypt('mode', 'ciphertext', 'key' [, iv, aad]) ``` -**Parameters** +**Arguments** - `mode` — Decryption mode. [String](../../sql-reference/data-types/string.md#string). - `ciphertext` — Encrypted text that needs to be decrypted. [String](../../sql-reference/data-types/string.md#string). @@ -252,7 +250,7 @@ decrypt('mode', 'ciphertext', 'key' [, iv, aad]) **Examples** -Re-using table from [encrypt](./encryption-functions.md#encrypt). +Re-using table from [encrypt](#encrypt). Query: @@ -284,6 +282,7 @@ SELECT comment, decrypt('aes-256-cfb128', secret, '12345678910121314151617181920 ``` Result: + ``` text ┌─comment─────────────────────────────┬─plaintext─┐ │ aes-256-cfb128 no IV │ Secret │ @@ -294,7 +293,7 @@ Result: └─────────────────────────────────────┴───────────┘ ``` -Notice how only portion of the data was properly decrypted, and the rest is gibberish since either `mode`, `key`, or `iv` were different upon encryption. +Notice how only a portion of the data was properly decrypted, and the rest is gibberish since either `mode`, `key`, or `iv` were different upon encryption. ## aes_decrypt_mysql {#aes_decrypt_mysql} @@ -317,7 +316,7 @@ Supported decryption modes: aes_decrypt_mysql('mode', 'ciphertext', 'key' [, iv]) ``` -**Parameters** +**Arguments** - `mode` — Decryption mode. [String](../../sql-reference/data-types/string.md#string). - `ciphertext` — Encrypted text that needs to be decrypted. [String](../../sql-reference/data-types/string.md#string). @@ -331,6 +330,7 @@ aes_decrypt_mysql('mode', 'ciphertext', 'key' [, iv]) **Examples** Let's decrypt data we've previously encrypted with MySQL: + ``` sql mysql> SET block_encryption_mode='aes-256-cfb128'; Query OK, 0 rows affected (0.00 sec) @@ -345,11 +345,13 @@ mysql> SELECT aes_encrypt('Secret', '123456789101213141516171819202122', 'iviviv ``` Query: + ``` sql SELECT aes_decrypt_mysql('aes-256-cfb128', unhex('24E9E4966469'), '123456789101213141516171819202122', 'iviviviviviviviv123456') AS plaintext ``` Result: + ``` text ┌─plaintext─┐ │ Secret │ diff --git a/docs/en/sql-reference/functions/ext-dict-functions.md b/docs/en/sql-reference/functions/ext-dict-functions.md index 7df6ef54f2a..834fcdf8282 100644 --- a/docs/en/sql-reference/functions/ext-dict-functions.md +++ b/docs/en/sql-reference/functions/ext-dict-functions.md @@ -19,7 +19,7 @@ dictGet('dict_name', 'attr_name', id_expr) dictGetOrDefault('dict_name', 'attr_name', id_expr, default_value_expr) ``` -**Parameters** +**Arguments** - `dict_name` — Name of the dictionary. [String literal](../../sql-reference/syntax.md#syntax-string-literal). - `attr_name` — Name of the column of the dictionary. [String literal](../../sql-reference/syntax.md#syntax-string-literal). @@ -108,7 +108,7 @@ Checks whether a key is present in a dictionary. dictHas('dict_name', id_expr) ``` -**Parameters** +**Arguments** - `dict_name` — Name of the dictionary. [String literal](../../sql-reference/syntax.md#syntax-string-literal). - `id_expr` — Key value. [Expression](../../sql-reference/syntax.md#syntax-expressions) returning a [UInt64](../../sql-reference/data-types/int-uint.md) or [Tuple](../../sql-reference/data-types/tuple.md)-type value depending on the dictionary configuration. @@ -130,7 +130,7 @@ Creates an array, containing all the parents of a key in the [hierarchical dicti dictGetHierarchy('dict_name', key) ``` -**Parameters** +**Arguments** - `dict_name` — Name of the dictionary. [String literal](../../sql-reference/syntax.md#syntax-string-literal). - `key` — Key value. [Expression](../../sql-reference/syntax.md#syntax-expressions) returning a [UInt64](../../sql-reference/data-types/int-uint.md)-type value. @@ -149,7 +149,7 @@ Checks the ancestor of a key through the whole hierarchical chain in the diction dictIsIn('dict_name', child_id_expr, ancestor_id_expr) ``` -**Parameters** +**Arguments** - `dict_name` — Name of the dictionary. [String literal](../../sql-reference/syntax.md#syntax-string-literal). - `child_id_expr` — Key to be checked. [Expression](../../sql-reference/syntax.md#syntax-expressions) returning a [UInt64](../../sql-reference/data-types/int-uint.md)-type value. @@ -185,7 +185,7 @@ dictGet[Type]('dict_name', 'attr_name', id_expr) dictGet[Type]OrDefault('dict_name', 'attr_name', id_expr, default_value_expr) ``` -**Parameters** +**Arguments** - `dict_name` — Name of the dictionary. [String literal](../../sql-reference/syntax.md#syntax-string-literal). - `attr_name` — Name of the column of the dictionary. [String literal](../../sql-reference/syntax.md#syntax-string-literal). diff --git a/docs/en/sql-reference/functions/functions-for-nulls.md b/docs/en/sql-reference/functions/functions-for-nulls.md index c32af7194fb..f57f0f7e27d 100644 --- a/docs/en/sql-reference/functions/functions-for-nulls.md +++ b/docs/en/sql-reference/functions/functions-for-nulls.md @@ -13,7 +13,9 @@ Checks whether the argument is [NULL](../../sql-reference/syntax.md#null-literal isNull(x) ``` -**Parameters** +Alias: `ISNULL`. + +**Arguments** - `x` — A value with a non-compound data type. @@ -53,7 +55,7 @@ Checks whether the argument is [NULL](../../sql-reference/syntax.md#null-literal isNotNull(x) ``` -**Parameters:** +**Arguments:** - `x` — A value with a non-compound data type. @@ -93,7 +95,7 @@ Checks from left to right whether `NULL` arguments were passed and returns the f coalesce(x,...) ``` -**Parameters:** +**Arguments:** - Any number of parameters of a non-compound type. All parameters must be compatible by data type. @@ -136,7 +138,7 @@ Returns an alternative value if the main argument is `NULL`. ifNull(x,alt) ``` -**Parameters:** +**Arguments:** - `x` — The value to check for `NULL`. - `alt` — The value that the function returns if `x` is `NULL`. @@ -176,7 +178,7 @@ Returns `NULL` if the arguments are equal. nullIf(x, y) ``` -**Parameters:** +**Arguments:** `x`, `y` — Values for comparison. They must be compatible types, or ClickHouse will generate an exception. @@ -215,7 +217,7 @@ Results in a value of type [Nullable](../../sql-reference/data-types/nullable.md assumeNotNull(x) ``` -**Parameters:** +**Arguments:** - `x` — The original value. @@ -277,7 +279,7 @@ Converts the argument type to `Nullable`. toNullable(x) ``` -**Parameters:** +**Arguments:** - `x` — The value of any non-compound type. diff --git a/docs/en/sql-reference/functions/geo/geohash.md b/docs/en/sql-reference/functions/geo/geohash.md index 6f288a7687d..c27eab0b421 100644 --- a/docs/en/sql-reference/functions/geo/geohash.md +++ b/docs/en/sql-reference/functions/geo/geohash.md @@ -72,7 +72,7 @@ Returns an array of [geohash](#geohash)-encoded strings of given precision that geohashesInBox(longitude_min, latitude_min, longitude_max, latitude_max, precision) ``` -**Parameters** +**Arguments** - `longitude_min` — Minimum longitude. Range: `[-180°, 180°]`. Type: [Float](../../../sql-reference/data-types/float.md). - `latitude_min` — Minimum latitude. Range: `[-90°, 90°]`. Type: [Float](../../../sql-reference/data-types/float.md). diff --git a/docs/en/sql-reference/functions/geo/h3.md b/docs/en/sql-reference/functions/geo/h3.md index 4ed651e4e9e..9dda947b3a7 100644 --- a/docs/en/sql-reference/functions/geo/h3.md +++ b/docs/en/sql-reference/functions/geo/h3.md @@ -162,7 +162,7 @@ Returns [H3](#h3index) point index `(lon, lat)` with specified resolution. geoToH3(lon, lat, resolution) ``` -**Parameters** +**Arguments** - `lon` — Longitude. Type: [Float64](../../../sql-reference/data-types/float.md). - `lat` — Latitude. Type: [Float64](../../../sql-reference/data-types/float.md). @@ -201,7 +201,7 @@ Result: h3kRing(h3index, k) ``` -**Parameters** +**Arguments** - `h3index` — Hexagon index number. Type: [UInt64](../../../sql-reference/data-types/int-uint.md). - `k` — Raduis. Type: [integer](../../../sql-reference/data-types/int-uint.md) @@ -315,7 +315,7 @@ Returns whether or not the provided [H3](#h3index) indexes are neighbors. h3IndexesAreNeighbors(index1, index2) ``` -**Parameters** +**Arguments** - `index1` — Hexagon index number. Type: [UInt64](../../../sql-reference/data-types/int-uint.md). - `index2` — Hexagon index number. Type: [UInt64](../../../sql-reference/data-types/int-uint.md). @@ -353,7 +353,7 @@ Returns an array of child indexes for the given [H3](#h3index) index. h3ToChildren(index, resolution) ``` -**Parameters** +**Arguments** - `index` — Hexagon index number. Type: [UInt64](../../../sql-reference/data-types/int-uint.md). - `resolution` — Index resolution. Range: `[0, 15]`. Type: [UInt8](../../../sql-reference/data-types/int-uint.md). @@ -390,7 +390,7 @@ Returns the parent (coarser) index containing the given [H3](#h3index) index. h3ToParent(index, resolution) ``` -**Parameters** +**Arguments** - `index` — Hexagon index number. Type: [UInt64](../../../sql-reference/data-types/int-uint.md). - `resolution` — Index resolution. Range: `[0, 15]`. Type: [UInt8](../../../sql-reference/data-types/int-uint.md). diff --git a/docs/en/sql-reference/functions/hash-functions.md b/docs/en/sql-reference/functions/hash-functions.md index 9394426b20b..465ad01527f 100644 --- a/docs/en/sql-reference/functions/hash-functions.md +++ b/docs/en/sql-reference/functions/hash-functions.md @@ -18,9 +18,9 @@ halfMD5(par1, ...) The function is relatively slow (5 million short strings per second per processor core). Consider using the [sipHash64](#hash_functions-siphash64) function instead. -**Parameters** +**Arguments** -The function takes a variable number of input parameters. Parameters can be any of the [supported data types](../../sql-reference/data-types/index.md). +The function takes a variable number of input parameters. Arguments can be any of the [supported data types](../../sql-reference/data-types/index.md). **Returned Value** @@ -61,9 +61,9 @@ Function [interprets](../../sql-reference/functions/type-conversion-functions.md 3. Then the function takes the hash value, calculated at the previous step, and the third element of the initial hash array, and calculates a hash for the array of them. 4. The previous step is repeated for all the remaining elements of the initial hash array. -**Parameters** +**Arguments** -The function takes a variable number of input parameters. Parameters can be any of the [supported data types](../../sql-reference/data-types/index.md). +The function takes a variable number of input parameters. Arguments can be any of the [supported data types](../../sql-reference/data-types/index.md). **Returned Value** @@ -97,9 +97,9 @@ cityHash64(par1,...) This is a fast non-cryptographic hash function. It uses the CityHash algorithm for string parameters and implementation-specific fast non-cryptographic hash function for parameters with other data types. The function uses the CityHash combinator to get the final results. -**Parameters** +**Arguments** -The function takes a variable number of input parameters. Parameters can be any of the [supported data types](../../sql-reference/data-types/index.md). +The function takes a variable number of input parameters. Arguments can be any of the [supported data types](../../sql-reference/data-types/index.md). **Returned Value** @@ -166,9 +166,9 @@ farmHash64(par1, ...) These functions use the `Fingerprint64` and `Hash64` methods respectively from all [available methods](https://github.com/google/farmhash/blob/master/src/farmhash.h). -**Parameters** +**Arguments** -The function takes a variable number of input parameters. Parameters can be any of the [supported data types](../../sql-reference/data-types/index.md). +The function takes a variable number of input parameters. Arguments can be any of the [supported data types](../../sql-reference/data-types/index.md). **Returned Value** @@ -226,7 +226,7 @@ Calculates [JavaHash](http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/478a4add97 javaHashUTF16LE(stringUtf16le) ``` -**Parameters** +**Arguments** - `stringUtf16le` — a string in UTF-16LE encoding. @@ -292,9 +292,9 @@ Produces a 64-bit [MetroHash](http://www.jandrewrogers.com/2015/05/27/metrohash/ metroHash64(par1, ...) ``` -**Parameters** +**Arguments** -The function takes a variable number of input parameters. Parameters can be any of the [supported data types](../../sql-reference/data-types/index.md). +The function takes a variable number of input parameters. Arguments can be any of the [supported data types](../../sql-reference/data-types/index.md). **Returned Value** @@ -327,9 +327,9 @@ murmurHash2_32(par1, ...) murmurHash2_64(par1, ...) ``` -**Parameters** +**Arguments** -Both functions take a variable number of input parameters. Parameters can be any of the [supported data types](../../sql-reference/data-types/index.md). +Both functions take a variable number of input parameters. Arguments can be any of the [supported data types](../../sql-reference/data-types/index.md). **Returned Value** @@ -358,7 +358,7 @@ Calculates a 64-bit [MurmurHash2](https://github.com/aappleby/smhasher) hash val gccMurmurHash(par1, ...); ``` -**Parameters** +**Arguments** - `par1, ...` — A variable number of parameters that can be any of the [supported data types](../../sql-reference/data-types/index.md#data_types). @@ -395,9 +395,9 @@ murmurHash3_32(par1, ...) murmurHash3_64(par1, ...) ``` -**Parameters** +**Arguments** -Both functions take a variable number of input parameters. Parameters can be any of the [supported data types](../../sql-reference/data-types/index.md). +Both functions take a variable number of input parameters. Arguments can be any of the [supported data types](../../sql-reference/data-types/index.md). **Returned Value** @@ -424,7 +424,7 @@ Produces a 128-bit [MurmurHash3](https://github.com/aappleby/smhasher) hash valu murmurHash3_128( expr ) ``` -**Parameters** +**Arguments** - `expr` — [Expressions](../../sql-reference/syntax.md#syntax-expressions) returning a [String](../../sql-reference/data-types/string.md)-type value. diff --git a/docs/en/sql-reference/functions/introspection.md b/docs/en/sql-reference/functions/introspection.md index bfa1998d68a..964265a461b 100644 --- a/docs/en/sql-reference/functions/introspection.md +++ b/docs/en/sql-reference/functions/introspection.md @@ -32,7 +32,7 @@ If you use official ClickHouse packages, you need to install the `clickhouse-com addressToLine(address_of_binary_instruction) ``` -**Parameters** +**Arguments** - `address_of_binary_instruction` ([UInt64](../../sql-reference/data-types/int-uint.md)) — Address of instruction in a running process. @@ -123,7 +123,7 @@ Converts virtual memory address inside ClickHouse server process to the symbol f addressToSymbol(address_of_binary_instruction) ``` -**Parameters** +**Arguments** - `address_of_binary_instruction` ([UInt64](../../sql-reference/data-types/int-uint.md)) — Address of instruction in a running process. @@ -220,7 +220,7 @@ Converts a symbol that you can get using the [addressToSymbol](#addresstosymbol) demangle(symbol) ``` -**Parameters** +**Arguments** - `symbol` ([String](../../sql-reference/data-types/string.md)) — Symbol from an object file. @@ -345,7 +345,7 @@ Emits trace log message to server log for each [Block](https://clickhouse.tech/d logTrace('message') ``` -**Parameters** +**Arguments** - `message` — Message that is emitted to server log. [String](../../sql-reference/data-types/string.md#string). diff --git a/docs/en/sql-reference/functions/ip-address-functions.md b/docs/en/sql-reference/functions/ip-address-functions.md index 1361eb65a56..64457627cce 100644 --- a/docs/en/sql-reference/functions/ip-address-functions.md +++ b/docs/en/sql-reference/functions/ip-address-functions.md @@ -9,10 +9,14 @@ toc_title: IP Addresses Takes a UInt32 number. Interprets it as an IPv4 address in big endian. Returns a string containing the corresponding IPv4 address in the format A.B.C.d (dot-separated numbers in decimal form). +Alias: `INET_NTOA`. + ## IPv4StringToNum(s) {#ipv4stringtonums} The reverse function of IPv4NumToString. If the IPv4 address has an invalid format, it returns 0. +Alias: `INET_ATON`. + ## IPv4NumToStringClassC(num) {#ipv4numtostringclasscnum} Similar to IPv4NumToString, but using xxx instead of the last octet. @@ -49,7 +53,11 @@ Since using ‘xxx’ is highly unusual, this may be changed in the future. We r ### IPv6NumToString(x) {#ipv6numtostringx} Accepts a FixedString(16) value containing the IPv6 address in binary format. Returns a string containing this address in text format. -IPv6-mapped IPv4 addresses are output in the format ::ffff:111.222.33.44. Examples: +IPv6-mapped IPv4 addresses are output in the format ::ffff:111.222.33.44. + +Alias: `INET6_NTOA`. + +Examples: ``` sql SELECT IPv6NumToString(toFixedString(unhex('2A0206B8000000000000000000000011'), 16)) AS addr @@ -113,22 +121,53 @@ LIMIT 10 └────────────────────────────┴────────┘ ``` -## IPv6StringToNum(s) {#ipv6stringtonums} +## IPv6StringToNum {#ipv6stringtonums} -The reverse function of IPv6NumToString. If the IPv6 address has an invalid format, it returns a string of null bytes. -If the IP address is a valid IPv4 address then the IPv6 equivalent of the IPv4 address is returned. +The reverse function of [IPv6NumToString](#ipv6numtostringx). If the IPv6 address has an invalid format, it returns a string of null bytes. + +If the input string contains a valid IPv4 address, returns its IPv6 equivalent. HEX can be uppercase or lowercase. +Alias: `INET6_ATON`. + +**Syntax** + ``` sql -SELECT cutIPv6(IPv6StringToNum('127.0.0.1'), 0, 0); +IPv6StringToNum(string) ``` -``` text -┌─cutIPv6(IPv6StringToNum('127.0.0.1'), 0, 0)─┐ -│ ::ffff:127.0.0.1 │ -└─────────────────────────────────────────────┘ +**Argument** + +- `string` — IP address. [String](../../sql-reference/data-types/string.md). + +**Returned value** + +- IPv6 address in binary format. + +Type: [FixedString(16)](../../sql-reference/data-types/fixedstring.md). + +**Example** + +Query: + +``` sql +SELECT addr, cutIPv6(IPv6StringToNum(addr), 0, 0) FROM (SELECT ['notaddress', '127.0.0.1', '1111::ffff'] AS addr) ARRAY JOIN addr; ``` +Result: + +``` text +┌─addr───────┬─cutIPv6(IPv6StringToNum(addr), 0, 0)─┐ +│ notaddress │ :: │ +│ 127.0.0.1 │ ::ffff:127.0.0.1 │ +│ 1111::ffff │ 1111::ffff │ +└────────────┴──────────────────────────────────────┘ +``` + +**See also** + +- [cutIPv6](#cutipv6x-bytestocutforipv6-bytestocutforipv4). + ## IPv4ToIPv6(x) {#ipv4toipv6x} Takes a `UInt32` number. Interprets it as an IPv4 address in [big endian](https://en.wikipedia.org/wiki/Endianness). Returns a `FixedString(16)` value containing the IPv6 address in binary format. Examples: @@ -222,75 +261,137 @@ SELECT └───────────────────────────────────┴──────────────────────────┘ ``` -## toIPv6(string) {#toipv6string} +## toIPv6 {#toipv6string} -An alias to `IPv6StringToNum()` that takes a string form of IPv6 address and returns value of [IPv6](../../sql-reference/data-types/domains/ipv6.md) type, which is binary equal to value returned by `IPv6StringToNum()`. -If the IP address is a valid IPv4 address then the IPv6 equivalent of the IPv4 address is returned. +Converts a string form of IPv6 address to [IPv6](../../sql-reference/data-types/domains/ipv6.md) type. If the IPv6 address has an invalid format, returns an empty value. +Similar to [IPv6StringToNum](#ipv6stringtonums) function, which converts IPv6 address to binary format. -``` sql -WITH - '2001:438:ffff::407d:1bc1' as IPv6_string -SELECT - toTypeName(IPv6StringToNum(IPv6_string)), - toTypeName(toIPv6(IPv6_string)) +If the input string contains a valid IPv4 address, then the IPv6 equivalent of the IPv4 address is returned. + +**Syntax** + +```sql +toIPv6(string) ``` -``` text -┌─toTypeName(IPv6StringToNum(IPv6_string))─┬─toTypeName(toIPv6(IPv6_string))─┐ -│ FixedString(16) │ IPv6 │ -└──────────────────────────────────────────┴─────────────────────────────────┘ -``` +**Argument** + +- `string` — IP address. [String](../../sql-reference/data-types/string.md) + +**Returned value** + +- IP address. + +Type: [IPv6](../../sql-reference/data-types/domains/ipv6.md). + +**Examples** + +Query: ``` sql -WITH - '2001:438:ffff::407d:1bc1' as IPv6_string +WITH '2001:438:ffff::407d:1bc1' AS IPv6_string SELECT hex(IPv6StringToNum(IPv6_string)), - hex(toIPv6(IPv6_string)) + hex(toIPv6(IPv6_string)); ``` +Result: + ``` text ┌─hex(IPv6StringToNum(IPv6_string))─┬─hex(toIPv6(IPv6_string))─────────┐ │ 20010438FFFF000000000000407D1BC1 │ 20010438FFFF000000000000407D1BC1 │ └───────────────────────────────────┴──────────────────────────────────┘ ``` +Query: + ``` sql -SELECT toIPv6('127.0.0.1') +SELECT toIPv6('127.0.0.1'); ``` +Result: + ``` text ┌─toIPv6('127.0.0.1')─┐ │ ::ffff:127.0.0.1 │ └─────────────────────┘ ``` -## isIPv4String +## isIPv4String {#isipv4string} -Determines if the input string is an IPv4 address or not. Returns `1` if true `0` otherwise. +Determines whether the input string is an IPv4 address or not. If `string` is IPv6 address returns `0`. -``` sql -SELECT isIPv4String('127.0.0.1') +**Syntax** + +```sql +isIPv4String(string) ``` +**Arguments** + +- `string` — IP address. [String](../../sql-reference/data-types/string.md). + +**Returned value** + +- `1` if `string` is IPv4 address, `0` otherwise. + +Type: [UInt8](../../sql-reference/data-types/int-uint.md). + +**Examples** + +Query: + +```sql +SELECT addr, isIPv4String(addr) FROM ( SELECT ['0.0.0.0', '127.0.0.1', '::ffff:127.0.0.1'] AS addr ) ARRAY JOIN addr +``` + +Result: + ``` text -┌─isIPv4String('127.0.0.1')─┐ -│ 1 │ -└───────────────────────────┘ +┌─addr─────────────┬─isIPv4String(addr)─┐ +│ 0.0.0.0 │ 1 │ +│ 127.0.0.1 │ 1 │ +│ ::ffff:127.0.0.1 │ 0 │ +└──────────────────┴────────────────────┘ ``` -## isIPv6String +## isIPv6String {#isipv6string} -Determines if the input string is an IPv6 address or not. Returns `1` if true `0` otherwise. +Determines whether the input string is an IPv6 address or not. If `string` is IPv4 address returns `0`. + +**Syntax** + +```sql +isIPv6String(string) +``` + +**Arguments** + +- `string` — IP address. [String](../../sql-reference/data-types/string.md). + +**Returned value** + +- `1` if `string` is IPv6 address, `0` otherwise. + +Type: [UInt8](../../sql-reference/data-types/int-uint.md). + +**Examples** + +Query: ``` sql -SELECT isIPv6String('2001:438:ffff::407d:1bc1') +SELECT addr, isIPv6String(addr) FROM ( SELECT ['::', '1111::ffff', '::ffff:127.0.0.1', '127.0.0.1'] AS addr ) ARRAY JOIN addr ``` +Result: + ``` text -┌─isIPv6String('2001:438:ffff::407d:1bc1')─┐ -│ 1 │ -└──────────────────────────────────────────┘ +┌─addr─────────────┬─isIPv6String(addr)─┐ +│ :: │ 1 │ +│ 1111::ffff │ 1 │ +│ ::ffff:127.0.0.1 │ 1 │ +│ 127.0.0.1 │ 0 │ +└──────────────────┴────────────────────┘ ``` [Original article](https://clickhouse.tech/docs/en/query_language/functions/ip_address_functions/) diff --git a/docs/en/sql-reference/functions/json-functions.md b/docs/en/sql-reference/functions/json-functions.md index 05e755eaddc..edee048eb77 100644 --- a/docs/en/sql-reference/functions/json-functions.md +++ b/docs/en/sql-reference/functions/json-functions.md @@ -236,7 +236,7 @@ Extracts raw data from a JSON object. JSONExtractKeysAndValuesRaw(json[, p, a, t, h]) ``` -**Parameters** +**Arguments** - `json` — [String](../../sql-reference/data-types/string.md) with valid JSON. - `p, a, t, h` — Comma-separated indices or keys that specify the path to the inner field in a nested JSON object. Each argument can be either a [string](../../sql-reference/data-types/string.md) to get the field by the key or an [integer](../../sql-reference/data-types/int-uint.md) to get the N-th field (indexed from 1, negative integers count from the end). If not set, the whole JSON is parsed as the top-level object. Optional parameter. diff --git a/docs/en/sql-reference/functions/machine-learning-functions.md b/docs/en/sql-reference/functions/machine-learning-functions.md index 8627fc26bad..f103a4ea421 100644 --- a/docs/en/sql-reference/functions/machine-learning-functions.md +++ b/docs/en/sql-reference/functions/machine-learning-functions.md @@ -27,7 +27,7 @@ Compares test groups (variants) and calculates for each group the probability to bayesAB(distribution_name, higher_is_better, variant_names, x, y) ``` -**Parameters** +**Arguments** - `distribution_name` — Name of the probability distribution. [String](../../sql-reference/data-types/string.md). Possible values: diff --git a/docs/en/sql-reference/functions/math-functions.md b/docs/en/sql-reference/functions/math-functions.md index 8dc287593c7..bfe973e3d96 100644 --- a/docs/en/sql-reference/functions/math-functions.md +++ b/docs/en/sql-reference/functions/math-functions.md @@ -121,7 +121,7 @@ Accepts a numeric argument and returns a UInt64 number close to 10 to the power cosh(x) ``` -**Parameters** +**Arguments** - `x` — The angle, in radians. Values from the interval: `-∞ < x < +∞`. [Float64](../../sql-reference/data-types/float.md#float32-float64). @@ -157,7 +157,7 @@ Result: acosh(x) ``` -**Parameters** +**Arguments** - `x` — Hyperbolic cosine of angle. Values from the interval: `1 <= x < +∞`. [Float64](../../sql-reference/data-types/float.md#float32-float64). @@ -197,7 +197,7 @@ Result: sinh(x) ``` -**Parameters** +**Arguments** - `x` — The angle, in radians. Values from the interval: `-∞ < x < +∞`. [Float64](../../sql-reference/data-types/float.md#float32-float64). @@ -233,7 +233,7 @@ Result: asinh(x) ``` -**Parameters** +**Arguments** - `x` — Hyperbolic sine of angle. Values from the interval: `-∞ < x < +∞`. [Float64](../../sql-reference/data-types/float.md#float32-float64). @@ -273,7 +273,7 @@ Result: atanh(x) ``` -**Parameters** +**Arguments** - `x` — Hyperbolic tangent of angle. Values from the interval: `–1 < x < 1`. [Float64](../../sql-reference/data-types/float.md#float32-float64). @@ -309,7 +309,7 @@ The [function](https://en.wikipedia.org/wiki/Atan2) calculates the angle in the atan2(y, x) ``` -**Parameters** +**Arguments** - `y` — y-coordinate of the point through which the ray passes. [Float64](../../sql-reference/data-types/float.md#float32-float64). - `x` — x-coordinate of the point through which the ray passes. [Float64](../../sql-reference/data-types/float.md#float32-float64). @@ -346,7 +346,7 @@ Calculates the length of the hypotenuse of a right-angle triangle. The [function hypot(x, y) ``` -**Parameters** +**Arguments** - `x` — The first cathetus of a right-angle triangle. [Float64](../../sql-reference/data-types/float.md#float32-float64). - `y` — The second cathetus of a right-angle triangle. [Float64](../../sql-reference/data-types/float.md#float32-float64). @@ -383,7 +383,7 @@ Calculates `log(1+x)`. The [function](https://en.wikipedia.org/wiki/Natural_loga log1p(x) ``` -**Parameters** +**Arguments** - `x` — Values from the interval: `-1 < x < +∞`. [Float64](../../sql-reference/data-types/float.md#float32-float64). @@ -415,7 +415,7 @@ Result: ## sign(x) {#signx} -The `sign` function can extract the sign of a real number. +Returns the sign of a real number. **Syntax** @@ -423,7 +423,7 @@ The `sign` function can extract the sign of a real number. sign(x) ``` -**Parameters** +**Arguments** - `x` — Values from `-∞` to `+∞`. Support all numeric types in ClickHouse. @@ -433,9 +433,9 @@ sign(x) - 0 for `x = 0` - 1 for `x > 0` -**Example** +**Examples** -Query: +Sign for the zero value: ``` sql SELECT sign(0); @@ -449,7 +449,7 @@ Result: └─────────┘ ``` -Query: +Sign for the positive value: ``` sql SELECT sign(1); @@ -463,7 +463,7 @@ Result: └─────────┘ ``` -Query: +Sign for the negative value: ``` sql SELECT sign(-1); diff --git a/docs/en/sql-reference/functions/other-functions.md b/docs/en/sql-reference/functions/other-functions.md index 7308ed60b5c..2c7f8da881e 100644 --- a/docs/en/sql-reference/functions/other-functions.md +++ b/docs/en/sql-reference/functions/other-functions.md @@ -19,7 +19,7 @@ Gets a named value from the [macros](../../operations/server-configuration-param getMacro(name); ``` -**Parameters** +**Arguments** - `name` — Name to retrieve from the `macros` section. [String](../../sql-reference/data-types/string.md#string). @@ -108,7 +108,7 @@ Extracts the trailing part of a string after the last slash or backslash. This f basename( expr ) ``` -**Parameters** +**Arguments** - `expr` — Expression resulting in a [String](../../sql-reference/data-types/string.md) type value. All the backslashes must be escaped in the resulting value. @@ -192,7 +192,7 @@ Returns estimation of uncompressed byte size of its arguments in memory. byteSize(argument [, ...]) ``` -**Parameters** +**Arguments** - `argument` — Value. @@ -349,7 +349,7 @@ The function is intended for development, debugging and demonstration. isConstant(x) ``` -**Parameters** +**Arguments** - `x` — Expression to check. @@ -420,7 +420,7 @@ Checks whether floating point value is finite. ifNotFinite(x,y) -**Parameters** +**Arguments** - `x` — Value to be checked for infinity. Type: [Float\*](../../sql-reference/data-types/float.md). - `y` — Fallback value. Type: [Float\*](../../sql-reference/data-types/float.md). @@ -460,7 +460,7 @@ Allows building a unicode-art diagram. `bar(x, min, max, width)` draws a band with a width proportional to `(x - min)` and equal to `width` characters when `x = max`. -Parameters: +**Arguments** - `x` — Size to display. - `min, max` — Integer constants. The value must fit in `Int64`. @@ -645,7 +645,7 @@ Accepts the time delta in seconds. Returns a time delta with (year, month, day, formatReadableTimeDelta(column[, maximum_unit]) ``` -**Parameters** +**Arguments** - `column` — A column with numeric time delta. - `maximum_unit` — Optional. Maximum unit to show. Acceptable values seconds, minutes, hours, days, months, years. @@ -728,9 +728,9 @@ The result of the function depends on the affected data blocks and the order of It can reach the neighbor rows only inside the currently processed data block. The rows order used during the calculation of `neighbor` can differ from the order of rows returned to the user. -To prevent that you can make a subquery with ORDER BY and call the function from outside the subquery. +To prevent that you can make a subquery with [ORDER BY](../../sql-reference/statements/select/order-by.md) and call the function from outside the subquery. -**Parameters** +**Arguments** - `column` — A column name or scalar expression. - `offset` — The number of rows forwards or backwards from the current row of `column`. [Int64](../../sql-reference/data-types/int-uint.md). @@ -834,12 +834,12 @@ Calculates the difference between successive row values ​​in the data block. Returns 0 for the first row and the difference from the previous row for each subsequent row. !!! warning "Warning" - It can reach the previos row only inside the currently processed data block. + It can reach the previous row only inside the currently processed data block. The result of the function depends on the affected data blocks and the order of data in the block. The rows order used during the calculation of `runningDifference` can differ from the order of rows returned to the user. -To prevent that you can make a subquery with ORDER BY and call the function from outside the subquery. +To prevent that you can make a subquery with [ORDER BY](../../sql-reference/statements/select/order-by.md) and call the function from outside the subquery. Example: @@ -909,6 +909,66 @@ WHERE diff != 1 Same as for [runningDifference](../../sql-reference/functions/other-functions.md#other_functions-runningdifference), the difference is the value of the first row, returned the value of the first row, and each subsequent row returns the difference from the previous row. +## runningConcurrency {#runningconcurrency} + +Given a series of beginning time and ending time of events, this function calculates concurrency of the events at each of the data point, that is, the beginning time. + +!!! warning "Warning" + Events spanning multiple data blocks will not be processed correctly. The function resets its state for each new data block. + +The result of the function depends on the order of data in the block. It assumes the beginning time is sorted in ascending order. + +**Syntax** + +``` sql +runningConcurrency(begin, end) +``` + +**Arguments** + +- `begin` — A column for the beginning time of events (inclusive). [Date](../../sql-reference/data-types/date.md), [DateTime](../../sql-reference/data-types/datetime.md), or [DateTime64](../../sql-reference/data-types/datetime64.md). +- `end` — A column for the ending time of events (exclusive). [Date](../../sql-reference/data-types/date.md), [DateTime](../../sql-reference/data-types/datetime.md), or [DateTime64](../../sql-reference/data-types/datetime64.md). + +Note that two columns `begin` and `end` must have the same type. + +**Returned values** + +- The concurrency of events at the data point. + +Type: [UInt32](../../sql-reference/data-types/int-uint.md) + +**Example** + +Input table: + +``` text +┌───────────────begin─┬─────────────────end─┐ +│ 2020-12-01 00:00:00 │ 2020-12-01 00:59:59 │ +│ 2020-12-01 00:30:00 │ 2020-12-01 00:59:59 │ +│ 2020-12-01 00:40:00 │ 2020-12-01 01:30:30 │ +│ 2020-12-01 01:10:00 │ 2020-12-01 01:30:30 │ +│ 2020-12-01 01:50:00 │ 2020-12-01 01:59:59 │ +└─────────────────────┴─────────────────────┘ +``` + +Query: + +``` sql +SELECT runningConcurrency(begin, end) FROM example +``` + +Result: + +``` text +┌─runningConcurrency(begin, end)─┐ +│ 1 │ +│ 2 │ +│ 3 │ +│ 2 │ +│ 1 │ +└────────────────────────────────┘ +``` + ## MACNumToString(num) {#macnumtostringnum} Accepts a UInt64 number. Interprets it as a MAC address in big endian. Returns a string containing the corresponding MAC address in the format AA:BB:CC:DD:EE:FF (colon-separated numbers in hexadecimal form). @@ -929,7 +989,7 @@ Returns the number of fields in [Enum](../../sql-reference/data-types/enum.md). getSizeOfEnumType(value) ``` -**Parameters:** +**Arguments:** - `value` — Value of type `Enum`. @@ -958,7 +1018,7 @@ Returns size on disk (without taking into account compression). blockSerializedSize(value[, value[, ...]]) ``` -**Parameters** +**Arguments** - `value` — Any value. @@ -990,7 +1050,7 @@ Returns the name of the class that represents the data type of the column in RAM toColumnTypeName(value) ``` -**Parameters:** +**Arguments:** - `value` — Any type of value. @@ -1030,7 +1090,7 @@ Outputs a detailed description of data structures in RAM dumpColumnStructure(value) ``` -**Parameters:** +**Arguments:** - `value` — Any type of value. @@ -1060,7 +1120,7 @@ Does not include default values for custom columns set by the user. defaultValueOfArgumentType(expression) ``` -**Parameters:** +**Arguments:** - `expression` — Arbitrary type of value or an expression that results in a value of an arbitrary type. @@ -1102,7 +1162,7 @@ Does not include default values for custom columns set by the user. defaultValueOfTypeName(type) ``` -**Parameters:** +**Arguments:** - `type` — A string representing a type name. @@ -1144,7 +1204,7 @@ Used for internal implementation of [arrayJoin](../../sql-reference/functions/ar SELECT replicate(x, arr); ``` -**Parameters:** +**Arguments:** - `arr` — Original array. ClickHouse creates a new array of the same length as the original and fills it with the value `x`. - `x` — The value that the resulting array will be filled with. @@ -1277,7 +1337,7 @@ Takes state of aggregate function. Returns result of aggregation (or finalized s finalizeAggregation(state) ``` -**Parameters** +**Arguments** - `state` — State of aggregation. [AggregateFunction](../../sql-reference/data-types/aggregatefunction.md#data-type-aggregatefunction). @@ -1381,7 +1441,7 @@ Accumulates states of an aggregate function for each row of a data block. runningAccumulate(agg_state[, grouping]); ``` -**Parameters** +**Arguments** - `agg_state` — State of the aggregate function. [AggregateFunction](../../sql-reference/data-types/aggregatefunction.md#data-type-aggregatefunction). - `grouping` — Grouping key. Optional. The state of the function is reset if the `grouping` value is changed. It can be any of the [supported data types](../../sql-reference/data-types/index.md) for which the equality operator is defined. @@ -1487,7 +1547,7 @@ Only supports tables created with the `ENGINE = Join(ANY, LEFT, )` st joinGet(join_storage_table_name, `value_column`, join_keys) ``` -**Parameters** +**Arguments** - `join_storage_table_name` — an [identifier](../../sql-reference/syntax.md#syntax-identifiers) indicates where search is performed. The identifier is searched in the default database (see parameter `default_database` in the config file). To override the default database, use the `USE db_name` or specify the database and the table through the separator `db_name.db_table`, see the example. - `value_column` — name of the column of the table that contains required data. @@ -1591,7 +1651,7 @@ Generates a string with a random set of [ASCII](https://en.wikipedia.org/wiki/AS randomPrintableASCII(length) ``` -**Parameters** +**Arguments** - `length` — Resulting string length. Positive integer. @@ -1627,7 +1687,7 @@ Generates a binary string of the specified length filled with random bytes (incl randomString(length) ``` -**Parameters** +**Arguments** - `length` — String length. Positive integer. @@ -1675,7 +1735,7 @@ Generates a binary string of the specified length filled with random bytes (incl randomFixedString(length); ``` -**Parameters** +**Arguments** - `length` — String length in bytes. [UInt64](../../sql-reference/data-types/int-uint.md). @@ -1713,7 +1773,7 @@ Generates a random string of a specified length. Result string contains valid UT randomStringUTF8(length); ``` -**Parameters** +**Arguments** - `length` — Required length of the resulting string in code points. [UInt64](../../sql-reference/data-types/int-uint.md). @@ -1785,7 +1845,7 @@ Checks whether the [Decimal](../../sql-reference/data-types/decimal.md) value is isDecimalOverflow(d, [p]) ``` -**Parameters** +**Arguments** - `d` — value. [Decimal](../../sql-reference/data-types/decimal.md). - `p` — precision. Optional. If omitted, the initial precision of the first argument is used. Using of this paratemer could be helpful for data extraction to another DBMS or file. [UInt8](../../sql-reference/data-types/int-uint.md#uint-ranges). @@ -1822,7 +1882,7 @@ Returns number of decimal digits you need to represent the value. countDigits(x) ``` -**Parameters** +**Arguments** - `x` — [Int](../../sql-reference/data-types/int-uint.md) or [Decimal](../../sql-reference/data-types/decimal.md) value. @@ -1881,7 +1941,7 @@ Returns [native interface](../../interfaces/tcp.md) TCP port number listened by tcpPort() ``` -**Parameters** +**Arguments** - None. diff --git a/docs/en/sql-reference/functions/random-functions.md b/docs/en/sql-reference/functions/random-functions.md index 68998928398..2b9846344e4 100644 --- a/docs/en/sql-reference/functions/random-functions.md +++ b/docs/en/sql-reference/functions/random-functions.md @@ -32,7 +32,7 @@ Produces a constant column with a random value. randConstant([x]) ``` -**Parameters** +**Arguments** - `x` — [Expression](../../sql-reference/syntax.md#syntax-expressions) resulting in any of the [supported data types](../../sql-reference/data-types/index.md#data_types). The resulting value is discarded, but the expression itself if used for bypassing [common subexpression elimination](../../sql-reference/functions/index.md#common-subexpression-elimination) if the function is called multiple times in one query. Optional parameter. @@ -81,7 +81,7 @@ fuzzBits([s], [prob]) Inverts bits of `s`, each with probability `prob`. -**Parameters** +**Arguments** - `s` - `String` or `FixedString` - `prob` - constant `Float32/64` diff --git a/docs/en/sql-reference/functions/rounding-functions.md b/docs/en/sql-reference/functions/rounding-functions.md index 922cf7374d7..83db1975366 100644 --- a/docs/en/sql-reference/functions/rounding-functions.md +++ b/docs/en/sql-reference/functions/rounding-functions.md @@ -35,7 +35,7 @@ The function returns the nearest number of the specified order. In case when giv round(expression [, decimal_places]) ``` -**Parameters:** +**Arguments:** - `expression` — A number to be rounded. Can be any [expression](../../sql-reference/syntax.md#syntax-expressions) returning the numeric [data type](../../sql-reference/data-types/index.md#data_types). - `decimal-places` — An integer value. @@ -114,7 +114,7 @@ For example, sum numbers 1.5, 2.5, 3.5, 4.5 with different rounding: roundBankers(expression [, decimal_places]) ``` -**Parameters** +**Arguments** - `expression` — A number to be rounded. Can be any [expression](../../sql-reference/syntax.md#syntax-expressions) returning the numeric [data type](../../sql-reference/data-types/index.md#data_types). - `decimal-places` — Decimal places. An integer number. diff --git a/docs/en/sql-reference/functions/splitting-merging-functions.md b/docs/en/sql-reference/functions/splitting-merging-functions.md index 25f41211b47..c70ee20f076 100644 --- a/docs/en/sql-reference/functions/splitting-merging-functions.md +++ b/docs/en/sql-reference/functions/splitting-merging-functions.md @@ -16,7 +16,7 @@ Returns an array of selected substrings. Empty substrings may be selected if the splitByChar(, ) ``` -**Parameters** +**Arguments** - `separator` — The separator which should contain exactly one character. [String](../../sql-reference/data-types/string.md). - `s` — The string to split. [String](../../sql-reference/data-types/string.md). @@ -53,7 +53,7 @@ Splits a string into substrings separated by a string. It uses a constant string splitByString(, ) ``` -**Parameters** +**Arguments** - `separator` — The separator. [String](../../sql-reference/data-types/string.md). - `s` — The string to split. [String](../../sql-reference/data-types/string.md). @@ -121,7 +121,7 @@ Extracts all groups from non-overlapping substrings matched by a regular express extractAllGroups(text, regexp) ``` -**Parameters** +**Arguments** - `text` — [String](../data-types/string.md) or [FixedString](../data-types/fixedstring.md). - `regexp` — Regular expression. Constant. [String](../data-types/string.md) or [FixedString](../data-types/fixedstring.md). diff --git a/docs/en/sql-reference/functions/string-functions.md b/docs/en/sql-reference/functions/string-functions.md index 2b93dd924a3..2c08fa3acb7 100644 --- a/docs/en/sql-reference/functions/string-functions.md +++ b/docs/en/sql-reference/functions/string-functions.md @@ -76,7 +76,7 @@ Replaces invalid UTF-8 characters by the `�` (U+FFFD) character. All running i toValidUTF8( input_string ) ``` -Parameters: +**Arguments** - input_string — Any set of bytes represented as the [String](../../sql-reference/data-types/string.md) data type object. @@ -98,13 +98,15 @@ SELECT toValidUTF8('\x61\xF0\x80\x80\x80b') Repeats a string as many times as specified and concatenates the replicated values as a single string. +Alias: `REPEAT`. + **Syntax** ``` sql repeat(s, n) ``` -**Parameters** +**Arguments** - `s` — The string to repeat. [String](../../sql-reference/data-types/string.md). - `n` — The number of times to repeat the string. [UInt](../../sql-reference/data-types/int-uint.md). @@ -173,7 +175,7 @@ Concatenates the strings listed in the arguments, without a separator. concat(s1, s2, ...) ``` -**Parameters** +**Arguments** Values of type String or FixedString. @@ -211,7 +213,7 @@ The function is named “injective” if it always returns different result for concatAssumeInjective(s1, s2, ...) ``` -**Parameters** +**Arguments** Values of type String or FixedString. @@ -276,10 +278,14 @@ Returns the string ‘s’ that was converted from the encoding in ‘from’ to Encodes ‘s’ string into base64 +Alias: `TO_BASE64`. + ## base64Decode(s) {#base64decode} Decode base64-encoded string ‘s’ into original string. In case of failure raises an exception. +Alias: `FROM_BASE64`. + ## tryBase64Decode(s) {#trybase64decode} Similar to base64Decode, but in case of error an empty string would be returned. @@ -328,7 +334,7 @@ By default removes all consecutive occurrences of common whitespace (ASCII chara trim([[LEADING|TRAILING|BOTH] trim_character FROM] input_string) ``` -**Parameters** +**Arguments** - `trim_character` — specified characters for trim. [String](../../sql-reference/data-types/string.md). - `input_string` — string for trim. [String](../../sql-reference/data-types/string.md). @@ -367,7 +373,7 @@ trimLeft(input_string) Alias: `ltrim(input_string)`. -**Parameters** +**Arguments** - `input_string` — string to trim. [String](../../sql-reference/data-types/string.md). @@ -405,7 +411,7 @@ trimRight(input_string) Alias: `rtrim(input_string)`. -**Parameters** +**Arguments** - `input_string` — string to trim. [String](../../sql-reference/data-types/string.md). @@ -443,7 +449,7 @@ trimBoth(input_string) Alias: `trim(input_string)`. -**Parameters** +**Arguments** - `input_string` — string to trim. [String](../../sql-reference/data-types/string.md). @@ -496,7 +502,7 @@ Replaces literals, sequences of literals and complex aliases with placeholders. normalizeQuery(x) ``` -**Parameters** +**Arguments** - `x` — Sequence of characters. [String](../../sql-reference/data-types/string.md). @@ -532,7 +538,7 @@ Returns identical 64bit hash values without the values of literals for similar q normalizedQueryHash(x) ``` -**Parameters** +**Arguments** - `x` — Sequence of characters. [String](../../sql-reference/data-types/string.md). @@ -570,7 +576,7 @@ The following five XML predefined entities will be replaced: `<`, `&`, `>`, `"`, encodeXMLComponent(x) ``` -**Parameters** +**Arguments** - `x` — The sequence of characters. [String](../../sql-reference/data-types/string.md). @@ -600,4 +606,46 @@ Hello, "world"! 'foo' ``` +## decodeXMLComponent {#decode-xml-component} + +Replaces XML predefined entities with characters. Predefined entities are `"` `&` `'` `>` `<` +This function also replaces numeric character references with Unicode characters. Both decimal (like `✓`) and hexadecimal (`✓`) forms are supported. + +**Syntax** + +``` sql +decodeXMLComponent(x) +``` + +**Parameters** + +- `x` — A sequence of characters. [String](../../sql-reference/data-types/string.md). + +**Returned value** + +- The sequence of characters after replacement. + +Type: [String](../../sql-reference/data-types/string.md). + +**Example** + +Query: + +``` sql +SELECT decodeXMLComponent(''foo''); +SELECT decodeXMLComponent('< Σ >'); +``` + +Result: + +``` text +'foo' +< Σ > +``` + +**See Also** + +- [List of XML and HTML character entity references](https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references) + + [Original article](https://clickhouse.tech/docs/en/query_language/functions/string_functions/) diff --git a/docs/en/sql-reference/functions/string-search-functions.md b/docs/en/sql-reference/functions/string-search-functions.md index 92591c89a37..83b0edea438 100644 --- a/docs/en/sql-reference/functions/string-search-functions.md +++ b/docs/en/sql-reference/functions/string-search-functions.md @@ -24,7 +24,7 @@ position(haystack, needle[, start_pos]) Alias: `locate(haystack, needle[, start_pos])`. -**Parameters** +**Arguments** - `haystack` — string, in which substring will to be searched. [String](../../sql-reference/syntax.md#syntax-string-literal). - `needle` — substring to be searched. [String](../../sql-reference/syntax.md#syntax-string-literal). @@ -95,7 +95,7 @@ Works under the assumption that the string contains a set of bytes representing positionCaseInsensitive(haystack, needle[, start_pos]) ``` -**Parameters** +**Arguments** - `haystack` — string, in which substring will to be searched. [String](../../sql-reference/syntax.md#syntax-string-literal). - `needle` — substring to be searched. [String](../../sql-reference/syntax.md#syntax-string-literal). @@ -138,7 +138,7 @@ For a case-insensitive search, use the function [positionCaseInsensitiveUTF8](#p positionUTF8(haystack, needle[, start_pos]) ``` -**Parameters** +**Arguments** - `haystack` — string, in which substring will to be searched. [String](../../sql-reference/syntax.md#syntax-string-literal). - `needle` — substring to be searched. [String](../../sql-reference/syntax.md#syntax-string-literal). @@ -211,7 +211,7 @@ Works under the assumption that the string contains a set of bytes representing positionCaseInsensitiveUTF8(haystack, needle[, start_pos]) ``` -**Parameters** +**Arguments** - `haystack` — string, in which substring will to be searched. [String](../../sql-reference/syntax.md#syntax-string-literal). - `needle` — substring to be searched. [String](../../sql-reference/syntax.md#syntax-string-literal). @@ -256,7 +256,7 @@ The search is performed on sequences of bytes without respect to string encoding multiSearchAllPositions(haystack, [needle1, needle2, ..., needlen]) ``` -**Parameters** +**Arguments** - `haystack` — string, in which substring will to be searched. [String](../../sql-reference/syntax.md#syntax-string-literal). - `needle` — substring to be searched. [String](../../sql-reference/syntax.md#syntax-string-literal). @@ -371,7 +371,7 @@ Matches all groups of the `haystack` string using the `pattern` regular expressi extractAllGroupsHorizontal(haystack, pattern) ``` -**Parameters** +**Arguments** - `haystack` — Input string. Type: [String](../../sql-reference/data-types/string.md). - `pattern` — Regular expression with [re2 syntax](https://github.com/google/re2/wiki/Syntax). Must contain groups, each group enclosed in parentheses. If `pattern` contains no groups, an exception is thrown. Type: [String](../../sql-reference/data-types/string.md). @@ -412,7 +412,7 @@ Matches all groups of the `haystack` string using the `pattern` regular expressi extractAllGroupsVertical(haystack, pattern) ``` -**Parameters** +**Arguments** - `haystack` — Input string. Type: [String](../../sql-reference/data-types/string.md). - `pattern` — Regular expression with [re2 syntax](https://github.com/google/re2/wiki/Syntax). Must contain groups, each group enclosed in parentheses. If `pattern` contains no groups, an exception is thrown. Type: [String](../../sql-reference/data-types/string.md). @@ -471,7 +471,7 @@ Case insensitive variant of [like](https://clickhouse.tech/docs/en/sql-reference ilike(haystack, pattern) ``` -**Parameters** +**Arguments** - `haystack` — Input string. [String](../../sql-reference/syntax.md#syntax-string-literal). - `pattern` — If `pattern` doesn't contain percent signs or underscores, then the `pattern` only represents the string itself. An underscore (`_`) in `pattern` stands for (matches) any single character. A percent sign (`%`) matches any sequence of zero or more characters. @@ -548,7 +548,7 @@ For a case-insensitive search, use [countSubstringsCaseInsensitive](../../sql-re countSubstrings(haystack, needle[, start_pos]) ``` -**Parameters** +**Arguments** - `haystack` — The string to search in. [String](../../sql-reference/syntax.md#syntax-string-literal). - `needle` — The substring to search for. [String](../../sql-reference/syntax.md#syntax-string-literal). @@ -614,7 +614,7 @@ Returns the number of substring occurrences case-insensitive. countSubstringsCaseInsensitive(haystack, needle[, start_pos]) ``` -**Parameters** +**Arguments** - `haystack` — The string to search in. [String](../../sql-reference/syntax.md#syntax-string-literal). - `needle` — The substring to search for. [String](../../sql-reference/syntax.md#syntax-string-literal). @@ -680,7 +680,7 @@ Returns the number of substring occurrences in `UTF-8` case-insensitive. SELECT countSubstringsCaseInsensitiveUTF8(haystack, needle[, start_pos]) ``` -**Parameters** +**Arguments** - `haystack` — The string to search in. [String](../../sql-reference/syntax.md#syntax-string-literal). - `needle` — The substring to search for. [String](../../sql-reference/syntax.md#syntax-string-literal). @@ -732,7 +732,7 @@ Returns the number of regular expression matches for a `pattern` in a `haystack` countMatches(haystack, pattern) ``` -**Parameters** +**Arguments** - `haystack` — The string to search in. [String](../../sql-reference/syntax.md#syntax-string-literal). - `pattern` — The regular expression with [re2 syntax](https://github.com/google/re2/wiki/Syntax). [String](../../sql-reference/data-types/string.md). diff --git a/docs/en/sql-reference/functions/tuple-functions.md b/docs/en/sql-reference/functions/tuple-functions.md index dcbcd3e374b..1006b68b8ee 100644 --- a/docs/en/sql-reference/functions/tuple-functions.md +++ b/docs/en/sql-reference/functions/tuple-functions.md @@ -45,7 +45,7 @@ untuple(x) You can use the `EXCEPT` expression to skip columns as a result of the query. -**Parameters** +**Arguments** - `x` - A `tuple` function, column, or tuple of elements. [Tuple](../../sql-reference/data-types/tuple.md). diff --git a/docs/en/sql-reference/functions/tuple-map-functions.md b/docs/en/sql-reference/functions/tuple-map-functions.md index a46c36395b8..1d4839cbbf9 100644 --- a/docs/en/sql-reference/functions/tuple-map-functions.md +++ b/docs/en/sql-reference/functions/tuple-map-functions.md @@ -5,6 +5,68 @@ toc_title: Working with maps # Functions for maps {#functions-for-working-with-tuple-maps} +## map {#function-map} + +Arranges `key:value` pairs into [Map(key, value)](../../sql-reference/data-types/map.md) data type. + +**Syntax** + +``` sql +map(key1, value1[, key2, value2, ...]) +``` + +**Arguments** + +- `key` — The key part of the pair. [String](../../sql-reference/data-types/string.md) or [Integer](../../sql-reference/data-types/int-uint.md). +- `value` — The value part of the pair. [String](../../sql-reference/data-types/string.md), [Integer](../../sql-reference/data-types/int-uint.md) or [Array](../../sql-reference/data-types/array.md). + +**Returned value** + +- Data structure as `key:value` pairs. + +Type: [Map(key, value)](../../sql-reference/data-types/map.md). + +**Examples** + +Query: + +``` sql +SELECT map('key1', number, 'key2', number * 2) FROM numbers(3); +``` + +Result: + +``` text +┌─map('key1', number, 'key2', multiply(number, 2))─┐ +│ {'key1':0,'key2':0} │ +│ {'key1':1,'key2':2} │ +│ {'key1':2,'key2':4} │ +└──────────────────────────────────────────────────┘ +``` + +Query: + +``` sql +CREATE TABLE table_map (a Map(String, UInt64)) ENGINE = MergeTree() ORDER BY a; +INSERT INTO table_map SELECT map('key1', number, 'key2', number * 2) FROM numbers(3); +SELECT a['key2'] FROM table_map; +``` + +Result: + +``` text +┌─arrayElement(a, 'key2')─┐ +│ 0 │ +│ 2 │ +│ 4 │ +└─────────────────────────┘ +``` + +**See Also** + +- [Map(key, value)](../../sql-reference/data-types/map.md) data type + + ## mapAdd {#function-mapadd} Collect all the keys and sum corresponding values. @@ -15,7 +77,7 @@ Collect all the keys and sum corresponding values. mapAdd(Tuple(Array, Array), Tuple(Array, Array) [, ...]) ``` -**Parameters** +**Arguments** Arguments are [tuples](../../sql-reference/data-types/tuple.md#tuplet1-t2) of two [arrays](../../sql-reference/data-types/array.md#data-type-array), where items in the first array represent keys, and the second array contains values for the each key. All key arrays should have same type, and all value arrays should contain items which are promote to the one type ([Int64](../../sql-reference/data-types/int-uint.md#int-ranges), [UInt64](../../sql-reference/data-types/int-uint.md#uint-ranges) or [Float64](../../sql-reference/data-types/float.md#float32-float64)). The common promoted type is used as a type for the result array. @@ -49,7 +111,7 @@ Collect all the keys and subtract corresponding values. mapSubtract(Tuple(Array, Array), Tuple(Array, Array) [, ...]) ``` -**Parameters** +**Arguments** Arguments are [tuples](../../sql-reference/data-types/tuple.md#tuplet1-t2) of two [arrays](../../sql-reference/data-types/array.md#data-type-array), where items in the first array represent keys, and the second array contains values for the each key. All key arrays should have same type, and all value arrays should contain items which are promote to the one type ([Int64](../../sql-reference/data-types/int-uint.md#int-ranges), [UInt64](../../sql-reference/data-types/int-uint.md#uint-ranges) or [Float64](../../sql-reference/data-types/float.md#float32-float64)). The common promoted type is used as a type for the result array. @@ -87,7 +149,7 @@ Generates a map, where keys are a series of numbers, from minimum to maximum key The number of elements in `keys` and `values` must be the same for each row. -**Parameters** +**Arguments** - `keys` — Array of keys. [Array](../../sql-reference/data-types/array.md#data-type-array)([Int](../../sql-reference/data-types/int-uint.md#uint-ranges)). - `values` — Array of values. [Array](../../sql-reference/data-types/array.md#data-type-array)([Int](../../sql-reference/data-types/int-uint.md#uint-ranges)). @@ -112,4 +174,129 @@ Result: └──────────────────────────────┴───────────────────────────────────┘ ``` -[Original article](https://clickhouse.tech/docs/en/query_language/functions/tuple-map-functions/) +## mapContains {#mapcontains} + +Determines whether the `map` contains the `key` parameter. + +**Syntax** + +``` sql +mapContains(map, key) +``` + +**Parameters** + +- `map` — Map. [Map](../../sql-reference/data-types/map.md). +- `key` — Key. Type matches the type of keys of `map` parameter. + +**Returned value** + +- `1` if `map` contains `key`, `0` if not. + +Type: [UInt8](../../sql-reference/data-types/int-uint.md). + +**Example** + +Query: + +```sql +CREATE TABLE test (a Map(String,String)) ENGINE = Memory; + +INSERT INTO test VALUES ({'name':'eleven','age':'11'}), ({'number':'twelve','position':'6.0'}); + +SELECT mapContains(a, 'name') FROM test; + +``` + +Result: + +```text +┌─mapContains(a, 'name')─┐ +│ 1 │ +│ 0 │ +└────────────────────────┘ +``` + +## mapKeys {#mapkeys} + +Returns all keys from the `map` parameter. + +**Syntax** + +```sql +mapKeys(map) +``` + +**Parameters** + +- `map` — Map. [Map](../../sql-reference/data-types/map.md). + +**Returned value** + +- Array containing all keys from the `map`. + +Type: [Array](../../sql-reference/data-types/array.md). + +**Example** + +Query: + +```sql +CREATE TABLE test (a Map(String,String)) ENGINE = Memory; + +INSERT INTO test VALUES ({'name':'eleven','age':'11'}), ({'number':'twelve','position':'6.0'}); + +SELECT mapKeys(a) FROM test; +``` + +Result: + +```text +┌─mapKeys(a)────────────┐ +│ ['name','age'] │ +│ ['number','position'] │ +└───────────────────────┘ +``` + +## mapValues {#mapvalues} + +Returns all values from the `map` parameter. + +**Syntax** + +```sql +mapKeys(map) +``` + +**Parameters** + +- `map` — Map. [Map](../../sql-reference/data-types/map.md). + +**Returned value** + +- Array containing all the values from `map`. + +Type: [Array](../../sql-reference/data-types/array.md). + +**Example** + +Query: + +```sql +CREATE TABLE test (a Map(String,String)) ENGINE = Memory; + +INSERT INTO test VALUES ({'name':'eleven','age':'11'}), ({'number':'twelve','position':'6.0'}); + +SELECT mapValues(a) FROM test; +``` + +Result: + +```text +┌─mapValues(a)─────┐ +│ ['eleven','11'] │ +│ ['twelve','6.0'] │ +└──────────────────┘ +``` + +[Original article](https://clickhouse.tech/docs/en/sql-reference/functions/tuple-map-functions/) diff --git a/docs/en/sql-reference/functions/type-conversion-functions.md b/docs/en/sql-reference/functions/type-conversion-functions.md index 3ca36f41c78..8a793b99ac9 100644 --- a/docs/en/sql-reference/functions/type-conversion-functions.md +++ b/docs/en/sql-reference/functions/type-conversion-functions.md @@ -22,7 +22,7 @@ Converts an input value to the [Int](../../sql-reference/data-types/int-uint.md) - `toInt128(expr)` — Results in the `Int128` data type. - `toInt256(expr)` — Results in the `Int256` data type. -**Parameters** +**Arguments** - `expr` — [Expression](../../sql-reference/syntax.md#syntax-expressions) returning a number or a string with the decimal representation of a number. Binary, octal, and hexadecimal representations of numbers are not supported. Leading zeroes are stripped. @@ -36,10 +36,14 @@ The behavior of functions for the [NaN and Inf](../../sql-reference/data-types/f **Example** +Query: + ``` sql -SELECT toInt64(nan), toInt32(32), toInt16('16'), toInt8(8.8) +SELECT toInt64(nan), toInt32(32), toInt16('16'), toInt8(8.8); ``` +Result: + ``` text ┌─────────toInt64(nan)─┬─toInt32(32)─┬─toInt16('16')─┬─toInt8(8.8)─┐ │ -9223372036854775808 │ 32 │ 16 │ 8 │ @@ -52,10 +56,14 @@ It takes an argument of type String and tries to parse it into Int (8 \| 16 \| 3 **Example** +Query: + ``` sql -select toInt64OrZero('123123'), toInt8OrZero('123qwe123') +SELECT toInt64OrZero('123123'), toInt8OrZero('123qwe123'); ``` +Result: + ``` text ┌─toInt64OrZero('123123')─┬─toInt8OrZero('123qwe123')─┐ │ 123123 │ 0 │ @@ -68,10 +76,14 @@ It takes an argument of type String and tries to parse it into Int (8 \| 16 \| 3 **Example** +Query: + ``` sql -select toInt64OrNull('123123'), toInt8OrNull('123qwe123') +SELECT toInt64OrNull('123123'), toInt8OrNull('123qwe123'); ``` +Result: + ``` text ┌─toInt64OrNull('123123')─┬─toInt8OrNull('123qwe123')─┐ │ 123123 │ ᴺᵁᴸᴸ │ @@ -88,7 +100,7 @@ Converts an input value to the [UInt](../../sql-reference/data-types/int-uint.md - `toUInt64(expr)` — Results in the `UInt64` data type. - `toUInt256(expr)` — Results in the `UInt256` data type. -**Parameters** +**Arguments** - `expr` — [Expression](../../sql-reference/syntax.md#syntax-expressions) returning a number or a string with the decimal representation of a number. Binary, octal, and hexadecimal representations of numbers are not supported. Leading zeroes are stripped. @@ -102,10 +114,14 @@ The behavior of functions for negative agruments and for the [NaN and Inf](../.. **Example** +Query: + ``` sql -SELECT toUInt64(nan), toUInt32(-32), toUInt16('16'), toUInt8(8.8) +SELECT toUInt64(nan), toUInt32(-32), toUInt16('16'), toUInt8(8.8); ``` +Result: + ``` text ┌───────toUInt64(nan)─┬─toUInt32(-32)─┬─toUInt16('16')─┬─toUInt8(8.8)─┐ │ 9223372036854775808 │ 4294967264 │ 16 │ 8 │ @@ -124,6 +140,8 @@ SELECT toUInt64(nan), toUInt32(-32), toUInt16('16'), toUInt8(8.8) ## toDate {#todate} +Alias: `DATE`. + ## toDateOrZero {#todateorzero} ## toDateOrNull {#todateornull} @@ -154,7 +172,7 @@ Converts an input string to a [Nullable(Decimal(P,S))](../../sql-reference/data- These functions should be used instead of `toDecimal*()` functions, if you prefer to get a `NULL` value instead of an exception in the event of an input value parsing error. -**Parameters** +**Arguments** - `expr` — [Expression](../../sql-reference/syntax.md#syntax-expressions), returns a value in the [String](../../sql-reference/data-types/string.md) data type. ClickHouse expects the textual representation of the decimal number. For example, `'1.111'`. - `S` — Scale, the number of decimal places in the resulting value. @@ -168,20 +186,28 @@ A value in the `Nullable(Decimal(P,S))` data type. The value contains: **Examples** +Query: + ``` sql -SELECT toDecimal32OrNull(toString(-1.111), 5) AS val, toTypeName(val) +SELECT toDecimal32OrNull(toString(-1.111), 5) AS val, toTypeName(val); ``` +Result: + ``` text ┌──────val─┬─toTypeName(toDecimal32OrNull(toString(-1.111), 5))─┐ │ -1.11100 │ Nullable(Decimal(9, 5)) │ └──────────┴────────────────────────────────────────────────────┘ ``` +Query: + ``` sql -SELECT toDecimal32OrNull(toString(-1.111), 2) AS val, toTypeName(val) +SELECT toDecimal32OrNull(toString(-1.111), 2) AS val, toTypeName(val); ``` +Result: + ``` text ┌──val─┬─toTypeName(toDecimal32OrNull(toString(-1.111), 2))─┐ │ ᴺᵁᴸᴸ │ Nullable(Decimal(9, 2)) │ @@ -199,7 +225,7 @@ Converts an input value to the [Decimal(P,S)](../../sql-reference/data-types/dec These functions should be used instead of `toDecimal*()` functions, if you prefer to get a `0` value instead of an exception in the event of an input value parsing error. -**Parameters** +**Arguments** - `expr` — [Expression](../../sql-reference/syntax.md#syntax-expressions), returns a value in the [String](../../sql-reference/data-types/string.md) data type. ClickHouse expects the textual representation of the decimal number. For example, `'1.111'`. - `S` — Scale, the number of decimal places in the resulting value. @@ -213,20 +239,28 @@ A value in the `Nullable(Decimal(P,S))` data type. The value contains: **Example** +Query: + ``` sql -SELECT toDecimal32OrZero(toString(-1.111), 5) AS val, toTypeName(val) +SELECT toDecimal32OrZero(toString(-1.111), 5) AS val, toTypeName(val); ``` +Result: + ``` text ┌──────val─┬─toTypeName(toDecimal32OrZero(toString(-1.111), 5))─┐ │ -1.11100 │ Decimal(9, 5) │ └──────────┴────────────────────────────────────────────────────┘ ``` +Query: + ``` sql -SELECT toDecimal32OrZero(toString(-1.111), 2) AS val, toTypeName(val) +SELECT toDecimal32OrZero(toString(-1.111), 2) AS val, toTypeName(val); ``` +Result: + ``` text ┌──val─┬─toTypeName(toDecimal32OrZero(toString(-1.111), 2))─┐ │ 0.00 │ Decimal(9, 2) │ @@ -258,12 +292,18 @@ Conversion between numeric types uses the same rules as assignments between diff Additionally, the toString function of the DateTime argument can take a second String argument containing the name of the time zone. Example: `Asia/Yekaterinburg` In this case, the time is formatted according to the specified time zone. +**Example** + +Query: + ``` sql SELECT now() AS now_local, - toString(now(), 'Asia/Yekaterinburg') AS now_yekat + toString(now(), 'Asia/Yekaterinburg') AS now_yekat; ``` +Result: + ``` text ┌───────────now_local─┬─now_yekat───────────┐ │ 2016-06-15 00:11:21 │ 2016-06-15 02:11:21 │ @@ -281,52 +321,39 @@ If the string has fewer bytes than N, it is padded with null bytes to the right. Accepts a String or FixedString argument. Returns the String with the content truncated at the first zero byte found. -Example: +**Example** + +Query: ``` sql -SELECT toFixedString('foo', 8) AS s, toStringCutToZero(s) AS s_cut +SELECT toFixedString('foo', 8) AS s, toStringCutToZero(s) AS s_cut; ``` +Result: + ``` text ┌─s─────────────┬─s_cut─┐ │ foo\0\0\0\0\0 │ foo │ └───────────────┴───────┘ ``` +Query: + ``` sql -SELECT toFixedString('foo\0bar', 8) AS s, toStringCutToZero(s) AS s_cut +SELECT toFixedString('foo\0bar', 8) AS s, toStringCutToZero(s) AS s_cut; ``` +Result: + ``` text ┌─s──────────┬─s_cut─┐ │ foo\0bar\0 │ foo │ └────────────┴───────┘ ``` -## reinterpretAs(x, T) {#type_conversion_function-cast} +## reinterpretAsUInt(8\|16\|32\|64) {#reinterpretasuint8163264} -Performs byte reinterpretation of ‘x’ as ‘t’ data type. - -Following reinterpretations are allowed: -1. Any type that has fixed size and value of that type can be represented continuously into FixedString. -2. Any type that if value of that type can be represented continuously into String. Null bytes are dropped from the end. For example, a UInt32 type value of 255 is a string that is one byte long. -3. FixedString, String, types that can be interpreted as numeric (Integers, Float, Date, DateTime, UUID) into types that can be interpreted as numeric (Integers, Float, Date, DateTime, UUID) into FixedString, - -``` sql -SELECT reinterpretAs(toInt8(-1), 'UInt8') as int_to_uint, - reinterpretAs(toInt8(1), 'Float32') as int_to_float, - reinterpretAs('1', 'UInt32') as string_to_int; -``` - -``` text -┌─int_to_uint─┬─int_to_float─┬─string_to_int─┐ -│ 255 │ 1e-45 │ 49 │ -└─────────────┴──────────────┴───────────────┘ -``` - -## reinterpretAsUInt(8\|16\|32\|64\|256) {#reinterpretasuint8163264256} - -## reinterpretAsInt(8\|16\|32\|64\|128\|256) {#reinterpretasint8163264128256} +## reinterpretAsInt(8\|16\|32\|64) {#reinterpretasint8163264} ## reinterpretAsFloat(32\|64) {#reinterpretasfloat3264} @@ -334,19 +361,87 @@ SELECT reinterpretAs(toInt8(-1), 'UInt8') as int_to_uint, ## reinterpretAsDateTime {#reinterpretasdatetime} +These functions accept a string and interpret the bytes placed at the beginning of the string as a number in host order (little endian). If the string isn’t long enough, the functions work as if the string is padded with the necessary number of null bytes. If the string is longer than needed, the extra bytes are ignored. A date is interpreted as the number of days since the beginning of the Unix Epoch, and a date with time is interpreted as the number of seconds since the beginning of the Unix Epoch. + ## reinterpretAsString {#type_conversion_functions-reinterpretAsString} +This function accepts a number or date or date with time, and returns a string containing bytes representing the corresponding value in host order (little endian). Null bytes are dropped from the end. For example, a UInt32 type value of 255 is a string that is one byte long. + ## reinterpretAsFixedString {#reinterpretasfixedstring} +This function accepts a number or date or date with time, and returns a FixedString containing bytes representing the corresponding value in host order (little endian). Null bytes are dropped from the end. For example, a UInt32 type value of 255 is a FixedString that is one byte long. + ## reinterpretAsUUID {#reinterpretasuuid} -These functions are aliases for `reinterpretAs`function. +This function accepts 16 bytes string, and returns UUID containing bytes representing the corresponding value in network byte order (big-endian). If the string isn't long enough, the functions work as if the string is padded with the necessary number of null bytes to the end. If the string longer than 16 bytes, the extra bytes at the end are ignored. + +**Syntax** + +``` sql +reinterpretAsUUID(fixed_string) +``` + +**Parameters** + +- `fixed_string` — Big-endian byte string. [FixedString](../../sql-reference/data-types/fixedstring.md#fixedstring). + +## reinterpret(x, T) {#type_conversion_function-reinterpret} + +**Returned value** + +- The UUID type value. [UUID](../../sql-reference/data-types/uuid.md#uuid-data-type). + +**Examples** + +String to UUID. + +Query: + +``` sql +SELECT reinterpret(toInt8(-1), 'UInt8') as int_to_uint, + reinterpret(toInt8(1), 'Float32') as int_to_float, + reinterpret('1', 'UInt32') as string_to_int; +``` + +Result: + +``` text +┌─reinterpretAsUUID(reverse(unhex('000102030405060708090a0b0c0d0e0f')))─┐ +│ 08090a0b-0c0d-0e0f-0001-020304050607 │ +└───────────────────────────────────────────────────────────────────────┘ +``` + +Going back and forth from String to UUID. + +Query: + +``` sql +WITH + generateUUIDv4() AS uuid, + identity(lower(hex(reverse(reinterpretAsString(uuid))))) AS str, + reinterpretAsUUID(reverse(unhex(str))) AS uuid2 +SELECT uuid = uuid2; +``` + +Result: + +``` text +┌─equals(uuid, uuid2)─┐ +│ 1 │ +└─────────────────────┘ +``` ## CAST(x, T) {#type_conversion_function-cast} -Converts ‘x’ to the ‘t’ data type. The syntax CAST(x AS t) is also supported. +Converts input value `x` to the `T` data type. -Example: +The syntax `CAST(x AS t)` is also supported. + +Note, that if value `x` does not fit the bounds of type T, the function overflows. For example, CAST(-1, 'UInt8') returns 255. + +**Example** + +Query: ``` sql SELECT @@ -354,9 +449,11 @@ SELECT CAST(timestamp AS DateTime) AS datetime, CAST(timestamp AS Date) AS date, CAST(timestamp, 'String') AS string, - CAST(timestamp, 'FixedString(22)') AS fixed_string + CAST(timestamp, 'FixedString(22)') AS fixed_string; ``` +Result: + ``` text ┌─timestamp───────────┬────────────datetime─┬───────date─┬─string──────────────┬─fixed_string──────────────┐ │ 2016-06-15 23:00:00 │ 2016-06-15 23:00:00 │ 2016-06-15 │ 2016-06-15 23:00:00 │ 2016-06-15 23:00:00\0\0\0 │ @@ -365,12 +462,18 @@ SELECT Conversion to FixedString(N) only works for arguments of type String or FixedString(N). -Type conversion to [Nullable](../../sql-reference/data-types/nullable.md) and back is supported. Example: +Type conversion to [Nullable](../../sql-reference/data-types/nullable.md) and back is supported. + +**Example** + +Query: ``` sql -SELECT toTypeName(x) FROM t_null +SELECT toTypeName(x) FROM t_null; ``` +Result: + ``` text ┌─toTypeName(x)─┐ │ Int8 │ @@ -378,10 +481,14 @@ SELECT toTypeName(x) FROM t_null └───────────────┘ ``` +Query: + ``` sql -SELECT toTypeName(CAST(x, 'Nullable(UInt16)')) FROM t_null +SELECT toTypeName(CAST(x, 'Nullable(UInt16)')) FROM t_null; ``` +Result: + ``` text ┌─toTypeName(CAST(x, 'Nullable(UInt16)'))─┐ │ Nullable(UInt16) │ @@ -395,15 +502,19 @@ SELECT toTypeName(CAST(x, 'Nullable(UInt16)')) FROM t_null ## accurateCast(x, T) {#type_conversion_function-accurate-cast} -Converts ‘x’ to the ‘t’ data type. The differente from cast(x, T) is that accurateCast -does not allow overflow of numeric types during cast if type value x does not fit -bounds of type T. +Converts `x` to the `T` data type. + +The difference from [cast(x, T)](#type_conversion_function-cast) is that `accurateCast` does not allow overflow of numeric types during cast if type value `x` does not fit the bounds of type `T`. For example, `accurateCast(-1, 'UInt8')` throws an exception. + +**Example** + +Query: -Example ``` sql -SELECT cast(-1, 'UInt8') as uint8; +SELECT cast(-1, 'UInt8') as uint8; ``` +Result: ``` text ┌─uint8─┐ @@ -411,38 +522,46 @@ SELECT cast(-1, 'UInt8') as uint8; └───────┘ ``` +Query: + ```sql SELECT accurateCast(-1, 'UInt8') as uint8; ``` +Result: + ``` text Code: 70. DB::Exception: Received from localhost:9000. DB::Exception: Value in column Int8 cannot be safely converted into type UInt8: While processing accurateCast(-1, 'UInt8') AS uint8. - ``` ## accurateCastOrNull(x, T) {#type_conversion_function-accurate-cast_or_null} -Converts ‘x’ to the ‘t’ data type. Always returns nullable type and returns NULL -if the casted value is not representable in the target type. +Converts input value `x` to the specified data type `T`. Always returns [Nullable](../../sql-reference/data-types/nullable.md) type and returns [NULL](../../sql-reference/syntax.md#null-literal) if the casted value is not representable in the target type. -Example: +**Syntax** + +```sql +accurateCastOrNull(x, T) +``` + +**Parameters** + +- `x` — Input value. +- `T` — The name of the returned data type. + +**Returned value** + +- The value, converted to the specified data type `T`. + +**Example** + +Query: ``` sql -SELECT - accurateCastOrNull(-1, 'UInt8') as uint8, - accurateCastOrNull(128, 'Int8') as int8, - accurateCastOrNull('Test', 'FixedString(2)') as fixed_string +SELECT toTypeName(accurateCastOrNull(5, 'UInt8')); ``` -``` text -┌─uint8─┬─int8─┬─fixed_string─┐ -│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ -└───────┴──────┴──────────────┘┘ -``` - -``` sql -SELECT toTypeName(accurateCastOrNull(5, 'UInt8')) -``` +Result: ``` text ┌─toTypeName(accurateCastOrNull(5, 'UInt8'))─┐ @@ -450,6 +569,23 @@ SELECT toTypeName(accurateCastOrNull(5, 'UInt8')) └────────────────────────────────────────────┘ ``` +Query: + +``` sql +SELECT + accurateCastOrNull(-1, 'UInt8') as uint8, + accurateCastOrNull(128, 'Int8') as int8, + accurateCastOrNull('Test', 'FixedString(2)') as fixed_string; +``` + +Result: + +``` text +┌─uint8─┬─int8─┬─fixed_string─┐ +│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ +└───────┴──────┴──────────────┘ +``` + ## toInterval(Year\|Quarter\|Month\|Week\|Day\|Hour\|Minute\|Second) {#function-tointerval} Converts a Number type argument to an [Interval](../../sql-reference/data-types/special-data-types/interval.md) data type. @@ -467,7 +603,7 @@ toIntervalQuarter(number) toIntervalYear(number) ``` -**Parameters** +**Arguments** - `number` — Duration of interval. Positive integer number. @@ -477,6 +613,8 @@ toIntervalYear(number) **Example** +Query: + ``` sql WITH toDate('2019-01-01') AS date, @@ -484,9 +622,11 @@ WITH toIntervalWeek(1) AS interval_to_week SELECT date + interval_week, - date + interval_to_week + date + interval_to_week; ``` +Result: + ``` text ┌─plus(date, interval_week)─┬─plus(date, interval_to_week)─┐ │ 2019-01-08 │ 2019-01-08 │ @@ -502,10 +642,10 @@ The function parses [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601), [RFC 112 **Syntax** ``` sql -parseDateTimeBestEffort(time_string [, time_zone]); +parseDateTimeBestEffort(time_string [, time_zone]) ``` -**Parameters** +**Arguments** - `time_string` — String containing a date and time to convert. [String](../../sql-reference/data-types/string.md). - `time_zone` — Time zone. The function parses `time_string` according to the time zone. [String](../../sql-reference/data-types/string.md). @@ -545,7 +685,7 @@ Query: ``` sql SELECT parseDateTimeBestEffort('Sat, 18 Aug 2018 07:22:16 GMT', 'Europe/Moscow') -AS parseDateTimeBestEffort +AS parseDateTimeBestEffort; ``` Result: @@ -560,7 +700,7 @@ Query: ``` sql SELECT parseDateTimeBestEffort('1284101485') -AS parseDateTimeBestEffort +AS parseDateTimeBestEffort; ``` Result: @@ -575,7 +715,7 @@ Query: ``` sql SELECT parseDateTimeBestEffort('2018-12-12 10:12:12') -AS parseDateTimeBestEffort +AS parseDateTimeBestEffort; ``` Result: @@ -589,7 +729,7 @@ Result: Query: ``` sql -SELECT parseDateTimeBestEffort('10 20:19') +SELECT parseDateTimeBestEffort('10 20:19'); ``` Result: @@ -609,15 +749,15 @@ Result: ## parseDateTimeBestEffortUS {#parsedatetimebesteffortUS} -This function is similar to [‘parseDateTimeBestEffort’](#parsedatetimebesteffort), the only difference is that this function prefers US date format (`MM/DD/YYYY` etc.) in case of ambiguity. +This function is similar to [parseDateTimeBestEffort](#parsedatetimebesteffort), the only difference is that this function prefers US date format (`MM/DD/YYYY` etc.) in case of ambiguity. **Syntax** ``` sql -parseDateTimeBestEffortUS(time_string [, time_zone]); +parseDateTimeBestEffortUS(time_string [, time_zone]) ``` -**Parameters** +**Arguments** - `time_string` — String containing a date and time to convert. [String](../../sql-reference/data-types/string.md). - `time_zone` — Time zone. The function parses `time_string` according to the time zone. [String](../../sql-reference/data-types/string.md). @@ -689,6 +829,178 @@ Same as for [parseDateTimeBestEffort](#parsedatetimebesteffort) except that it r Same as for [parseDateTimeBestEffort](#parsedatetimebesteffort) except that it returns zero date or zero date time when it encounters a date format that cannot be processed. +## parseDateTimeBestEffortUSOrNull {#parsedatetimebesteffortusornull} + +Same as [parseDateTimeBestEffortUS](#parsedatetimebesteffortUS) function except that it returns `NULL` when it encounters a date format that cannot be processed. + +**Syntax** + +``` sql +parseDateTimeBestEffortUSOrNull(time_string[, time_zone]) +``` + +**Parameters** + +- `time_string` — String containing a date or date with time to convert. The date must be in the US date format (`MM/DD/YYYY`, etc). [String](../../sql-reference/data-types/string.md). +- `time_zone` — [Timezone](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone). The function parses `time_string` according to the timezone. Optional. [String](../../sql-reference/data-types/string.md). + +**Supported non-standard formats** + +- A string containing 9..10 digit [unix timestamp](https://en.wikipedia.org/wiki/Unix_time). +- A string with a date and a time components: `YYYYMMDDhhmmss`, `MM/DD/YYYY hh:mm:ss`, `MM-DD-YY hh:mm`, `YYYY-MM-DD hh:mm:ss`, etc. +- A string with a date, but no time component: `YYYY`, `YYYYMM`, `YYYY*MM`, `MM/DD/YYYY`, `MM-DD-YY`, etc. +- A string with a day and time: `DD`, `DD hh`, `DD hh:mm`. In this case, `YYYY-MM` are substituted with `2000-01`. +- A string that includes date and time along with timezone offset information: `YYYY-MM-DD hh:mm:ss ±h:mm`, etc. For example, `2020-12-12 17:36:00 -5:00`. + +**Returned values** + +- `time_string` converted to the [DateTime](../../sql-reference/data-types/datetime.md) data type. +- `NULL` if the input string cannot be converted to the `DateTime` data type. + +**Examples** + +Query: + +``` sql +SELECT parseDateTimeBestEffortUSOrNull('02/10/2021 21:12:57') AS parseDateTimeBestEffortUSOrNull; +``` + +Result: + +``` text +┌─parseDateTimeBestEffortUSOrNull─┐ +│ 2021-02-10 21:12:57 │ +└─────────────────────────────────┘ +``` + +Query: + +``` sql +SELECT parseDateTimeBestEffortUSOrNull('02-10-2021 21:12:57 GMT', 'Europe/Moscow') AS parseDateTimeBestEffortUSOrNull; +``` + +Result: + +``` text +┌─parseDateTimeBestEffortUSOrNull─┐ +│ 2021-02-11 00:12:57 │ +└─────────────────────────────────┘ +``` + +Query: + +``` sql +SELECT parseDateTimeBestEffortUSOrNull('02.10.2021') AS parseDateTimeBestEffortUSOrNull; +``` + +Result: + +``` text +┌─parseDateTimeBestEffortUSOrNull─┐ +│ 2021-02-10 00:00:00 │ +└─────────────────────────────────┘ +``` + +Query: + +``` sql +SELECT parseDateTimeBestEffortUSOrNull('10.2021') AS parseDateTimeBestEffortUSOrNull; +``` + +Result: + +``` text +┌─parseDateTimeBestEffortUSOrNull─┐ +│ ᴺᵁᴸᴸ │ +└─────────────────────────────────┘ +``` + +## parseDateTimeBestEffortUSOrZero {#parsedatetimebesteffortusorzero} + +Same as [parseDateTimeBestEffortUS](#parsedatetimebesteffortUS) function except that it returns zero date (`1970-01-01`) or zero date with time (`1970-01-01 00:00:00`) when it encounters a date format that cannot be processed. + +**Syntax** + +``` sql +parseDateTimeBestEffortUSOrZero(time_string[, time_zone]) +``` + +**Parameters** + +- `time_string` — String containing a date or date with time to convert. The date must be in the US date format (`MM/DD/YYYY`, etc). [String](../../sql-reference/data-types/string.md). +- `time_zone` — [Timezone](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone). The function parses `time_string` according to the timezone. Optional. [String](../../sql-reference/data-types/string.md). + +**Supported non-standard formats** + +- A string containing 9..10 digit [unix timestamp](https://en.wikipedia.org/wiki/Unix_time). +- A string with a date and a time components: `YYYYMMDDhhmmss`, `MM/DD/YYYY hh:mm:ss`, `MM-DD-YY hh:mm`, `YYYY-MM-DD hh:mm:ss`, etc. +- A string with a date, but no time component: `YYYY`, `YYYYMM`, `YYYY*MM`, `MM/DD/YYYY`, `MM-DD-YY`, etc. +- A string with a day and time: `DD`, `DD hh`, `DD hh:mm`. In this case, `YYYY-MM` are substituted with `2000-01`. +- A string that includes date and time along with timezone offset information: `YYYY-MM-DD hh:mm:ss ±h:mm`, etc. For example, `2020-12-12 17:36:00 -5:00`. + +**Returned values** + +- `time_string` converted to the [DateTime](../../sql-reference/data-types/datetime.md) data type. +- Zero date or zero date with time if the input string cannot be converted to the `DateTime` data type. + +**Examples** + +Query: + +``` sql +SELECT parseDateTimeBestEffortUSOrZero('02/10/2021 21:12:57') AS parseDateTimeBestEffortUSOrZero; +``` + +Result: + +``` text +┌─parseDateTimeBestEffortUSOrZero─┐ +│ 2021-02-10 21:12:57 │ +└─────────────────────────────────┘ +``` + +Query: + +``` sql +SELECT parseDateTimeBestEffortUSOrZero('02-10-2021 21:12:57 GMT', 'Europe/Moscow') AS parseDateTimeBestEffortUSOrZero; +``` + +Result: + +``` text +┌─parseDateTimeBestEffortUSOrZero─┐ +│ 2021-02-11 00:12:57 │ +└─────────────────────────────────┘ +``` + +Query: + +``` sql +SELECT parseDateTimeBestEffortUSOrZero('02.10.2021') AS parseDateTimeBestEffortUSOrZero; +``` + +Result: + +``` text +┌─parseDateTimeBestEffortUSOrZero─┐ +│ 2021-02-10 00:00:00 │ +└─────────────────────────────────┘ +``` + +Query: + +``` sql +SELECT parseDateTimeBestEffortUSOrZero('02.2021') AS parseDateTimeBestEffortUSOrZero; +``` + +Result: + +``` text +┌─parseDateTimeBestEffortUSOrZero─┐ +│ 1970-01-01 00:00:00 │ +└─────────────────────────────────┘ +``` + ## toLowCardinality {#tolowcardinality} Converts input parameter to the [LowCardianlity](../../sql-reference/data-types/lowcardinality.md) version of same data type. @@ -701,7 +1013,7 @@ To convert data from the `LowCardinality` data type use the [CAST](#type_convers toLowCardinality(expr) ``` -**Parameters** +**Arguments** - `expr` — [Expression](../../sql-reference/syntax.md#syntax-expressions) resulting in one of the [supported data types](../../sql-reference/data-types/index.md#data_types). @@ -716,7 +1028,7 @@ Type: `LowCardinality(expr_result_type)` Query: ``` sql -SELECT toLowCardinality('1') +SELECT toLowCardinality('1'); ``` Result: @@ -741,7 +1053,7 @@ Converts a `DateTime64` to a `Int64` value with fixed sub-second precision. Inpu toUnixTimestamp64Milli(value) ``` -**Parameters** +**Arguments** - `value` — DateTime64 value with any precision. @@ -755,7 +1067,7 @@ Query: ``` sql WITH toDateTime64('2019-09-16 19:20:12.345678910', 6) AS dt64 -SELECT toUnixTimestamp64Milli(dt64) +SELECT toUnixTimestamp64Milli(dt64); ``` Result: @@ -768,7 +1080,7 @@ Result: ``` sql WITH toDateTime64('2019-09-16 19:20:12.345678910', 6) AS dt64 -SELECT toUnixTimestamp64Nano(dt64) +SELECT toUnixTimestamp64Nano(dt64); ``` Result: @@ -793,7 +1105,7 @@ Converts an `Int64` to a `DateTime64` value with fixed sub-second precision and fromUnixTimestamp64Milli(value [, ti]) ``` -**Parameters** +**Arguments** - `value` — `Int64` value with any precision. - `timezone` — `String` (optional) timezone name of the result. @@ -802,13 +1114,17 @@ fromUnixTimestamp64Milli(value [, ti]) - `value` converted to the `DateTime64` data type. -**Examples** +**Example** + +Query: ``` sql WITH CAST(1234567891011, 'Int64') AS i64 -SELECT fromUnixTimestamp64Milli(i64, 'UTC') +SELECT fromUnixTimestamp64Milli(i64, 'UTC'); ``` +Result: + ``` text ┌─fromUnixTimestamp64Milli(i64, 'UTC')─┐ │ 2009-02-13 23:31:31.011 │ @@ -817,15 +1133,15 @@ SELECT fromUnixTimestamp64Milli(i64, 'UTC') ## formatRow {#formatrow} -Converts arbitrary expressions into a string via given format. +Converts arbitrary expressions into a string via given format. -**Syntax** +**Syntax** ``` sql formatRow(format, x, y, ...) ``` -**Parameters** +**Arguments** - `format` — Text format. For example, [CSV](../../interfaces/formats.md#csv), [TSV](../../interfaces/formats.md#tabseparated). - `x`,`y`, ... — Expressions. @@ -840,7 +1156,7 @@ Query: ``` sql SELECT formatRow('CSV', number, 'good') -FROM numbers(3) +FROM numbers(3); ``` Result: @@ -860,13 +1176,13 @@ Result: Converts arbitrary expressions into a string via given format. The function trims the last `\n` if any. -**Syntax** +**Syntax** ``` sql formatRowNoNewline(format, x, y, ...) ``` -**Parameters** +**Arguments** - `format` — Text format. For example, [CSV](../../interfaces/formats.md#csv), [TSV](../../interfaces/formats.md#tabseparated). - `x`,`y`, ... — Expressions. @@ -881,7 +1197,7 @@ Query: ``` sql SELECT formatRowNoNewline('CSV', number, 'good') -FROM numbers(3) +FROM numbers(3); ``` Result: diff --git a/docs/en/sql-reference/functions/url-functions.md b/docs/en/sql-reference/functions/url-functions.md index 006542f494a..9e79ef2d0cb 100644 --- a/docs/en/sql-reference/functions/url-functions.md +++ b/docs/en/sql-reference/functions/url-functions.md @@ -25,7 +25,7 @@ Extracts the hostname from a URL. domain(url) ``` -**Parameters** +**Arguments** - `url` — URL. Type: [String](../../sql-reference/data-types/string.md). @@ -76,7 +76,7 @@ Extracts the the top-level domain from a URL. topLevelDomain(url) ``` -**Parameters** +**Arguments** - `url` — URL. Type: [String](../../sql-reference/data-types/string.md). @@ -133,10 +133,9 @@ For example: ### cutToFirstSignificantSubdomainCustom {#cuttofirstsignificantsubdomaincustom} -Same as `cutToFirstSignificantSubdomain` but accept custom TLD list name, useful if: +Returns the part of the domain that includes top-level subdomains up to the first significant subdomain. Accepts custom [TLD list](https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains) name. -- you need fresh TLD list, -- or you have custom. +Can be useful if you need fresh TLD list or you have custom. Configuration example: @@ -149,21 +148,150 @@ Configuration example: ``` -Example: +**Syntax** -- `cutToFirstSignificantSubdomain('https://news.yandex.com.tr/', 'public_suffix_list') = 'yandex.com.tr'`. +``` sql +cutToFirstSignificantSubdomain(URL, TLD) +``` + +**Parameters** + +- `URL` — URL. [String](../../sql-reference/data-types/string.md). +- `TLD` — Custom TLD list name. [String](../../sql-reference/data-types/string.md). + +**Returned value** + +- Part of the domain that includes top-level subdomains up to the first significant subdomain. + +Type: [String](../../sql-reference/data-types/string.md). + +**Example** + +Query: + +```sql +SELECT cutToFirstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list'); +``` + +Result: + +```text +┌─cutToFirstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list')─┐ +│ foo.there-is-no-such-domain │ +└───────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +**See Also** + +- [firstSignificantSubdomain](#firstsignificantsubdomain). ### cutToFirstSignificantSubdomainCustomWithWWW {#cuttofirstsignificantsubdomaincustomwithwww} -Same as `cutToFirstSignificantSubdomainWithWWW` but accept custom TLD list name. +Returns the part of the domain that includes top-level subdomains up to the first significant subdomain without stripping `www`. Accepts custom TLD list name. + +Can be useful if you need fresh TLD list or you have custom. + +Configuration example: + +```xml + + + + public_suffix_list.dat + + +``` + +**Syntax** + +```sql +cutToFirstSignificantSubdomainCustomWithWWW(URL, TLD) +``` + +**Parameters** + +- `URL` — URL. [String](../../sql-reference/data-types/string.md). +- `TLD` — Custom TLD list name. [String](../../sql-reference/data-types/string.md). + +**Returned value** + +- Part of the domain that includes top-level subdomains up to the first significant subdomain without stripping `www`. + +Type: [String](../../sql-reference/data-types/string.md). + +**Example** + +Query: + +```sql +SELECT cutToFirstSignificantSubdomainCustomWithWWW('www.foo', 'public_suffix_list'); +``` + +Result: + +```text +┌─cutToFirstSignificantSubdomainCustomWithWWW('www.foo', 'public_suffix_list')─┐ +│ www.foo │ +└──────────────────────────────────────────────────────────────────────────────┘ +``` + +**See Also** + +- [firstSignificantSubdomain](#firstsignificantsubdomain). ### firstSignificantSubdomainCustom {#firstsignificantsubdomaincustom} -Same as `firstSignificantSubdomain` but accept custom TLD list name. +Returns the first significant subdomain. Accepts customs TLD list name. -### cutToFirstSignificantSubdomainCustomWithWWW {#cuttofirstsignificantsubdomaincustomwithwww} +Can be useful if you need fresh TLD list or you have custom. -Same as `cutToFirstSignificantSubdomainWithWWW` but accept custom TLD list name. +Configuration example: + +```xml + + + + public_suffix_list.dat + + +``` + +**Syntax** + +```sql +firstSignificantSubdomainCustom(URL, TLD) +``` + +**Parameters** + +- `URL` — URL. [String](../../sql-reference/data-types/string.md). +- `TLD` — Custom TLD list name. [String](../../sql-reference/data-types/string.md). + +**Returned value** + +- First significant subdomain. + +Type: [String](../../sql-reference/data-types/string.md). + +**Example** + +Query: + +```sql +SELECT firstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list'); +``` + +Result: + +```text +┌─firstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list')─┐ +│ foo │ +└──────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +**See Also** + +- [firstSignificantSubdomain](#firstsignificantsubdomain). ### port(URL\[, default_port = 0\]) {#port} @@ -242,7 +370,7 @@ Extracts network locality (`username:password@host:port`) from a URL. netloc(URL) ``` -**Parameters** +**Arguments** - `url` — URL. [String](../../sql-reference/data-types/string.md). diff --git a/docs/en/sql-reference/functions/ym-dict-functions.md b/docs/en/sql-reference/functions/ym-dict-functions.md index f70532252c7..56530b5e83b 100644 --- a/docs/en/sql-reference/functions/ym-dict-functions.md +++ b/docs/en/sql-reference/functions/ym-dict-functions.md @@ -115,7 +115,7 @@ Finds the highest continent in the hierarchy for the region. regionToTopContinent(id[, geobase]); ``` -**Parameters** +**Arguments** - `id` — Region ID from the Yandex geobase. [UInt32](../../sql-reference/data-types/int-uint.md). - `geobase` — Dictionary key. See [Multiple Geobases](#multiple-geobases). [String](../../sql-reference/data-types/string.md). Optional. diff --git a/docs/en/sql-reference/operators/in.md b/docs/en/sql-reference/operators/in.md index bfa8b3d1003..34866f3d09a 100644 --- a/docs/en/sql-reference/operators/in.md +++ b/docs/en/sql-reference/operators/in.md @@ -13,10 +13,28 @@ SELECT (CounterID, UserID) IN ((34, 123), (101500, 456)) FROM ... If the left side is a single column that is in the index, and the right side is a set of constants, the system uses the index for processing the query. -Don’t list too many values explicitly (i.e. millions). If a data set is large, put it in a temporary table (for example, see the section “External data for query processing”), then use a subquery. +Don’t list too many values explicitly (i.e. millions). If a data set is large, put it in a temporary table (for example, see the section [External data for query processing](../../engines/table-engines/special/external-data.md)), then use a subquery. The right side of the operator can be a set of constant expressions, a set of tuples with constant expressions (shown in the examples above), or the name of a database table or SELECT subquery in brackets. +ClickHouse allows types to differ in the left and the right parts of `IN` subquery. In this case it converts the left side value to the type of the right side, as if the [accurateCastOrNull](../functions/type-conversion-functions.md#type_conversion_function-accurate-cast_or_null) function is applied. That means, that the data type becomes [Nullable](../../sql-reference/data-types/nullable.md), and if the conversion cannot be performed, it returns [NULL](../../sql-reference/syntax.md#null-literal). + +**Example** + +Query: + +``` sql +SELECT '1' IN (SELECT 1); +``` + +Result: + +``` text +┌─in('1', _subquery49)─┐ +│ 1 │ +└──────────────────────┘ +``` + If the right side of the operator is the name of a table (for example, `UserID IN users`), this is equivalent to the subquery `UserID IN (SELECT * FROM users)`. Use this when working with external data that is sent along with the query. For example, the query can be sent together with a set of user IDs loaded to the ‘users’ temporary table, which should be filtered. If the right side of the operator is a table name that has the Set engine (a prepared data set that is always in RAM), the data set will not be created over again for each query. diff --git a/docs/en/sql-reference/statements/alter/column.md b/docs/en/sql-reference/statements/alter/column.md index 0ea4d4b3dc5..16aa266ebf9 100644 --- a/docs/en/sql-reference/statements/alter/column.md +++ b/docs/en/sql-reference/statements/alter/column.md @@ -20,10 +20,12 @@ The following actions are supported: - [ADD COLUMN](#alter_add-column) — Adds a new column to the table. - [DROP COLUMN](#alter_drop-column) — Deletes the column. +- [RENAME COLUMN](#alter_rename-column) — Renames the column. - [CLEAR COLUMN](#alter_clear-column) — Resets column values. - [COMMENT COLUMN](#alter_comment-column) — Adds a text comment to the column. - [MODIFY COLUMN](#alter_modify-column) — Changes column’s type, default expression and TTL. - [MODIFY COLUMN REMOVE](#modify-remove) — Removes one of the column properties. +- [RENAME COLUMN](#alter_rename-column) — Renames an existing column. These actions are described in detail below. @@ -78,6 +80,22 @@ Example: ALTER TABLE visits DROP COLUMN browser ``` +## RENAME COLUMN {#alter_rename-column} + +``` sql +RENAME COLUMN [IF EXISTS] name to new_name +``` + +Renames the column `name` to `new_name`. If the `IF EXISTS` clause is specified, the query won’t return an error if the column doesn’t exist. Since renaming does not involve the underlying data, the query is completed almost instantly. + +**NOTE**: Columns specified in the key expression of the table (either with `ORDER BY` or `PRIMARY KEY`) cannot be renamed. Trying to change these columns will produce `SQL Error [524]`. + +Example: + +``` sql +ALTER TABLE visits RENAME COLUMN webBrowser TO browser +``` + ## CLEAR COLUMN {#alter_clear-column} ``` sql @@ -166,6 +184,22 @@ ALTER TABLE table_with_ttl MODIFY COLUMN column_ttl REMOVE TTL; - [REMOVE TTL](ttl.md). +## RENAME COLUMN {#alter_rename-column} + +Renames an existing column. + +Syntax: + +```sql +ALTER TABLE table_name RENAME COLUMN column_name TO new_column_name; +``` + +**Example** + +```sql +ALTER TABLE table_with_ttl RENAME COLUMN column_ttl TO column_ttl_new; +``` + ## Limitations {#alter-query-limitations} The `ALTER` query lets you create and delete separate elements (columns) in nested data structures, but not whole nested data structures. To add a nested data structure, you can add columns with a name like `name.nested_name` and the type `Array(T)`. A nested data structure is equivalent to multiple array columns with a name that has the same prefix before the dot. diff --git a/docs/en/sql-reference/statements/alter/ttl.md b/docs/en/sql-reference/statements/alter/ttl.md index 5331afdb2f8..e8bfb78ec68 100644 --- a/docs/en/sql-reference/statements/alter/ttl.md +++ b/docs/en/sql-reference/statements/alter/ttl.md @@ -81,5 +81,5 @@ The `TTL` is no longer there, so the second row is not deleted: ### See Also -- More about the [TTL-expression](../../../sql-reference/statements/create/table#ttl-expression). -- Modify column [with TTL](../../../sql-reference/statements/alter/column#alter_modify-column). +- More about the [TTL-expression](../../../../sql-reference/statements/create/table#ttl-expression). +- Modify column [with TTL](../../../../sql-reference/statements/alter/column#alter_modify-column). diff --git a/docs/en/sql-reference/statements/alter/user.md b/docs/en/sql-reference/statements/alter/user.md index efad6561439..b590bf4887d 100644 --- a/docs/en/sql-reference/statements/alter/user.md +++ b/docs/en/sql-reference/statements/alter/user.md @@ -12,10 +12,10 @@ Syntax: ``` sql ALTER USER [IF EXISTS] name1 [ON CLUSTER cluster_name1] [RENAME TO new_name1] [, name2 [ON CLUSTER cluster_name2] [RENAME TO new_name2] ...] - [IDENTIFIED [WITH {PLAINTEXT_PASSWORD|SHA256_PASSWORD|DOUBLE_SHA1_PASSWORD}] BY {'password'|'hash'}] - [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] + [NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']}] + [[ADD | DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] [DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ] - [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] + [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY | WRITABLE] | PROFILE 'profile_name'] [,...] ``` To use `ALTER USER` you must have the [ALTER USER](../../../sql-reference/statements/grant.md#grant-access-management) privilege. diff --git a/docs/en/sql-reference/statements/create/user.md b/docs/en/sql-reference/statements/create/user.md index d5343cce7be..49a4e3813a1 100644 --- a/docs/en/sql-reference/statements/create/user.md +++ b/docs/en/sql-reference/statements/create/user.md @@ -12,10 +12,10 @@ Syntax: ``` sql CREATE USER [IF NOT EXISTS | OR REPLACE] name1 [ON CLUSTER cluster_name1] [, name2 [ON CLUSTER cluster_name2] ...] - [IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH}] BY {'password'|'hash'}] + [NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']}] [HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] [DEFAULT ROLE role [,...]] - [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] + [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY | WRITABLE] | PROFILE 'profile_name'] [,...] ``` `ON CLUSTER` clause allows creating users on a cluster, see [Distributed DDL](../../../sql-reference/distributed-ddl.md). @@ -30,6 +30,8 @@ There are multiple ways of user identification: - `IDENTIFIED WITH sha256_hash BY 'hash'` - `IDENTIFIED WITH double_sha1_password BY 'qwerty'` - `IDENTIFIED WITH double_sha1_hash BY 'hash'` +- `IDENTIFIED WITH ldap SERVER 'server_name'` +- `IDENTIFIED WITH kerberos` or `IDENTIFIED WITH kerberos REALM 'realm'` ## User Host {#user-host} diff --git a/docs/en/sql-reference/statements/create/view.md b/docs/en/sql-reference/statements/create/view.md index 95d66175021..8acd58f4338 100644 --- a/docs/en/sql-reference/statements/create/view.md +++ b/docs/en/sql-reference/statements/create/view.md @@ -41,7 +41,6 @@ SELECT a, b, c FROM (SELECT ...) CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER] [TO[db.]name] [ENGINE = engine] [POPULATE] AS SELECT ... ``` - Materialized views store data transformed by the corresponding [SELECT](../../../sql-reference/statements/select/index.md) query. When creating a materialized view without `TO [db].[table]`, you must specify `ENGINE` – the table engine for storing data. @@ -65,4 +64,191 @@ Views look the same as normal tables. For example, they are listed in the result There isn’t a separate query for deleting views. To delete a view, use [DROP TABLE](../../../sql-reference/statements/drop.md). +## Live View (Experimental) {#live-view} + +!!! important "Important" + This is an experimental feature that may change in backwards-incompatible ways in the future releases. + Enable usage of live views and `WATCH` query using `set allow_experimental_live_view = 1`. + + +```sql +CREATE LIVE VIEW [IF NOT EXISTS] [db.]table_name [WITH [TIMEOUT [value_in_sec] [AND]] [REFRESH [value_in_sec]]] AS SELECT ... +``` + +Live views store result of the corresponding [SELECT](../../../sql-reference/statements/select/index.md) query and are updated any time the result of the query changes. Query result as well as partial result needed to combine with new data are stored in memory providing increased performance for repeated queries. Live views can provide push notifications when query result changes using the [WATCH](../../../sql-reference/statements/watch.md) query. + +Live views are triggered by insert into the innermost table specified in the query. + +Live views work similarly to how a query in a distributed table works. But instead of combining partial results from different servers they combine partial result from current data with partial result from the new data. When a live view query includes a subquery then the cached partial result is only stored for the innermost subquery. + +!!! info "Limitations" + - [Table function](../../../sql-reference/table-functions/index.md) is not supported as the innermost table. + - Tables that do not have inserts such as a [dictionary](../../../sql-reference/dictionaries/index.md), [system table](../../../operations/system-tables/index.md), a [normal view](#normal), or a [materialized view](#materialized) will not trigger a live view. + - Only queries where one can combine partial result from the old data plus partial result from the new data will work. Live view will not work for queries that require the complete data set to compute the final result or aggregations where the state of the aggregation must be preserved. + - Does not work with replicated or distributed tables where inserts are performed on different nodes. + - Can't be triggered by multiple tables. + + See [WITH REFRESH](#live-view-with-refresh) to force periodic updates of a live view that in some cases can be used as a workaround. + +You can watch for changes in the live view query result using the [WATCH](../../../sql-reference/statements/watch.md) query + +```sql +WATCH [db.]live_view +``` + +**Example:** + +```sql +CREATE TABLE mt (x Int8) Engine = MergeTree ORDER BY x; +CREATE LIVE VIEW lv AS SELECT sum(x) FROM mt; +``` + +Watch a live view while doing a parallel insert into the source table. + +```sql +WATCH lv +``` + +```bash +┌─sum(x)─┬─_version─┐ +│ 1 │ 1 │ +└────────┴──────────┘ +┌─sum(x)─┬─_version─┐ +│ 2 │ 2 │ +└────────┴──────────┘ +┌─sum(x)─┬─_version─┐ +│ 6 │ 3 │ +└────────┴──────────┘ +... +``` + +```sql +INSERT INTO mt VALUES (1); +INSERT INTO mt VALUES (2); +INSERT INTO mt VALUES (3); +``` + +or add [EVENTS](../../../sql-reference/statements/watch.md#events-clause) clause to just get change events. + +```sql +WATCH [db.]live_view EVENTS +``` + +**Example:** + +```sql +WATCH lv EVENTS +``` + +```bash +┌─version─┐ +│ 1 │ +└─────────┘ +┌─version─┐ +│ 2 │ +└─────────┘ +┌─version─┐ +│ 3 │ +└─────────┘ +... +``` + +You can execute [SELECT](../../../sql-reference/statements/select/index.md) query on a live view in the same way as for any regular view or a table. If the query result is cached it will return the result immediately without running the stored query on the underlying tables. + +```sql +SELECT * FROM [db.]live_view WHERE ... +``` + +### Force Refresh {#live-view-alter-refresh} + +You can force live view refresh using the `ALTER LIVE VIEW [db.]table_name REFRESH` statement. + +### With Timeout {#live-view-with-timeout} + +When a live view is create with a `WITH TIMEOUT` clause then the live view will be dropped automatically after the specified number of seconds elapse since the end of the last [WATCH](../../../sql-reference/statements/watch.md) query that was watching the live view. + +```sql +CREATE LIVE VIEW [db.]table_name WITH TIMEOUT [value_in_sec] AS SELECT ... +``` + +If the timeout value is not specified then the value specified by the `temporary_live_view_timeout` setting is used. + +**Example:** + +```sql +CREATE TABLE mt (x Int8) Engine = MergeTree ORDER BY x; +CREATE LIVE VIEW lv WITH TIMEOUT 15 AS SELECT sum(x) FROM mt; +``` + +### With Refresh {#live-view-with-refresh} + +When a live view is created with a `WITH REFRESH` clause then it will be automatically refreshed after the specified number of seconds elapse since the last refresh or trigger. + +```sql +CREATE LIVE VIEW [db.]table_name WITH REFRESH [value_in_sec] AS SELECT ... +``` + +If the refresh value is not specified then the value specified by the `periodic_live_view_refresh` setting is used. + +**Example:** + +```sql +CREATE LIVE VIEW lv WITH REFRESH 5 AS SELECT now(); +WATCH lv +``` + +```bash +┌───────────────now()─┬─_version─┐ +│ 2021-02-21 08:47:05 │ 1 │ +└─────────────────────┴──────────┘ +┌───────────────now()─┬─_version─┐ +│ 2021-02-21 08:47:10 │ 2 │ +└─────────────────────┴──────────┘ +┌───────────────now()─┬─_version─┐ +│ 2021-02-21 08:47:15 │ 3 │ +└─────────────────────┴──────────┘ +``` + +You can combine `WITH TIMEOUT` and `WITH REFRESH` clauses using an `AND` clause. + +```sql +CREATE LIVE VIEW [db.]table_name WITH TIMEOUT [value_in_sec] AND REFRESH [value_in_sec] AS SELECT ... +``` + +**Example:** + +```sql +CREATE LIVE VIEW lv WITH TIMEOUT 15 AND REFRESH 5 AS SELECT now(); +``` + +After 15 sec the live view will be automatically dropped if there are no active `WATCH` queries. + +```sql +WATCH lv +``` + +``` +Code: 60. DB::Exception: Received from localhost:9000. DB::Exception: Table default.lv doesn't exist.. +``` + +### Usage + +Most common uses of live view tables include: + +- Providing push notifications for query result changes to avoid polling. +- Caching results of most frequent queries to provide immediate query results. +- Watching for table changes and triggering a follow-up select queries. +- Watching metrics from system tables using periodic refresh. + +### Settings {#live-view-settings} + +You can use the following settings to control the behaviour of live views. + +- `allow_experimental_live_view` - enable live views. Default is `0`. +- `live_view_heartbeat_interval` - the heartbeat interval in seconds to indicate live query is alive. Default is `15` seconds. +- `max_live_view_insert_blocks_before_refresh` - maximum number of inserted blocks after which + mergeable blocks are dropped and query is re-executed. Default is `64` inserts. +- `temporary_live_view_timeout` - interval after which live view with timeout is deleted. Default is `5` seconds. +- `periodic_live_view_refresh` - interval after which periodically refreshed live view is forced to refresh. Default is `60` seconds. + [Original article](https://clickhouse.tech/docs/en/sql-reference/statements/create/view/) diff --git a/docs/en/sql-reference/statements/optimize.md b/docs/en/sql-reference/statements/optimize.md index a67f282e793..9b16a12d2e2 100644 --- a/docs/en/sql-reference/statements/optimize.md +++ b/docs/en/sql-reference/statements/optimize.md @@ -17,7 +17,7 @@ When `OPTIMIZE` is used with the [ReplicatedMergeTree](../../engines/table-engin - If `OPTIMIZE` doesn’t perform a merge for any reason, it doesn’t notify the client. To enable notifications, use the [optimize_throw_if_noop](../../operations/settings/settings.md#setting-optimize_throw_if_noop) setting. - If you specify a `PARTITION`, only the specified partition is optimized. [How to set partition expression](../../sql-reference/statements/alter/index.md#alter-how-to-specify-part-expr). -- If you specify `FINAL`, optimization is performed even when all the data is already in one part. +- If you specify `FINAL`, optimization is performed even when all the data is already in one part. Also merge is forced even if concurrent merges are performed. - If you specify `DEDUPLICATE`, then completely identical rows will be deduplicated (all columns are compared), it makes sense only for the MergeTree engine. !!! warning "Warning" diff --git a/docs/en/sql-reference/statements/select/all.md b/docs/en/sql-reference/statements/select/all.md index 5e0de4c142b..891b82c4319 100644 --- a/docs/en/sql-reference/statements/select/all.md +++ b/docs/en/sql-reference/statements/select/all.md @@ -4,10 +4,8 @@ toc_title: ALL # ALL Clause {#select-all} -`SELECT ALL` is identical to `SELECT` without `DISTINCT`. +If there are multiple matching rows in the table, then `ALL` returns all of them. `SELECT ALL` is identical to `SELECT` without `DISTINCT`. If both `ALL` and `DISTINCT` specified, exception will be thrown. -- If `ALL` specified, ignore it. -- If both `ALL` and `DISTINCT` specified, exception will be thrown. `ALL` can also be specified inside aggregate function with the same effect(noop), for instance: @@ -19,3 +17,5 @@ equals to ```sql SELECT sum(number) FROM numbers(10); ``` + +[Original article](https://clickhouse.tech/docs/en/sql-reference/statements/select/all) diff --git a/docs/en/sql-reference/statements/show.md b/docs/en/sql-reference/statements/show.md index 35631f8c8d6..7b3f709b876 100644 --- a/docs/en/sql-reference/statements/show.md +++ b/docs/en/sql-reference/statements/show.md @@ -428,4 +428,69 @@ errors_count: 0 estimated_recovery_time: 0 ``` -[Original article](https://clickhouse.tech/docs/en/query_language/show/) +## SHOW SETTINGS {#show-settings} + +Returns a list of system settings and their values. Selects data from the [system.settings](../../operations/system-tables/settings.md) table. + +**Syntax** + +```sql +SHOW [CHANGED] SETTINGS LIKE|ILIKE +``` + +**Clauses** + +`LIKE|ILIKE` allow to specify a matching pattern for the setting name. It can contain globs such as `%` or `_`. `LIKE` clause is case-sensitive, `ILIKE` — case insensitive. + +When the `CHANGED` clause is used, the query returns only settings changed from their default values. + +**Examples** + +Query with the `LIKE` clause: + +```sql +SHOW SETTINGS LIKE 'send_timeout'; +``` +Result: + +```text +┌─name─────────┬─type────┬─value─┐ +│ send_timeout │ Seconds │ 300 │ +└──────────────┴─────────┴───────┘ +``` + +Query with the `ILIKE` clause: + +```sql +SHOW SETTINGS ILIKE '%CONNECT_timeout%' +``` + +Result: + +```text +┌─name────────────────────────────────────┬─type─────────┬─value─┐ +│ connect_timeout │ Seconds │ 10 │ +│ connect_timeout_with_failover_ms │ Milliseconds │ 50 │ +│ connect_timeout_with_failover_secure_ms │ Milliseconds │ 100 │ +└─────────────────────────────────────────┴──────────────┴───────┘ +``` + +Query with the `CHANGED` clause: + +```sql +SHOW CHANGED SETTINGS ILIKE '%MEMORY%' +``` + +Result: + +```text +┌─name─────────────┬─type───┬─value───────┐ +│ max_memory_usage │ UInt64 │ 10000000000 │ +└──────────────────┴────────┴─────────────┘ +``` + +**See Also** + +- [system.settings](../../operations/system-tables/settings.md) table + +[Original article](https://clickhouse.tech/docs/en/sql-reference/statements/show/) diff --git a/docs/en/sql-reference/statements/watch.md b/docs/en/sql-reference/statements/watch.md new file mode 100644 index 00000000000..761bc8a041e --- /dev/null +++ b/docs/en/sql-reference/statements/watch.md @@ -0,0 +1,106 @@ +--- +toc_priority: 53 +toc_title: WATCH +--- + +# WATCH Statement (Experimental) {#watch} + +!!! important "Important" + This is an experimental feature that may change in backwards-incompatible ways in the future releases. + Enable live views and `WATCH` query using `set allow_experimental_live_view = 1`. + + +``` sql +WATCH [db.]live_view +[EVENTS] +[LIMIT n] +[FORMAT format] +``` + +The `WATCH` query performs continuous data retrieval from a [live view](./create/view.md#live-view) table. Unless the `LIMIT` clause is specified it provides an infinite stream of query results from a [live view](./create/view.md#live-view). + +```sql +WATCH [db.]live_view +``` + +The virtual `_version` column in the query result indicates the current result version. + +**Example:** + +```sql +CREATE LIVE VIEW lv WITH REFRESH 5 AS SELECT now(); +WATCH lv +``` + +```bash +┌───────────────now()─┬─_version─┐ +│ 2021-02-21 09:17:21 │ 1 │ +└─────────────────────┴──────────┘ +┌───────────────now()─┬─_version─┐ +│ 2021-02-21 09:17:26 │ 2 │ +└─────────────────────┴──────────┘ +┌───────────────now()─┬─_version─┐ +│ 2021-02-21 09:17:31 │ 3 │ +└─────────────────────┴──────────┘ +... +``` + +By default, the requested data is returned to the client, while in conjunction with [INSERT INTO](../../sql-reference/statements/insert-into.md) it can be forwarded to a different table. + +```sql +INSERT INTO [db.]table WATCH [db.]live_view ... +``` + +## EVENTS Clause {#events-clause} + +The `EVENTS` clause can be used to obtain a short form of the `WATCH` query where instead of the query result you will just get the latest query result version. + +```sql +WATCH [db.]live_view EVENTS +``` + +**Example:** + +```sql +CREATE LIVE VIEW lv WITH REFRESH 5 AS SELECT now(); +WATCH lv EVENTS +``` + +```bash +┌─version─┐ +│ 1 │ +└─────────┘ +┌─version─┐ +│ 2 │ +└─────────┘ +... +``` + +## LIMIT Clause {#limit-clause} + +The `LIMIT n` clause species the number of updates the `WATCH` query should wait for before terminating. By default there is no limit on the number of updates and therefore the query will not terminate. The value of `0` indicates that the `WATCH` query should not wait for any new query results and therefore will return immediately once query is evaluated. + +```sql +WATCH [db.]live_view LIMIT 1 +``` + +**Example:** + +```sql +CREATE LIVE VIEW lv WITH REFRESH 5 AS SELECT now(); +WATCH lv EVENTS LIMIT 1 +``` + +```bash +┌─version─┐ +│ 1 │ +└─────────┘ +``` + +## FORMAT Clause {#format-clause} + +The `FORMAT` clause works the same way as for the [SELECT](../../sql-reference/statements/select/format.md#format-clause). + +!!! info "Note" + The [JSONEachRowWithProgress](../../../interfaces/formats/#jsoneachrowwithprogress) format should be used when watching [live view](./create/view.md#live-view) tables over the HTTP interface. The progress messages will be added to the output to keep the long-lived HTTP connection alive until the query result changes. The interval between progress messages is controlled using the [live_view_heartbeat_interval](./create/view.md#live-view-settings) setting. + diff --git a/docs/en/sql-reference/table-functions/file.md b/docs/en/sql-reference/table-functions/file.md index d1eb81e52c6..da0999e66eb 100644 --- a/docs/en/sql-reference/table-functions/file.md +++ b/docs/en/sql-reference/table-functions/file.md @@ -5,7 +5,7 @@ toc_title: file # file {#file} -Creates a table from a file. This table function is similar to [url](../../sql-reference/table-functions/url.md) and [hdfs](../../sql-reference/table-functions/hdfs.md) ones. +Creates a table from a file. This table function is similar to [url](../../sql-reference/table-functions/url.md) and [hdfs](../../sql-reference/table-functions/hdfs.md) ones. `file` function can be used in `SELECT` and `INSERT` queries on data in [File](../../engines/table-engines/special/file.md) tables. @@ -15,9 +15,9 @@ Creates a table from a file. This table function is similar to [url](../../sql-r file(path, format, structure) ``` -**Input parameters** +**Parameters** -- `path` — The relative path to the file from [user_files_path](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-user_files_path). Path to file support following globs in readonly mode: `*`, `?`, `{abc,def}` and `{N..M}` where `N`, `M` — numbers, `'abc', 'def'` — strings. +- `path` — The relative path to the file from [user_files_path](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-user_files_path). Path to file support following globs in read-only mode: `*`, `?`, `{abc,def}` and `{N..M}` where `N`, `M` — numbers, `'abc', 'def'` — strings. - `format` — The [format](../../interfaces/formats.md#formats) of the file. - `structure` — Structure of the table. Format: `'column1_name column1_type, column2_name column2_type, ...'`. @@ -39,7 +39,7 @@ $ cat /var/lib/clickhouse/user_files/test.csv 78,43,45 ``` -Getting data from a table in `test.csv` and selecting first two rows from it: +Getting data from a table in `test.csv` and selecting the first two rows from it: ``` sql SELECT * FROM file('test.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32') LIMIT 2; @@ -51,7 +51,8 @@ SELECT * FROM file('test.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 U │ 3 │ 2 │ 1 │ └─────────┴─────────┴─────────┘ ``` -Getting the first 10 lines of a table that contains 3 columns of UInt32 type from a CSV file: + +Getting the first 10 lines of a table that contains 3 columns of [UInt32](../../sql-reference/data-types/int-uint.md) type from a CSV file: ``` sql SELECT * FROM file('test.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32') LIMIT 10; @@ -71,17 +72,16 @@ SELECT * FROM file('test.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 U └─────────┴─────────┴─────────┘ ``` - ## Globs in Path {#globs-in-path} -Multiple path components can have globs. For being processed file should exists and matches to the whole path pattern (not only suffix or prefix). +Multiple path components can have globs. For being processed file must exist and match to the whole path pattern (not only suffix or prefix). - `*` — Substitutes any number of any characters except `/` including empty string. - `?` — Substitutes any single character. - `{some_string,another_string,yet_another_one}` — Substitutes any of strings `'some_string', 'another_string', 'yet_another_one'`. - `{N..M}` — Substitutes any number in range from N to M including both borders. -Constructions with `{}` are similar to the [remote table function](../../sql-reference/table-functions/remote.md)). +Constructions with `{}` are similar to the [remote](remote.md) table function. **Example** @@ -94,13 +94,13 @@ Suppose we have several files with the following relative paths: - 'another_dir/some_file_2' - 'another_dir/some_file_3' -Query the amount of rows in these files: +Query the number of rows in these files: ``` sql SELECT count(*) FROM file('{some,another}_dir/some_file_{1..3}', 'TSV', 'name String, value UInt32'); ``` -Query the amount of rows in all files of these two directories: +Query the number of rows in all files of these two directories: ``` sql SELECT count(*) FROM file('{some,another}_dir/*', 'TSV', 'name String, value UInt32'); @@ -124,6 +124,6 @@ SELECT count(*) FROM file('big_dir/file{0..9}{0..9}{0..9}', 'CSV', 'name String, **See Also** -- [Virtual columns](https://clickhouse.tech/docs/en/operations/table_engines/#table_engines-virtual_columns) +- [Virtual columns](index.md#table_engines-virtual_columns) [Original article](https://clickhouse.tech/docs/en/sql-reference/table-functions/file/) diff --git a/docs/en/sql-reference/table-functions/generate.md b/docs/en/sql-reference/table-functions/generate.md index 5bbd22dfe4e..be6ba2b8bc4 100644 --- a/docs/en/sql-reference/table-functions/generate.md +++ b/docs/en/sql-reference/table-functions/generate.md @@ -13,7 +13,7 @@ Supports all data types that can be stored in table except `LowCardinality` and generateRandom('name TypeName[, name TypeName]...', [, 'random_seed'[, 'max_string_length'[, 'max_array_length']]]); ``` -**Parameters** +**Arguments** - `name` — Name of corresponding column. - `TypeName` — Type of corresponding column. diff --git a/docs/en/sql-reference/table-functions/mysql.md b/docs/en/sql-reference/table-functions/mysql.md index eec4a1d0c46..7b4e2a301b3 100644 --- a/docs/en/sql-reference/table-functions/mysql.md +++ b/docs/en/sql-reference/table-functions/mysql.md @@ -13,7 +13,7 @@ Allows `SELECT` and `INSERT` queries to be performed on data that is stored on a mysql('host:port', 'database', 'table', 'user', 'password'[, replace_query, 'on_duplicate_clause']) ``` -**Parameters** +**Arguments** - `host:port` — MySQL server address. @@ -44,7 +44,7 @@ The rest of the conditions and the `LIMIT` sampling constraint are executed in C A table object with the same columns as the original MySQL table. !!! info "Note" - In the `INSERT` query to distinguish table function `mysql(...)` from table name with column names list you must use keywords `FUNCTION` or `TABLE FUNCTION`. See examples below. + In the `INSERT` query to distinguish table function `mysql(...)` from table name with column names list, you must use keywords `FUNCTION` or `TABLE FUNCTION`. See examples below. **Examples** diff --git a/docs/en/sql-reference/table-functions/remote.md b/docs/en/sql-reference/table-functions/remote.md index 8af5b588412..e80e58a76aa 100644 --- a/docs/en/sql-reference/table-functions/remote.md +++ b/docs/en/sql-reference/table-functions/remote.md @@ -5,7 +5,7 @@ toc_title: remote # remote, remoteSecure {#remote-remotesecure} -Allows to access remote servers without creating a [Distributed](../../engines/table-engines/special/distributed.md) table. `remoteSecure` - same as `remote` but with secured connection. +Allows to access remote servers without creating a [Distributed](../../engines/table-engines/special/distributed.md) table. `remoteSecure` - same as `remote` but with a secured connection. Both functions can be used in `SELECT` and `INSERT` queries. @@ -18,31 +18,31 @@ remoteSecure('addresses_expr', db, table[, 'user'[, 'password'], sharding_key]) remoteSecure('addresses_expr', db.table[, 'user'[, 'password'], sharding_key]) ``` -**Input parameters** +**Parameters** -- `addresses_expr` – An expression that generates addresses of remote servers. This may be just one server address. The server address is `host:port`, or just `host`. +- `addresses_expr` — An expression that generates addresses of remote servers. This may be just one server address. The server address is `host:port`, or just `host`. The host can be specified as the server name, or as the IPv4 or IPv6 address. An IPv6 address is specified in square brackets. - The port is the TCP port on the remote server. If the port is omitted, it uses [tcp_port](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-tcp_port) from the server’s config file in `remote` (by default, 9000) and [tcp_port_secure](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-tcp_port_secure) in `remoteSecure` (by default, 9440). + The port is the TCP port on the remote server. If the port is omitted, it uses [tcp_port](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-tcp_port) from the server’s config file in `remote` (by default, 9000) and [tcp_port_secure](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-tcp_port_secure) in `remoteSecure` (by default, 9440). The port is required for an IPv6 address. Type: [String](../../sql-reference/data-types/string.md). -- `db` - Database name. Type: [String](../../sql-reference/data-types/string.md). -- `table` - Table name. Type: [String](../../sql-reference/data-types/string.md). -- `user` - User name. If the user is not specified, `default` is used. Type: [String](../../sql-reference/data-types/string.md). -- `password` - User password. If the password is not specified, an empty password is used. Type: [String](../../sql-reference/data-types/string.md). -- `sharding_key` - Sharding key to support distributing data across nodes. For example: `insert into remote('127.0.0.1:9000,127.0.0.2', db, table, 'default', rand())`. Type: [UInt32](../../sql-reference/data-types/int-uint.md). +- `db` — Database name. Type: [String](../../sql-reference/data-types/string.md). +- `table` — Table name. Type: [String](../../sql-reference/data-types/string.md). +- `user` — User name. If the user is not specified, `default` is used. Type: [String](../../sql-reference/data-types/string.md). +- `password` — User password. If the password is not specified, an empty password is used. Type: [String](../../sql-reference/data-types/string.md). +- `sharding_key` — Sharding key to support distributing data across nodes. For example: `insert into remote('127.0.0.1:9000,127.0.0.2', db, table, 'default', rand())`. Type: [UInt32](../../sql-reference/data-types/int-uint.md). **Returned value** -Dataset from remote servers. +The dataset from remote servers. **Usage** -Using the `remote` table function is less optimal than creating a `Distributed` table, because in this case the server connection is re-established for every request. In addition, if host names are set, the names are resolved, and errors are not counted when working with various replicas. When processing a large number of queries, always create the `Distributed` table ahead of time, and don’t use the `remote` table function. +Using the `remote` table function is less optimal than creating a `Distributed` table because in this case the server connection is re-established for every request. Also, if hostnames are set, the names are resolved, and errors are not counted when working with various replicas. When processing a large number of queries, always create the `Distributed` table ahead of time, and don’t use the `remote` table function. The `remote` table function can be useful in the following cases: @@ -62,7 +62,7 @@ localhost [2a02:6b8:0:1111::11]:9000 ``` -Multiple addresses can be comma-separated. In this case, ClickHouse will use distributed processing, so it will send the query to all specified addresses (like to shards with different data). Example: +Multiple addresses can be comma-separated. In this case, ClickHouse will use distributed processing, so it will send the query to all specified addresses (like shards with different data). Example: ``` text example01-01-1,example01-02-1 @@ -82,7 +82,7 @@ example01-{01..02}-1 If you have multiple pairs of curly brackets, it generates the direct product of the corresponding sets. -Addresses and parts of addresses in curly brackets can be separated by the pipe symbol (\|). In this case, the corresponding sets of addresses are interpreted as replicas, and the query will be sent to the first healthy replica. However, the replicas are iterated in the order currently set in the [load_balancing](../../operations/settings/settings.md) setting. This example specifies two shards that each have two replicas: +Addresses and parts of addresses in curly brackets can be separated by the pipe symbol (\|). In this case, the corresponding sets of addresses are interpreted as replicas, and the query will be sent to the first healthy replica. However, the replicas are iterated in the order currently set in the [load_balancing](../../operations/settings/settings.md#settings-load_balancing) setting. This example specifies two shards that each have two replicas: ``` text example01-{01..02}-{1|2} diff --git a/docs/en/sql-reference/table-functions/url.md b/docs/en/sql-reference/table-functions/url.md index d70774b7588..63b0ff0e152 100644 --- a/docs/en/sql-reference/table-functions/url.md +++ b/docs/en/sql-reference/table-functions/url.md @@ -15,25 +15,25 @@ toc_title: url url(URL, format, structure) ``` -**Input parameters** +**Parameters** -- `URL` - HTTP or HTTPS server address, which can accept `GET` (for `SELECT`) or `POST` (for `INSERT`) requests. Type: [String](../../sql-reference/data-types/string.md). -- `format` - [Format](../../interfaces/formats.md#formats) of the data. Type: [String](../../sql-reference/data-types/string.md). -- `structure` - Table structure in `'UserID UInt64, Name String'` format. Determines column names and types. Type: [String](../../sql-reference/data-types/string.md). +- `URL` — HTTP or HTTPS server address, which can accept `GET` or `POST` requests (for `SELECT` or `INSERT` queries correspondingly). Type: [String](../../sql-reference/data-types/string.md). +- `format` — [Format](../../interfaces/formats.md#formats) of the data. Type: [String](../../sql-reference/data-types/string.md). +- `structure` — Table structure in `'UserID UInt64, Name String'` format. Determines column names and types. Type: [String](../../sql-reference/data-types/string.md). **Returned value** -A table with the specified format and structure and with data from the defined URL. +A table with the specified format and structure and with data from the defined `URL`. **Examples** -Getting the first 3 lines of a table that contains columns of `String` and `UInt32` type from HTTP-server which answers in `CSV` format. +Getting the first 3 lines of a table that contains columns of `String` and [UInt32](../../sql-reference/data-types/int-uint.md) type from HTTP-server which answers in [CSV](../../interfaces/formats.md/#csv) format. ``` sql SELECT * FROM url('http://127.0.0.1:12345/', CSV, 'column1 String, column2 UInt32') LIMIT 3; ``` -Inserting data from a URL into a table: +Inserting data from a `URL` into a table: ``` sql CREATE TABLE test_table (column1 String, column2 UInt32) ENGINE=Memory; diff --git a/docs/en/sql-reference/table-functions/view.md b/docs/en/sql-reference/table-functions/view.md index 9997971af65..08096c2b019 100644 --- a/docs/en/sql-reference/table-functions/view.md +++ b/docs/en/sql-reference/table-functions/view.md @@ -13,7 +13,7 @@ Turns a subquery into a table. The function implements views (see [CREATE VIEW]( view(subquery) ``` -**Parameters** +**Arguments** - `subquery` — `SELECT` query. diff --git a/docs/en/sql-reference/window-functions/index.md b/docs/en/sql-reference/window-functions/index.md index 5a6f13226a5..cbf03a44d46 100644 --- a/docs/en/sql-reference/window-functions/index.md +++ b/docs/en/sql-reference/window-functions/index.md @@ -10,33 +10,51 @@ This is an experimental feature that is currently in development and is not read for general use. It will change in unpredictable backwards-incompatible ways in the future releases. Set `allow_experimental_window_functions = 1` to enable it. -ClickHouse currently supports calculation of aggregate functions over a window. -Pure window functions such as `rank`, `lag`, `lead` and so on are not yet supported. +ClickHouse supports the standard grammar for defining windows and window functions. The following features are currently supported: -The window can be specified either with an `OVER` clause or with a separate -`WINDOW` clause. - -Only two variants of frame are supported, `ROWS` and `RANGE`. Offsets for the `RANGE` frame are not yet supported. +| Feature | Support or workaround | +| --------| ----------| +| ad hoc window specification (`count(*) over (partition by id order by time desc)`) | supported | +| expressions involving window functions, e.g. `(count(*) over ()) / 2)` | not supported, wrap in a subquery ([feature request](https://github.com/ClickHouse/ClickHouse/issues/19857)) | +| `WINDOW` clause (`select ... from table window w as (partiton by id)`) | supported | +| `ROWS` frame | supported | +| `RANGE` frame | supported, the default | +| `INTERVAL` syntax for `DateTime` `RANGE OFFSET` frame | not supported, specify the number of seconds instead | +| `GROUPS` frame | not supported | +| Calculating aggregate functions over a frame (`sum(value) over (order by time)`) | all aggregate functions are supported | +| `rank()`, `dense_rank()`, `row_number()` | supported | +| `lag/lead(value, offset)` | not supported, replace with `any(value) over (.... rows between preceding and preceding)`, or `following` for `lead`| ## References ### GitHub Issues + The roadmap for the initial support of window functions is [in this issue](https://github.com/ClickHouse/ClickHouse/issues/18097). All GitHub issues related to window funtions have the [comp-window-functions](https://github.com/ClickHouse/ClickHouse/labels/comp-window-functions) tag. ### Tests + These tests contain the examples of the currently supported grammar: + https://github.com/ClickHouse/ClickHouse/blob/master/tests/performance/window_functions.xml + https://github.com/ClickHouse/ClickHouse/blob/master/tests/queries/0_stateless/01591_window_functions.sql ### Postgres Docs + https://www.postgresql.org/docs/current/sql-select.html#SQL-WINDOW + https://www.postgresql.org/docs/devel/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS + https://www.postgresql.org/docs/devel/functions-window.html + https://www.postgresql.org/docs/devel/tutorial-window.html ### MySQL Docs + https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html + https://dev.mysql.com/doc/refman/8.0/en/window-functions-usage.html + https://dev.mysql.com/doc/refman/8.0/en/window-functions-frames.html diff --git a/docs/ja/commercial/cloud.md b/docs/ja/commercial/cloud.md index 403b34d198c..84f58e46cdb 100644 --- a/docs/ja/commercial/cloud.md +++ b/docs/ja/commercial/cloud.md @@ -20,4 +20,16 @@ toc_title: "\u30AF\u30E9\u30A6\u30C9" - 暗号化と分離 - 自動メンテナンス +## Alibaba Cloud {#alibaba-cloud} + +ClickHouseのためのAlibaba Cloudの管理サービス [中国サイト](https://www.aliyun.com/product/clickhouse) (2021年5月に国際サイトで利用可能になります) 次の主な機能を提供します: + +- Alibaba Cloud Apsara分散システムをベースにした信頼性の高いクラウドディスクストレージエンジン +- 手動でのデータ移行を必要とせずに、オン・デマンドで容量を拡張 +- シングル・ノード、シングル・レプリカ、マルチ・ノード、マルチ・レプリカ・アーキテクチャをサポートし、ホット・データとコールド・データの階層化をサポート +- アクセスホワイトリスト、OneKey Recovery、マルチレイヤーネットワークセキュリティ保護、クラウドディスク暗号化をサポート +- クラウドログシステム、データベース、およびデータアプリケーションツールとのシームレスな統合 +- 組み込み型の監視およびデータベース管理プラットフォーム +- プロフェッショナルデータベースエキスパートによるテクニカル・サポートとサービス + {## [元の記事](https://clickhouse.tech/docs/en/commercial/cloud/) ##} diff --git a/docs/ru/commercial/cloud.md b/docs/ru/commercial/cloud.md index 4f57592b4c7..8023f738c70 100644 --- a/docs/ru/commercial/cloud.md +++ b/docs/ru/commercial/cloud.md @@ -1,6 +1,6 @@ --- toc_priority: 1 -toc_title: "\u041f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0438\u0020\u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445\u0020\u0443\u0441\u043b\u0443\u0433\u0020\u0043\u006c\u0069\u0063\u006b\u0048\u006f\u0075\u0073\u0065" +toc_title: "Поставщики облачных услуг ClickHouse" --- # Поставщики облачных услуг ClickHouse {#clickhouse-cloud-service-providers} diff --git a/docs/ru/commercial/index.md b/docs/ru/commercial/index.md index c6c440c17e8..66b1b125823 100644 --- a/docs/ru/commercial/index.md +++ b/docs/ru/commercial/index.md @@ -1,9 +1,7 @@ --- -toc_folder_title: "\u041A\u043E\u043C\u043C\u0435\u0440\u0447\u0435\u0441\u043A\u0438\ - \u0435 \u0443\u0441\u043B\u0443\u0433\u0438" +toc_folder_title: "Коммерческие услуги" toc_priority: 70 -toc_title: "\u041A\u043E\u043C\u043C\u0435\u0440\u0447\u0435\u0441\u043A\u0438\u0435\ - \ \u0443\u0441\u043B\u0443\u0433\u0438" +toc_title: "Коммерческие услуги" --- # Коммерческие услуги {#clickhouse-commercial-services} diff --git a/docs/ru/development/architecture.md b/docs/ru/development/architecture.md index de8fba1bc4b..9f43fabba4f 100644 --- a/docs/ru/development/architecture.md +++ b/docs/ru/development/architecture.md @@ -1,6 +1,6 @@ --- toc_priority: 62 -toc_title: "\u041e\u0431\u0437\u043e\u0440\u0020\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b\u0020\u0043\u006c\u0069\u0063\u006b\u0048\u006f\u0075\u0073\u0065" +toc_title: "Обзор архитектуры ClickHouse" --- # Обзор архитектуры ClickHouse {#overview-of-clickhouse-architecture} diff --git a/docs/ru/development/browse-code.md b/docs/ru/development/browse-code.md index ac17cf0e6f5..3f6de574abe 100644 --- a/docs/ru/development/browse-code.md +++ b/docs/ru/development/browse-code.md @@ -1,6 +1,6 @@ --- toc_priority: 71 -toc_title: "\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f\u0020\u043f\u043e\u0020\u043a\u043e\u0434\u0443\u0020\u0043\u006c\u0069\u0063\u006b\u0048\u006f\u0075\u0073\u0065" +toc_title: "Навигация по коду ClickHouse" --- diff --git a/docs/ru/development/contrib.md b/docs/ru/development/contrib.md index 05367267e41..f3310836ba9 100644 --- a/docs/ru/development/contrib.md +++ b/docs/ru/development/contrib.md @@ -1,6 +1,6 @@ --- toc_priority: 70 -toc_title: "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435\u0020\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0435\u0020\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438" +toc_title: "Используемые сторонние библиотеки" --- diff --git a/docs/ru/development/developer-instruction.md b/docs/ru/development/developer-instruction.md index 7d88c97fe46..9ddb17b7212 100644 --- a/docs/ru/development/developer-instruction.md +++ b/docs/ru/development/developer-instruction.md @@ -1,6 +1,6 @@ --- toc_priority: 61 -toc_title: "\u0418\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432" +toc_title: "Инструкция для разработчиков" --- # Инструкция для разработчиков diff --git a/docs/ru/development/style.md b/docs/ru/development/style.md index 1b211259bbb..72607ca6bad 100644 --- a/docs/ru/development/style.md +++ b/docs/ru/development/style.md @@ -1,6 +1,6 @@ --- toc_priority: 68 -toc_title: "\u041a\u0430\u043a\u0020\u043f\u0438\u0441\u0430\u0442\u044c\u0020\u043a\u043e\u0434\u0020\u043d\u0430\u0020\u0043\u002b\u002b" +toc_title: "Как писать код на C++" --- diff --git a/docs/ru/engines/database-engines/index.md b/docs/ru/engines/database-engines/index.md index 4dfe766f066..e06c032a636 100644 --- a/docs/ru/engines/database-engines/index.md +++ b/docs/ru/engines/database-engines/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u0414\u0432\u0438\u0436\u043a\u0438\u0020\u0431\u0430\u0437\u0020\u0434\u0430\u043d\u043d\u044b\u0445" +toc_folder_title: "Движки баз данных" toc_priority: 27 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435" +toc_title: "Введение" --- # Движки баз данных {#dvizhki-baz-dannykh} diff --git a/docs/ru/engines/index.md b/docs/ru/engines/index.md index 28ccc8bcfe6..fe41ada8fb6 100644 --- a/docs/ru/engines/index.md +++ b/docs/ru/engines/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0045\u006e\u0067\u0069\u006e\u0065\u0073" +toc_folder_title: "Engines" toc_hidden: true toc_priority: 25 toc_title: hidden diff --git a/docs/ru/engines/table-engines/index.md b/docs/ru/engines/table-engines/index.md index 740588c50a4..05236eb5b33 100644 --- a/docs/ru/engines/table-engines/index.md +++ b/docs/ru/engines/table-engines/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u0414\u0432\u0438\u0436\u043a\u0438\u0020\u0442\u0430\u0431\u043b\u0438\u0446" +toc_folder_title: "Движки таблиц" toc_priority: 26 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435" +toc_title: "Введение" --- diff --git a/docs/ru/engines/table-engines/integrations/index.md b/docs/ru/engines/table-engines/integrations/index.md index db7e527442e..e01d9d0cee2 100644 --- a/docs/ru/engines/table-engines/integrations/index.md +++ b/docs/ru/engines/table-engines/integrations/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0414\u0432\u0438\u0436\u043a\u0438\u0020\u0442\u0430\u0431\u043b\u0438\u0446\u0020\u0434\u043b\u044f\u0020\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438" +toc_folder_title: "Движки таблиц для интеграции" toc_priority: 30 --- diff --git a/docs/ru/engines/table-engines/integrations/kafka.md b/docs/ru/engines/table-engines/integrations/kafka.md index 940fee2452b..5a6971b1ae6 100644 --- a/docs/ru/engines/table-engines/integrations/kafka.md +++ b/docs/ru/engines/table-engines/integrations/kafka.md @@ -31,21 +31,26 @@ SETTINGS [kafka_schema = '',] [kafka_num_consumers = N,] [kafka_skip_broken_messages = N] + [kafka_commit_every_batch = 0,] + [kafka_thread_per_consumer = 0] ``` Обязательные параметры: -- `kafka_broker_list` – перечень брокеров, разделенный запятыми (`localhost:9092`). -- `kafka_topic_list` – перечень необходимых топиков Kafka. -- `kafka_group_name` – группа потребителя Kafka. Отступы для чтения отслеживаются для каждой группы отдельно. Если необходимо, чтобы сообщения не повторялись на кластере, используйте везде одно имя группы. -- `kafka_format` – формат сообщений. Названия форматов должны быть теми же, что можно использовать в секции `FORMAT`, например, `JSONEachRow`. Подробнее читайте в разделе [Форматы](../../../interfaces/formats.md). +- `kafka_broker_list` — перечень брокеров, разделенный запятыми (`localhost:9092`). +- `kafka_topic_list` — перечень необходимых топиков Kafka. +- `kafka_group_name` — группа потребителя Kafka. Отступы для чтения отслеживаются для каждой группы отдельно. Если необходимо, чтобы сообщения не повторялись на кластере, используйте везде одно имя группы. +- `kafka_format` — формат сообщений. Названия форматов должны быть теми же, что можно использовать в секции `FORMAT`, например, `JSONEachRow`. Подробнее читайте в разделе [Форматы](../../../interfaces/formats.md). Опциональные параметры: -- `kafka_row_delimiter` – символ-разделитель записей (строк), которым завершается сообщение. -- `kafka_schema` – опциональный параметр, необходимый, если используется формат, требующий определения схемы. Например, [Cap’n Proto](https://capnproto.org/) требует путь к файлу со схемой и название корневого объекта `schema.capnp:Message`. -- `kafka_num_consumers` – количество потребителей (consumer) на таблицу. По умолчанию: `1`. Укажите больше потребителей, если пропускная способность одного потребителя недостаточна. Общее число потребителей не должно превышать количество партиций в топике, так как на одну партицию может быть назначено не более одного потребителя. -- `kafka_skip_broken_messages` – максимальное количество некорректных сообщений в блоке. Если `kafka_skip_broken_messages = N`, то движок отбрасывает `N` сообщений Кафки, которые не получилось обработать. Одно сообщение в точности соответствует одной записи (строке). Значение по умолчанию – 0. +- `kafka_row_delimiter` — символ-разделитель записей (строк), которым завершается сообщение. +- `kafka_schema` — опциональный параметр, необходимый, если используется формат, требующий определения схемы. Например, [Cap’n Proto](https://capnproto.org/) требует путь к файлу со схемой и название корневого объекта `schema.capnp:Message`. +- `kafka_num_consumers` — количество потребителей (consumer) на таблицу. По умолчанию: `1`. Укажите больше потребителей, если пропускная способность одного потребителя недостаточна. Общее число потребителей не должно превышать количество партиций в топике, так как на одну партицию может быть назначено не более одного потребителя. +- `kafka_max_block_size` — максимальный размер пачек (в сообщениях) для poll (по умолчанию `max_block_size`). +- `kafka_skip_broken_messages` — максимальное количество некорректных сообщений в блоке. Если `kafka_skip_broken_messages = N`, то движок отбрасывает `N` сообщений Кафки, которые не получилось обработать. Одно сообщение в точности соответствует одной записи (строке). Значение по умолчанию – 0. +- `kafka_commit_every_batch` — включает или отключает режим записи каждой принятой и обработанной пачки по отдельности вместо единой записи целого блока (по умолчанию `0`). +- `kafka_thread_per_consumer` — включает или отключает предоставление отдельного потока каждому потребителю (по умолчанию `0`). При включенном режиме каждый потребитель сбрасывает данные независимо и параллельно, при отключённом — строки с данными от нескольких потребителей собираются в один блок. Примеры diff --git a/docs/ru/engines/table-engines/integrations/rabbitmq.md b/docs/ru/engines/table-engines/integrations/rabbitmq.md index dedb5842d68..f55163c1988 100644 --- a/docs/ru/engines/table-engines/integrations/rabbitmq.md +++ b/docs/ru/engines/table-engines/integrations/rabbitmq.md @@ -52,10 +52,26 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] - `rabbitmq_max_block_size` - `rabbitmq_flush_interval_ms` -Требуемая конфигурация: +Настройки форматов данных также могут быть добавлены в списке RabbitMQ настроек. + +Example: + +``` sql + CREATE TABLE queue ( + key UInt64, + value UInt64, + date DateTime + ) ENGINE = RabbitMQ SETTINGS rabbitmq_host_port = 'localhost:5672', + rabbitmq_exchange_name = 'exchange1', + rabbitmq_format = 'JSONEachRow', + rabbitmq_num_consumers = 5, + date_time_input_format = 'best_effort'; +``` Конфигурация сервера RabbitMQ добавляется с помощью конфигурационного файла ClickHouse. +Требуемая конфигурация: + ``` xml root @@ -63,16 +79,12 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ``` -Example: +Дополнительная конфигурация: -``` sql - CREATE TABLE queue ( - key UInt64, - value UInt64 - ) ENGINE = RabbitMQ SETTINGS rabbitmq_host_port = 'localhost:5672', - rabbitmq_exchange_name = 'exchange1', - rabbitmq_format = 'JSONEachRow', - rabbitmq_num_consumers = 5; +``` xml + + clickhouse + ``` ## Описание {#description} @@ -98,6 +110,7 @@ Example: - `consistent_hash` - данные равномерно распределяются между всеми связанными таблицами, где имя точки обмена совпадает. Обратите внимание, что этот тип обмена должен быть включен с помощью плагина RabbitMQ: `rabbitmq-plugins enable rabbitmq_consistent_hash_exchange`. Настройка `rabbitmq_queue_base` может быть использована в следующих случаях: + 1. чтобы восстановить чтение из ранее созданных очередей, если оно прекратилось по какой-либо причине, но очереди остались непустыми. Для восстановления чтения из одной конкретной очереди, нужно написать ее имя в `rabbitmq_queue_base` настройку и не указывать настройки `rabbitmq_num_consumers` и `rabbitmq_num_queues`. Чтобы восстановить чтение из всех очередей, которые были созданы для конкретной таблицы, необходимо совпадение следующих настроек: `rabbitmq_queue_base`, `rabbitmq_num_consumers`, `rabbitmq_num_queues`. По умолчанию, если настройка `rabbitmq_queue_base` не указана, будут использованы уникальные для каждой таблицы имена очередей. 2. чтобы объявить одни и те же очереди для разных таблиц, что позволяет создавать несколько параллельных подписчиков на каждую из очередей. То есть обеспечивается лучшая производительность. В данном случае, для таких таблиц также необходимо совпадение настроек: `rabbitmq_num_consumers`, `rabbitmq_num_queues`. 3. чтобы повторно использовать созданные c `durable` настройкой очереди, так как они не удаляются автоматически (но могут быть удалены с помощью любого RabbitMQ CLI). diff --git a/docs/ru/engines/table-engines/log-family/index.md b/docs/ru/engines/table-engines/log-family/index.md index 7c6d2f81d7c..b2a56f650f4 100644 --- a/docs/ru/engines/table-engines/log-family/index.md +++ b/docs/ru/engines/table-engines/log-family/index.md @@ -1,6 +1,6 @@ --- -toc_folder_title: "\u0421\u0435\u043c\u0435\u0439\u0441\u0442\u0432\u043e\u0020\u004c\u006f\u0067" -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435" +toc_folder_title: "Семейство Log" +toc_title: "Введение" toc_priority: 29 --- diff --git a/docs/ru/engines/table-engines/mergetree-family/custom-partitioning-key.md b/docs/ru/engines/table-engines/mergetree-family/custom-partitioning-key.md index 2d26528d964..00d850b01c3 100644 --- a/docs/ru/engines/table-engines/mergetree-family/custom-partitioning-key.md +++ b/docs/ru/engines/table-engines/mergetree-family/custom-partitioning-key.md @@ -1,6 +1,6 @@ --- toc_priority: 32 -toc_title: "\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439\u0020\u043a\u043b\u044e\u0447\u0020\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f" +toc_title: "Произвольный ключ партиционирования" --- diff --git a/docs/ru/engines/table-engines/mergetree-family/index.md b/docs/ru/engines/table-engines/mergetree-family/index.md index abdfdd77d7f..e184e51c406 100644 --- a/docs/ru/engines/table-engines/mergetree-family/index.md +++ b/docs/ru/engines/table-engines/mergetree-family/index.md @@ -1,5 +1,5 @@ --- toc_folder_title: MergeTree Family toc_priority: 28 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435" +toc_title: "Введение" --- diff --git a/docs/ru/engines/table-engines/mergetree-family/mergetree.md b/docs/ru/engines/table-engines/mergetree-family/mergetree.md index 6fc566b7c31..bc74b2592b9 100644 --- a/docs/ru/engines/table-engines/mergetree-family/mergetree.md +++ b/docs/ru/engines/table-engines/mergetree-family/mergetree.md @@ -56,13 +56,13 @@ ORDER BY expr ClickHouse использует ключ сортировки в качестве первичного ключа, если первичный ключ не задан в секции `PRIMARY KEY`. - Чтобы отключить сортировку, используйте синтаксис `ORDER BY tuple()`. Смотрите [выбор первичного ключа](#vybor-pervichnogo-kliucha). + Чтобы отключить сортировку, используйте синтаксис `ORDER BY tuple()`. Смотрите [выбор первичного ключа](#primary-keys-and-indexes-in-queries). - `PARTITION BY` — [ключ партиционирования](custom-partitioning-key.md). Необязательный параметр. Для партиционирования по месяцам используйте выражение `toYYYYMM(date_column)`, где `date_column` — столбец с датой типа [Date](../../../engines/table-engines/mergetree-family/mergetree.md). В этом случае имена партиций имеют формат `"YYYYMM"`. -- `PRIMARY KEY` — первичный ключ, если он [отличается от ключа сортировки](#pervichnyi-kliuch-otlichnyi-ot-kliucha-sortirovki). Необязательный параметр. +- `PRIMARY KEY` — первичный ключ, если он [отличается от ключа сортировки](#choosing-a-primary-key-that-differs-from-the-sorting-key). Необязательный параметр. По умолчанию первичный ключ совпадает с ключом сортировки (который задаётся секцией `ORDER BY`.) Поэтому в большинстве случаев секцию `PRIMARY KEY` отдельно указывать не нужно. @@ -188,7 +188,7 @@ ClickHouse не требует уникального первичного кл При сортировке с использованием выражения `ORDER BY` для значений `NULL` всегда работает принцип [NULLS_LAST](../../../sql-reference/statements/select/order-by.md#sorting-of-special-values). -### Выбор первичного ключа {#vybor-pervichnogo-kliucha} +### Выбор первичного ключа {#selecting-the-primary-key} Количество столбцов в первичном ключе не ограничено явным образом. В зависимости от структуры данных в первичный ключ можно включать больше или меньше столбцов. Это может: @@ -217,7 +217,7 @@ ClickHouse не требует уникального первичного кл -### Первичный ключ, отличный от ключа сортировки {#pervichnyi-kliuch-otlichnyi-ot-kliucha-sortirovki} +### Первичный ключ, отличный от ключа сортировки {#choosing-a-primary-key-that-differs-from-the-sorting-key} Существует возможность задать первичный ключ (выражение, значения которого будут записаны в индексный файл для каждой засечки), отличный от ключа сортировки (выражение, по которому будут упорядочены строки в кусках @@ -236,7 +236,7 @@ ClickHouse не требует уникального первичного кл [ALTER ключа сортировки](../../../engines/table-engines/mergetree-family/mergetree.md) — лёгкая операция, так как при одновременном добавлении нового столбца в таблицу и ключ сортировки не нужно изменять данные кусков (они остаются упорядоченными и по новому выражению ключа). -### Использование индексов и партиций в запросах {#ispolzovanie-indeksov-i-partitsii-v-zaprosakh} +### Использование индексов и партиций в запросах {#use-of-indexes-and-partitions-in-queries} Для запросов `SELECT` ClickHouse анализирует возможность использования индекса. Индекс может использоваться, если в секции `WHERE/PREWHERE`, в качестве одного из элементов конъюнкции, или целиком, есть выражение, представляющее операции сравнения на равенства, неравенства, а также `IN` или `LIKE` с фиксированным префиксом, над столбцами или выражениями, входящими в первичный ключ или ключ партиционирования, либо над некоторыми частично монотонными функциями от этих столбцов, а также логические связки над такими выражениями. @@ -270,7 +270,7 @@ SELECT count() FROM table WHERE CounterID = 34 OR URL LIKE '%upyachka%' Ключ партиционирования по месяцам обеспечивает чтение только тех блоков данных, которые содержат даты из нужного диапазона. При этом блок данных может содержать данные за многие даты (до целого месяца). В пределах одного блока данные упорядочены по первичному ключу, который может не содержать дату в качестве первого столбца. В связи с этим, при использовании запроса с указанием условия только на дату, но не на префикс первичного ключа, будет читаться данных больше, чем за одну дату. -### Использование индекса для частично-монотонных первичных ключей {#ispolzovanie-indeksa-dlia-chastichno-monotonnykh-pervichnykh-kliuchei} +### Использование индекса для частично-монотонных первичных ключей {#use-of-index-for-partially-monotonic-primary-keys} Рассмотрим, например, дни месяца. Они образуют последовательность [монотонную](https://ru.wikipedia.org/wiki/Монотонная_последовательность) в течение одного месяца, но не монотонную на более длительных периодах. Это частично-монотонная последовательность. Если пользователь создаёт таблицу с частично-монотонным первичным ключом, ClickHouse как обычно создаёт разреженный индекс. Когда пользователь выбирает данные из такого рода таблиц, ClickHouse анализирует условия запроса. Если пользователь хочет получить данные между двумя метками индекса, и обе эти метки находятся внутри одного месяца, ClickHouse может использовать индекс в данном конкретном случае, поскольку он может рассчитать расстояние между параметрами запроса и индексными метками. @@ -312,7 +312,7 @@ SELECT count() FROM table WHERE s < 'z' SELECT count() FROM table WHERE u64 * i32 == 10 AND u64 * length(s) >= 1234 ``` -#### Доступные индексы {#dostupnye-indeksy} +#### Доступные индексы {#available-types-of-indices} - `minmax` — Хранит минимум и максимум выражения (если выражение - `tuple`, то для каждого элемента `tuple`), используя их для пропуска блоков аналогично первичному ключу. @@ -375,7 +375,7 @@ INDEX b (u64 * length(str), i32 + f64 * 100, date, str) TYPE set(100) GRANULARIT - `s != 1` - `NOT startsWith(s, 'test')` -## Конкурентный доступ к данным {#konkurentnyi-dostup-k-dannym} +## Конкурентный доступ к данным {#concurrent-data-access} Для конкурентного доступа к таблице используется мультиверсионность. То есть, при одновременном чтении и обновлении таблицы, данные будут читаться из набора кусочков, актуального на момент запроса. Длинных блокировок нет. Вставки никак не мешают чтениям. @@ -531,13 +531,13 @@ TTL d + INTERVAL 1 MONTH GROUP BY k1, k2 SET x = max(x), y = min(y); ## Хранение данных таблицы на нескольких блочных устройствах {#table_engine-mergetree-multiple-volumes} -### Введение {#vvedenie} +### Введение {#introduction} Движки таблиц семейства `MergeTree` могут хранить данные на нескольких блочных устройствах. Это может оказаться полезным, например, при неявном разделении данных одной таблицы на «горячие» и «холодные». Наиболее свежая часть занимает малый объём и запрашивается регулярно, а большой хвост исторических данных запрашивается редко. При наличии в системе нескольких дисков, «горячая» часть данных может быть размещена на быстрых дисках (например, на NVMe SSD или в памяти), а холодная на более медленных (например, HDD). Минимальной перемещаемой единицей для `MergeTree` является кусок данных (data part). Данные одного куска могут находится только на одном диске. Куски могут перемещаться между дисками в фоне, согласно пользовательским настройкам, а также с помощью запросов [ALTER](../../../engines/table-engines/mergetree-family/mergetree.md#alter_move-partition). -### Термины {#terminy} +### Термины {#terms} - Диск — примонтированное в файловой системе блочное устройство. - Диск по умолчанию — диск, на котором находится путь, указанный в конфигурационной настройке сервера [path](../../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-path). @@ -689,7 +689,7 @@ SETTINGS storage_policy = 'moving_from_ssd_to_hdd' Количество потоков для фоновых перемещений кусков между дисками можно изменить с помощью настройки [background_move_pool_size](../../../operations/settings/settings.md#background_move_pool_size) -### Особенности работы {#osobennosti-raboty} +### Особенности работы {#details} В таблицах `MergeTree` данные попадают на диск несколькими способами: @@ -712,4 +712,99 @@ SETTINGS storage_policy = 'moving_from_ssd_to_hdd' После выполнения фоновых слияний или мутаций старые куски не удаляются сразу, а через некоторое время (табличная настройка `old_parts_lifetime`). Также они не перемещаются на другие тома или диски, поэтому до момента удаления они продолжают учитываться при подсчёте занятого дискового пространства. +## Использование сервиса S3 для хранения данных {#table_engine-mergetree-s3} + +Таблицы семейства `MergeTree` могут хранить данные в сервисе [S3](https://aws.amazon.com/s3/) при использовании диска типа `s3`. + +Конфигурация: + +``` xml + + ... + + + s3 + https://storage.yandexcloud.net/my-bucket/root-path/ + your_access_key_id + your_secret_access_key + + http://proxy1 + http://proxy2 + + 10000 + 5000 + 100 + 10 + 1000 + /var/lib/clickhouse/disks/s3/ + true + /var/lib/clickhouse/disks/s3/cache/ + false + + + ... + +``` + +Обязательные параметры: + +- `endpoint` — URL точки приема запроса на стороне S3 в [форматах](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html) `path` или `virtual hosted`. URL точки должен содержать бакет и путь к корневой директории на сервере, где хранятся данные. +- `access_key_id` — id ключа доступа к S3. +- `secret_access_key` — секретный ключ доступа к S3. + +Необязательные параметры: + +- `use_environment_credentials` — признак, нужно ли считывать учетные данные AWS из переменных окружения `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` и `AWS_SESSION_TOKEN`, если они есть. Значение по умолчанию: `false`. +- `proxy` — конфигурация прокси-сервера для конечной точки S3. Каждый элемент `uri` внутри блока `proxy` должен содержать URL прокси-сервера. +- `connect_timeout_ms` — таймаут подключения к сокету в миллисекундах. Значение по умолчанию: 10 секунд. +- `request_timeout_ms` — таймаут выполнения запроса в миллисекундах. Значение по умолчанию: 5 секунд. +- `max_connections` — размер пула соединений S3. Значение по умолчанию: `100`. +- `retry_attempts` — число попыток выполнения запроса в случае возникновения ошибки. Значение по умолчанию: `10`. +- `min_bytes_for_seek` — минимальное количество байтов, которые используются для операций поиска вместо последовательного чтения. Значение по умолчанию: 1 МБайт. +- `metadata_path` — путь к локальному файловому хранилищу для хранения файлов с метаданными для S3. Значение по умолчанию: `/var/lib/clickhouse/disks//`. +- `cache_enabled` — признак, разрешено ли хранение кэша засечек и файлов индекса в локальной файловой системе. Значение по умолчанию: `true`. +- `cache_path` — путь в локальной файловой системе, где будут храниться кэш засечек и файлы индекса. Значение по умолчанию: `/var/lib/clickhouse/disks//cache/`. +- `skip_access_check` — признак, выполнять ли проверку доступов при запуске диска. Если установлено значение `true`, то проверка не выполняется. Значение по умолчанию: `false`. + + +Диск S3 может быть сконфигурирован как `main` или `cold`: + +``` xml + + ... + + + s3 + https://storage.yandexcloud.net/my-bucket/root-path/ + your_access_key_id + your_secret_access_key + + + + + +
+ s3 +
+
+
+ + +
+ default +
+ + s3 + +
+ 0.2 +
+
+ ... +
+``` + +Если диск сконфигурирован как `cold`, данные будут переноситься в S3 при срабатывании правил TTL или когда свободное место на локальном диске станет меньше порогового значения, которое определяется как `move_factor * disk_size`. + + [Оригинальная статья](https://clickhouse.tech/docs/ru/engines/table-engines/mergetree-family/mergetree/) diff --git a/docs/ru/engines/table-engines/mergetree-family/replication.md b/docs/ru/engines/table-engines/mergetree-family/replication.md index a8a308b104f..1735a02cf4c 100644 --- a/docs/ru/engines/table-engines/mergetree-family/replication.md +++ b/docs/ru/engines/table-engines/mergetree-family/replication.md @@ -1,6 +1,6 @@ --- toc_priority: 31 -toc_title: "\u0420\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f\u0020\u0434\u0430\u043d\u043d\u044b\u0445" +toc_title: "Репликация данных" --- # Репликация данных {#table_engines-replication} diff --git a/docs/ru/engines/table-engines/special/external-data.md b/docs/ru/engines/table-engines/special/external-data.md index 7e383c0c12d..da9e132dd4f 100644 --- a/docs/ru/engines/table-engines/special/external-data.md +++ b/docs/ru/engines/table-engines/special/external-data.md @@ -1,6 +1,6 @@ --- toc_priority: 45 -toc_title: "\u0412\u043d\u0435\u0448\u043d\u0438\u0435\u0020\u0434\u0430\u043d\u043d\u044b\u0435\u0020\u0434\u043b\u044f\u0020\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438\u0020\u0437\u0430\u043f\u0440\u043e\u0441\u0430" +toc_title: "Внешние данные для обработки запроса" --- # Внешние данные для обработки запроса {#vneshnie-dannye-dlia-obrabotki-zaprosa} diff --git a/docs/ru/engines/table-engines/special/file.md b/docs/ru/engines/table-engines/special/file.md index 6a55ef31732..9be09fd33e6 100644 --- a/docs/ru/engines/table-engines/special/file.md +++ b/docs/ru/engines/table-engines/special/file.md @@ -63,7 +63,7 @@ SELECT * FROM file_engine_table ## Использование движка в Clickhouse-local {#ispolzovanie-dvizhka-v-clickhouse-local} -В [clickhouse-local](../../../engines/table-engines/special/file.md) движок в качестве параметра принимает не только формат, но и путь к файлу. В том числе можно указать стандартные потоки ввода/вывода цифровым или буквенным обозначением `0` или `stdin`, `1` или `stdout`. +В [clickhouse-local](../../../engines/table-engines/special/file.md) движок в качестве параметра принимает не только формат, но и путь к файлу. В том числе можно указать стандартные потоки ввода/вывода цифровым или буквенным обозначением `0` или `stdin`, `1` или `stdout`. Можно записывать и читать сжатые файлы. Для этого нужно задать дополнительный параметр движка или расширение файла (`gz`, `br` или `xz`). **Пример:** diff --git a/docs/ru/engines/table-engines/special/index.md b/docs/ru/engines/table-engines/special/index.md index 0d86461dd2d..0300d3ad641 100644 --- a/docs/ru/engines/table-engines/special/index.md +++ b/docs/ru/engines/table-engines/special/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435\u0020\u0434\u0432\u0438\u0436\u043a\u0438\u0020\u0442\u0430\u0431\u043b\u0438\u0446" +toc_folder_title: "Специальные движки таблиц" toc_priority: 31 --- diff --git a/docs/ru/faq/general/columnar-database.md b/docs/ru/faq/general/columnar-database.md new file mode 100644 index 00000000000..f38e46cfe93 --- /dev/null +++ b/docs/ru/faq/general/columnar-database.md @@ -0,0 +1,25 @@ +--- +title: Что такое столбцовая база данных? +toc_hidden: true +toc_priority: 101 +--- + +# Что такое столбцовая (колоночная) база данных? {#what-is-a-columnar-database} + +В столбцовой БД данные каждого столбца хранятся отдельно (независимо) от других столбцов. Такой принцип хранения позволяет при выполнении запроса считывать с диска данные только тех столбцов, которые непосредственно участвуют в этом запросе. Обратная сторона такого принципа хранения заключается в том, что выполнение операций над строками становится более затратным. ClickHouse — типичный пример столбцовой СУБД. + +Ключевые преимущества столбцовой СУБД: + +- выполнение запросов над отдельными столбцами таблицы, а не над всей таблицей сразу; +- агрегация запросов на больших объемах данных; +- сжатие данных в столбцах. + +Ниже — иллюстрация того, как извлекаются данные для отчетов при использовании обычной строковой СУБД и столбцовой СУБД: + +**Стандартная строковая СУБД** +![Стандартная строковая СУБД](https://clickhouse.tech/docs/en/images/row-oriented.gif#) + +**Столбцовая СУБД** +![Столбцовая СУБД](https://clickhouse.tech/docs/en/images/column-oriented.gif#) + +Для аналитических приложений столбцовые СУБД предпочтительнее, так как в них можно хранить много столбцов в таблице просто на всякий случай, и это не будет сказываться на скорости чтения данных. Столбцовые СУБД предназначены для обработки и хранения больших данных. Они прекрасно масштабируются при помощи распределенных кластеров на относительно недорогих серверах — для увеличения производительности. В ClickHouse для этого используются [распределенные](../../engines/table-engines/special/distributed.md) и [реплицированные](../../engines/table-engines/mergetree-family/replication.md) таблицы. diff --git a/docs/ru/faq/general/dbms-naming.md b/docs/ru/faq/general/dbms-naming.md new file mode 100644 index 00000000000..2611daeffcc --- /dev/null +++ b/docs/ru/faq/general/dbms-naming.md @@ -0,0 +1,17 @@ +--- +title: "Что означает название ClickHouse?" +toc_hidden: true +toc_priority: 10 +--- + +# Что означает название ClickHouse? {#what-does-clickhouse-mean} + +Это комбинация терминов **Click**stream и Data ware**House**. Название пришло из Яндекс.Метрики, для которой первоначально был разработан ClickHouse — там он использовался для хранения истории визитов пользователей на сайты и всех пользовательских действий — "кликов". Кстати, ClickHouse по-прежнему выполняет эту функцию. Узнать об этом больше можно на странице [истории ClickHouse](../../introduction/history.md). + +Поскольку название составное, использовать его нужно следующим образом: + +- единственно правильный способ написания — Click**H**ouse — с заглавной буквой H; +- если нужно сокращеннное название, используйте **CH**. Исторически сложилось, что в Китае также популярно сокращение CK — в основном, из-за того, что это название использовалось в одном из первых обсуждений ClickHouse на китайском языке. + +!!! info "Забавный факт" + Спустя годы после того, как ClickHouse получил свое название, принцип комбинирования двух слов, каждое из которых имеет подходящий смысл, был признан лучшим способом назвать базу данных в [исследовании Andy Pavlo](https://www.cs.cmu.edu/~pavlo/blog/2020/03/on-naming-a-database-management-system.html), Associate Professor of Databases в Carnegie Mellon University. ClickHouse разделил награду "за лучшее название СУБД" с Postgres. diff --git a/docs/ru/faq/general/index.md b/docs/ru/faq/general/index.md index cf0f8451450..cf105eaf8bb 100644 --- a/docs/ru/faq/general/index.md +++ b/docs/ru/faq/general/index.md @@ -1,25 +1,24 @@ --- -title: General questions about ClickHouse +title: Общие вопросы о ClickHouse toc_hidden_folder: true toc_priority: 1 toc_title: Общие вопросы --- -# Общие вопросы о ClickHouse {#obshchie-voprosy} +# Общие вопросы о ClickHouse {#general-questions} Вопросы: -- Что такое ClickHouse? -- Почему ClickHouse такой быстрый? -- Кто пользуется ClickHouse? -- Что обозначает название “ClickHouse”? -- Что значит “Не тормозит”? -- Что такое OLAP? -- Что такое колоночная база данных? +- [Что такое ClickHouse?](../../index.md#what-is-clickhouse) +- [Почему ClickHouse такой быстрый?](why-clickhouse-is-so-fast.md) +- [Кто пользуется ClickHouse?](who-is-using-clickhouse.md) +- [Что обозначает название ClickHouse?](dbms-naming.md) +- [Как фраза “Не тормозит” осталась на всех футболках?](ne-tormozit.md) +- [Что такое OLAP?](olap.md) +- [Что такое столбцовая база данных?](columnar-database.md) - [Почему бы не использовать системы типа MapReduce?](mapreduce.md) !!! info "Если вы не нашли то, что искали:" - Загляните в другие категории F.A.Q. или поищите в других разделах документации, ориентируйтесь по оглавлению слева. - -{## [Original article](https://clickhouse.tech/docs/ru/faq/general/) ##} + Загляните в другие категории F.A.Q. или поищите в остальных разделах документации, ориентируясь по оглавлению слева. +[Original article](https://clickhouse.tech/docs/ru/faq/general/) diff --git a/docs/ru/faq/general/mapreduce.md b/docs/ru/faq/general/mapreduce.md index 645391493c3..8a524c9f680 100644 --- a/docs/ru/faq/general/mapreduce.md +++ b/docs/ru/faq/general/mapreduce.md @@ -4,13 +4,10 @@ toc_hidden: true toc_priority: 110 --- -## Почему бы не использовать системы типа MapReduce? {#pochemu-by-ne-ispolzovat-sistemy-tipa-mapreduce} +# Почему бы не использовать системы типа MapReduce? {#why-not-use-something-like-mapreduce} -Системами типа MapReduce будем называть системы распределённых вычислений, в которых операция reduce сделана на основе распределённой сортировки. Наиболее распространённым opensource решением данного класса является [Apache Hadoop](http://hadoop.apache.org). Яндекс использует собственное решение — YT. +Системами типа MapReduce будем называть системы распределённых вычислений, в которых операция свёртки реализована на основе распределённой сортировки. Наиболее распространённое решение с открытым кодом в данном классе — [Apache Hadoop](http://hadoop.apache.org). Яндекс пользуется собственным решением — YT. -Такие системы не подходят для онлайн запросов в силу слишком большой latency. То есть, не могут быть использованы в качестве бэкенда для веб-интерфейса. -Такие системы не подходят для обновления данных в реальном времени. -Распределённая сортировка не является оптимальным способом выполнения операции reduce, если результат выполнения операции и все промежуточные результаты, при их наличии, помещаются в оперативку на одном сервере, как обычно бывает в запросах, выполняющихся в режиме онлайн. В таком случае, оптимальным способом выполнения операции reduce является хэш-таблица. Частым способом оптимизации map-reduce задач является предагрегация (частичный reduce) с использованием хэш-таблицы в оперативной памяти. Эта оптимизация делается пользователем в ручном режиме. -Распределённая сортировка является основной причиной тормозов при выполнении несложных map-reduce задач. +Такие системы не подходят для онлайн запросов в силу слишком большой задержки. То есть не могут быть использованы в качестве бэкенда для веб-интерфейса. Также эти системы не подходят для обновления данных в реальном времени. Распределённая сортировка является не оптимальным способом для выполнения операции свёртки в случае запросов, выполняющихся в режиме онлайн, потому что результат выполнения операции и все промежуточные результаты (если такие есть) помещаются в оперативную память на одном сервере. В таком случае оптимальным способом выполнения операции свёртки является хеш-таблица. Частым способом оптимизации "map-reduce" задач является предагрегация (частичная свёртка) с использованием хеш-таблицы в оперативной памяти. Пользователь делает эту оптимизацию в ручном режиме. Распределённая сортировка — основная причина тормозов при выполнении несложных задач типа "map-reduce". -Большинство реализаций MapReduce позволяют выполнять произвольный код на кластере. Но для OLAP задач лучше подходит декларативный язык запросов, который позволяет быстро проводить исследования. Для примера, для Hadoop существует Hive и Pig. Также смотрите Cloudera Impala, Shark (устаревший) для Spark, а также Spark SQL, Presto, Apache Drill. Впрочем, производительность при выполнении таких задач является сильно неоптимальной по сравнению со специализированными системами, а сравнительно высокая latency не позволяет использовать эти системы в качестве бэкенда для веб-интерфейса. +Большинство реализаций MapReduce позволяют выполнять произвольный код на кластере. Но для OLAP-задач лучше подходит декларативный язык запросов, который позволяет быстро проводить исследования. Например, для Hadoop существуют Hive и Pig. Также посмотрите на Cloudera Impala, Shark (устаревший) для Spark, а также Spark SQL, Presto, Apache Drill. Впрочем, производительность при выполнении таких задач очень неоптимальная, если сравнивать со специализированными системами, а относительно высокая задержка не позволяет использовать эти системы в качестве бэкенда для веб-интерфейса. diff --git a/docs/ru/faq/general/ne-tormozit.md b/docs/ru/faq/general/ne-tormozit.md new file mode 100644 index 00000000000..1230e34c475 --- /dev/null +++ b/docs/ru/faq/general/ne-tormozit.md @@ -0,0 +1,25 @@ +--- +title: "What does “не тормозит” mean?" +toc_hidden: true +toc_priority: 11 +--- + +# Что значит “Не тормозит”? {#what-does-ne-tormozit-mean} + +Обычно этот вопрос возникает, когда люди видят официальные футболки ClickHouse. На них большими буквами написано **“ClickHouse не тормозит”**. + +До того, как код ClickHouse стал открытым, его разрабатывали как собственную систему хранения данных в крупнейшей российской ИТ-компании [Яндекс](https://yandex.com/company/). Поэтому оригинальный слоган написан по-русски. После выхода версии с открытым исходным кодом мы впервые выпустили некоторое количество таких футболок для мероприятий в России, и просто оставили прежний слоган. + +Когда мы решили отправить партию этих футболок на мероприятия вне России, мы пробовали подобрать подходящий английский слоган. К сожалению, мы так и не смогли придумать достаточно точный и выразительный перевод, ведь на русском этот слоган звучит очень ёмко и при этом довольно элегантно. К тому же, существовало ограничение по количеству символов на футболках. В итоге мы решили оставить русский вариант даже для международных событий. И это стало прекрасным решением, потому что люди по всему миру приятно удивлялись, когда видели фразу и интересовались, что же там написано. + +Итак, как же объяснить эту фразу на английском? Вот несколько вариантов: + +- Если переводить буквально, то получится что-то подобное: *“ClickHouse doesn’t press the brake pedal”*. +- Если же вы хотите максимально сохранить том смысл, который вкладывает в эту фразу человек из ИТ-сферы, то будет примерно следующее: *“If your larger system lags, it’s not because it uses ClickHouse”*. +- Более короткие, но не такие точные версии: *“ClickHouse is not slow”*, *“ClickHouse doesn’t lag”* или просто *“ClickHouse is fast”*. + +Если вы не видели наших футболок, посмотрите видео о ClickHouse. Например, вот это: + +![iframe](https://www.youtube.com/embed/bSyQahMVZ7w) + +P.S. Эти футболки не продаются, а распространяются бесплатно на большинстве митапов [ClickHouse](https://clickhouse.tech/#meet), обычно в награду за самые интересные вопросы или другие виды активного участия. diff --git a/docs/ru/faq/general/olap.md b/docs/ru/faq/general/olap.md new file mode 100644 index 00000000000..9dce0ffbdf7 --- /dev/null +++ b/docs/ru/faq/general/olap.md @@ -0,0 +1,39 @@ +--- +title: Что такое OLAP? +toc_hidden: true +toc_priority: 100 +--- + +# Что такое OLAP? {#what-is-olap} + +[OLAP](https://ru.wikipedia.org/wiki/OLAP) (OnLine Analytical Processing) переводится как обработка данных в реальном времени. Это широкий термин, который можно рассмотреть с двух сторон: с технической и с точки зрения бизнеса. Для самого общего понимания можно просто прочитать его с конца: + +**Processing** + Обрабатываются некие исходные данные… + +**Analytical** +: … чтобы получить какие-то аналитические отчеты или новые знания… + +**OnLine** +: … в реальном времени, практически без задержек на обработку. + +## OLAP с точки зрения бизнеса {#olap-from-the-business-perspective} + +В последние годы бизнес-сообщество стало осознавать ценность данных. Компании, которые принимают решения вслепую, чаще всего отстают от конкурентов. Управление бизнесом на основе данных, которое применяется успешными компаниями, побуждает собирать все данные, которые могут быть полезны в будущем для принятия бизнес-решений, а также подбирать механизмы, чтобы своевременно эти данные анализировать. Именно для этого и нужны СУБД с OLAP. + +С точки зрения бизнеса, OLAP позволяет компаниям постоянно планировать, анализировать и оценивать операционную деятельность, чтобы повышать её эффективность, уменьшать затраты и как следствие — увеличивать долю рынка. Это можно делать как в собственной системе, так и в облачной (SaaS), в веб или мобильных аналитических приложениях, CRM-системах и т.д. Технология OLAP используется во многих приложениях BI (Business Intelligence — бизнес-аналитика). + +ClickHouse — это СУБД с OLAP, которая часто используется для поддержки SaaS-решений для анализа данных в различных предметных областях. Но поскольку некоторые компании все еще не слишком охотно размещают свои данные в облаке (у сторонних провайдеров), ClickHouse может быть развернут и на собственных серверах заказчика. + +## OLAP с технической точки зрения {#olap-from-the-technical-perspective} + +Все СУБД можно разделить на две группы: OLAP (**аналитическая** обработка в реальном времени) и OLTP (обработка **транзакций** в реальном времени). OLAP используются для построения отчетов на основе больших объемов накопленных исторических данных, но эти отчеты обновляются не слишком часто. OLTP обычно применяются для обработки непрерывных потоков операций (транзакций), каждая из которых изменяет состояние данных. + +На практике OLAP и OLTP — это не строго разделённые категории, а скорее спектр возможностей. Большинство СУБД специализируются на каком-то одном виде обработки данных, но имеют инструменты и для выполнения других операций, когда это необходимо. Из-за такой специализации часто приходится использовать несколько СУБД и интегрировать их между собой. Это вполне реальная и решаемая задача, но, как известно, чем больше систем, тем выше расходы на их содержание. Поэтому в последние годы становятся популярны гибридные СУБД — HTAP (**Hybrid Transactional/Analytical Processing**), которые одинаково эффективно выполняют оба вида операций по обработке данных. + +Даже если СУБД сначала развивались исключительно как OLAP или как OLTP, разработчики постепенно двигаются в сторону HTAP, чтобы сохранять конкурентоспособность. И ClickHouse не исключение. Изначально он создавался как [OLAP СУБД с максимальной производительностью](../../faq/general/why-clickhouse-is-so-fast.md), и на сегодняшний день в нем нет полноценной поддержки обработки тразакций, но уже реализованы некоторые возможности, такие как постоянная скорость чтения/записи данных и мутации при изменении/удалении данных. + +Принципиальное "разделение труда" между OLAP и OLTP СУБД сохраняется: + +- Чтобы эффективно строить аналитические отчеты, нужно уметь обрабатывать колонки по отдельности, поэтому большинство OLAP СУБД — [столбцовые](../../faq/general/columnar-database.md). +- Хранение данных по столбцам снижает скорость выполнения операций над строками (таких как добавление или изменение данных) пропорционально числу столбцов, а это число может быть огромным для систем, ориентированных на сбор разнообразных детальных данных о событиях. Поэтому большинство OLTP систем используют строковые СУБД. diff --git a/docs/ru/faq/general/who-is-using-clickhouse.md b/docs/ru/faq/general/who-is-using-clickhouse.md new file mode 100644 index 00000000000..02a4d198deb --- /dev/null +++ b/docs/ru/faq/general/who-is-using-clickhouse.md @@ -0,0 +1,19 @@ +--- +title: Кто пользуется ClickHouse? +toc_hidden: true +toc_priority: 9 +--- + +# Кто пользуется ClickHouse? {#who-is-using-clickhouse} + +Так как CH является продуктом с открытым исходным кодом, на этот вопрос не так просто ответить. Вы не должны сообщать кому-либо о том, что вы начали пользоваться ClickHouse, достаточно взять исходный код или предкомпилированный установочный пакет. Не нужно подписывать контракт, а [лицензия Apache 2.0](https://github.com/ClickHouse/ClickHouse/blob/master/LICENSE) позволяет распространять ПО без ограничений. + +Кроме того, стек используемых технологий часто не раскрывается из-за NDA. Некоторые компании рассматривают технологии, которыми пользуются, как своё конкурентное преимущество, даже если это продукты с открытым исходным кодом. Такие компании не позволяют сотрудникам рассказывать о том, с каким ПО они работают, или требуют согласовывать это с PR-отделом. + +Итак, как же узнать, кто пользуется ClickHouse? + +Один из способов — **поспрашивать в своем окружении**. В разговорах люди более охотно делятся тем, какие технологии внедрены в их компаниях, какие задачи решаются с их помощью, могут назвать характеристики аппаратного обеспечения, объемы данных и т.д. Мы регулярно разговариваем с пользователями во время [митапов ClickHouse](https://www.youtube.com/channel/UChtmrD-dsdpspr42P_PyRAw/playlists) по всему миру и слышали о более чем 1000 компаний, которые пользуются ClickHouse. К сожалению, мы не можем раскрывать подробности, потому что по умолчанию считаем такие истории защищенными NDA, чтобы избежать любых возможных проблем. Вы можете прийти на любой из наших будущих митапов и самостоятельно поговорить с другими пользователями. Мы анонсируем события по разным каналам, например, вы можете подписаться на [наш Twitter](http://twitter.com/ClickHouseDB/). + +Второй способ узнать — посмотреть, что компании **говорят публично** о том, как именно они пользуются ClickHouse. Это более существенная информация, потому что ее можно найти в публикациях в блогах, видеозаписях разговоров, презентациях и т.д. Мы собираем ссылки на такие материалы на своей странице **[Пользователи ClickHouse](../../introduction/adopters.md)**. Будем рады, если вы поделитесь историей вашей компании или ссылками по теме (но всегда помните о том, что не стоит нарушать NDA). + +В числе пользователей есть множество очень крупных компаний, знакомых вам, таких как Bloomberg, Cisco, China Telecom, Tencent или Uber, но на самом деле это далеко не полный перечень. К примеру, если вы возьмете [список Forbes крупнейших ИТ-компаний в 2020](https://www.forbes.com/sites/hanktucker/2020/05/13/worlds-largest-technology-companies-2020-apple-stays-on-top-zoom-and-uber-debut/), то увидите, что более половины из этих компаний так или иначе пользуются ClickHouse. Также необходимо упомянуть Яндекс — компанию, которая открыла исходный код ClickHouse в 2016 году и является одной из самых крупных ИТ-компаний в Европе. diff --git a/docs/ru/faq/general/why-clickhouse-is-so-fast.md b/docs/ru/faq/general/why-clickhouse-is-so-fast.md new file mode 100644 index 00000000000..694488b40a9 --- /dev/null +++ b/docs/ru/faq/general/why-clickhouse-is-so-fast.md @@ -0,0 +1,63 @@ +--- +title: Почему ClickHouse так быстро работает? +toc_hidden: true +toc_priority: 8 +--- + +# Почему ClickHouse так быстро работает? {#why-clickhouse-is-so-fast} + +Производительность изначально заложена в архитектуре ClickHouse. Высокая скорость выполнения запросов была и остается самым важным критерием, который учитывается при разработке. Но мы обращаем внимание и на другие характеристики, такие как удобство использования, масштабируемость, безопасность. Всё это делает ClickHouse настоящей промышленной разработкой. + +Сначала ClickHouse создавался как прототип, который должен был отлично справляться с одной единственной задачей — отбирать и агрегировать данные с максимальной скоростью. Это необходимо, чтобы создать обычный аналитический отчет, и именно это делает стандартный запрос [GROUP BY](../../sql-reference/statements/select/group-by.md). Для решения такой задачи команда разработки ClickHouse приняла несколько архитектурных решений: + +Столбцовое хранение данных +: Исходные данные часто содержат сотни или даже тысячи столбцов, в то время как для конкретного отчета нужны только несколько из них. Система не должна читать ненужные столбцы, поскольку операции чтения данных с диска — самые дорогостоящие. + +Индексы +: ClickHouse хранит структуры данных в оперативной памяти, что позволяет считывать не только нужные столбцы, но и нужные диапазоны строк для этих столбцов. + +Сжатие данных +: Различные способы хранения смежных значений в столбце позволяют достигать более высокой степени сжатия данных (по сравнению с обычными строковыми СУБД), т.к. в смежных строках значения часто бывают одинаковыми или близкими. В дополнение к универсальному сжатию ClickHouse поддерживает [специализированные кодеки](../../sql-reference/statements/create/table.md#create-query-specialized-codecs), которые позволяют еще больше уменьшить объемы хранимых данных. + +Векторные запросы +: ClickHouse не только хранит, но и обрабатывает данные в столбцах. Это приводит к лучшей утилизации кеша процессора и позволяет использовать инструкции [SIMD](https://en.wikipedia.org/wiki/SIMD). + +Масштабируемость +: ClickHouse может задействовать все доступные мощности процессоров и объемы дисков, чтобы выполнить даже одиночный запрос. Не только на отдельном сервере, но и в целом кластере. + +Похожие техники используют и многие другие СУБД. **Внимание к мельчайшим деталям** — вот что на самом деле выделяет ClickHouse. Большинство языков программирования поддерживают большинство распространенных алгоритмов и структур данных, но как правило, они бывают слишком универсальными, чтобы быть по-настоящему эффективными. Мы рассматриваем каждую задачу как тонкий инструмент со множеством настроек, вместо того чтобы просто взять какую-то случайную реализацию. Например, если вам нужна хеш-таблица, вот несколько ключевых вопросов, которые нужно продумать: + +- Какую хеш-функцию выбрать? +- Каким способом разрешать коллизии: [открытая адресация](https://en.wikipedia.org/wiki/Open_addressing) или [метод цепочек](https://en.wikipedia.org/wiki/Hash_table#Separate_chaining)? +- Как хранить данные в памяти: ключи и значения в одном массиве или в отдельных? Будут ли там храниться маленькие или большие значения? +- Фактор заполнения: когда и как менять размер таблицы? Как перемещать значения при изменении размера? +- Будут ли значения удаляться и если да, то какой алгоритм сработает лучше? +- Понадобится ли быстрое зондирование с использованием битовых масок, встроенное хранение строковых ключей, поддержка неперемещаемых значений, предварительная выборка и пакетная обработка? + +Хеш-таблица — ключевая структура данных для реализации `GROUP BY`, и ClickHouse автоматически выбирает одну из [более 30 вариаций](https://github.com/ClickHouse/ClickHouse/blob/master/src/Interpreters/Aggregator.h) для каждого специфического запроса. + +Для алгоритмов сортировки, например, следует продумать следующие вопросы: + +- Что будет сортироваться: массив чисел, кортежей, строк или структур? +- Доступны ли все данные в оперативной памяти? +- Нужна ли стабильная сортировка? +- Нужна ли полная сортировка? Может быть, будет достаточно частичной или выборочной сортировки? +- Как сравнивать данные? +- Не являются ли данные частично отсортированными? + +Алгоритмы, основанные на характеристиках рабочих данных, обычно дают лучшие результаты, чем их более универсальные аналоги. Если заранее неизвестно, с какими данными придется работать, ClickHouse будет в процессе выполнения пробовать различные реализации и в итоге выберет оптимальный вариант. Например, рекомендуем прочитать [статью о том, как в ClickHouse реализуется распаковка LZ4](https://habr.com/en/company/yandex/blog/457612/). + +Ну и последнее, но тем не менее важное условие: команда ClickHouse постоянно отслеживает в интернете сообщения пользователей о найденных ими удачных реализациях, алгоритмах или структурах данных, анализирует и пробует новые идеи. Иногда в этом потоке сообщений попадаются действительно ценные предложения. + +!!! info "Советы о том, как создать собственную высокопроизводительную систему" + + + - При проектировании системы обращайте внимание на мельчайшие детали реализации. + - Учитывайте возможности аппаратного обеспечения. + - Выбирайте структуры и представления данных исходя из требований конкретной задачи. + - Для особых случаев разрабатывайте специализированные решения. + - Пробуйте новые алгоритмы, о которых вы вчера прочитали в интернете. Ищите возможности для совершенствования. + - Выбирайте алгоритмы динамически, в процессе выполнения, на основе статистики. + - Ориентируйтесь на показатели, собранные при работе с реальными данными. + - Проверяйте производительность в процессе CI. + - Измеряйте и анализируйте всё, что только возможно. diff --git a/docs/ru/faq/index.md b/docs/ru/faq/index.md index 611e604bc8e..08deec5f7ce 100644 --- a/docs/ru/faq/index.md +++ b/docs/ru/faq/index.md @@ -4,14 +4,42 @@ toc_hidden: true toc_priority: 76 --- -# Содержание F.A.Q. {#soderzhanie} +# ClickHouse F.A.Q. {#clickhouse-f-a-q} -В этом разделе документации собрали вопросы о ClickHouse, которые задают чаще всего. +В этом разделе документации собраны ответы на вопросы о ClickHouse, которые задают чаще всего. Категории: -- **[Общие вопросы](../faq/general/index.md)** -- **[Применение](../faq/use-cases/index.md)** -- **[Операции](../faq/operations/index.md)** -- **[Интеграция](../faq/integration/index.md)** +- **[Общие вопросы](general/index.md)** + - [Что такое ClickHouse?](../index.md#what-is-clickhouse) + - [Почему ClickHouse такой быстрый?](general/why-clickhouse-is-so-fast.md) + - [Кто пользуется ClickHouse?](general/who-is-using-clickhouse.md) + - [Что обозначает название ClickHouse?](general/dbms-naming.md) + - [Как фраза “Не тормозит” осталась на всех футболках?](general/ne-tormozit.md) + - [Что такое OLAP?](general/olap.md) + - [Что такое столбцовая база данных?](general/columnar-database.md) + - [Почему бы не использовать системы типа MapReduce?](general/mapreduce.md) +- **[Применение](use-cases/index.md)** + - [Можно ли использовать ClickHouse как БД временных рядов?](use-cases/time-series.md) + - [Можно ли использовать ClickHouse для хранения данных вида "ключ-значение"?](use-cases/key-value.md) +- **[Операции](operations/index.md)** + - [Какую версию ClickHouse использовать?](operations/production.md) + - [Возможно ли удалить старые записи из таблицы ClickHouse?](operations/delete-old-data.md) +- **[Интеграция](integration/index.md)** + - [Как экспортировать данные из ClickHouse в файл?](integration/file-export.md) + - [Как импортировать JSON в ClickHouse?](integration/json-import.md) + - [Что делать, если у меня проблема с кодировками при использовании Oracle через ODBC?](integration/oracle-odbc.md) +{## TODO +Question candidates: +- How to choose a primary key? +- How to add a column in ClickHouse? +- Too many parts +- How to filter ClickHouse table by an array column contents? +- How to insert all rows from one table to another of identical structure? +- How to kill a process (query) in ClickHouse? +- How to implement pivot (like in pandas)? +- How to remove the default ClickHouse user through users.d? +- Importing MySQL dump to Clickhouse +- Window function workarounds (row\_number, lag/lead, running diff/sum/average) +##} diff --git a/docs/ru/faq/integration/file-export.md b/docs/ru/faq/integration/file-export.md index d21ffbd3349..b9a54dc0766 100644 --- a/docs/ru/faq/integration/file-export.md +++ b/docs/ru/faq/integration/file-export.md @@ -1,27 +1,27 @@ --- -title: How do I export data from ClickHouse to a file? +title: Как экспортировать данные из ClickHouse в файл? toc_hidden: true toc_priority: 10 --- -## Как экспортировать данные из ClickHouse в файл? {#how-to-export-to-file-rus} +# Как экспортировать данные из ClickHouse в файл? {#how-to-export-to-file-rus} -### Секция INTO OUTFILE {#sektsiia-into-outfile-rus} +## Секция INTO OUTFILE {#using-into-outfile-clause} -Добавьте секцию [INTO OUTFILE](../../sql-reference/statements/select/into-outfile.md#into-outfile-clause) к своему запросу. +Добавьте к своему запросу секцию [INTO OUTFILE](../../sql-reference/statements/select/into-outfile.md#into-outfile-clause). Например: ``` sql -SELECT * FROM table INTO OUTFILE 'file' +SELECT * FROM table INTO OUTFILE 'file'; ``` -По умолчанию, для выдачи данных ClickHouse использует формат [TabSeparated](../../interfaces/formats.md#tabseparated). Чтобы выбрать [формат данных](../../interfaces/formats.md), используйте секцию [FORMAT](../../sql-reference/statements/select/format.md#format-clause). +По умолчанию при выдаче данных ClickHouse использует формат [TabSeparated](../../interfaces/formats.md#tabseparated). Чтобы выбрать другой [формат данных](../../interfaces/formats.md), используйте секцию [FORMAT](../../sql-reference/statements/select/format.md#format-clause). Например: ``` sql -SELECT * FROM table INTO OUTFILE 'file' FORMAT CSV +SELECT * FROM table INTO OUTFILE 'file' FORMAT CSV; ``` ## Таблица с движком File {#using-a-file-engine-table} diff --git a/docs/ru/faq/integration/index.md b/docs/ru/faq/integration/index.md index 59fd84a8139..fdb9039d066 100644 --- a/docs/ru/faq/integration/index.md +++ b/docs/ru/faq/integration/index.md @@ -1,19 +1,19 @@ --- -title: Questions about integrating ClickHouse and other systems +title: Интеграция ClickHouse с другими системами toc_hidden_folder: true toc_priority: 4 toc_title: Интеграция --- -# Вопросы об интеграции ClickHouse с другими системами {#question-about-integrating-clickhouse-and-other-systems-rus} +# Интеграция ClickHouse с другими системами {#question-about-integrating-clickhouse-and-other-systems-rus} Вопросы: - [Как экспортировать данные из ClickHouse в файл?](file-export.md) -- Как импортировать JSON в ClickHouse? +- [Как импортировать JSON в ClickHouse?](json-import.md) - [Что делать, если у меня проблема с кодировками при использовании Oracle через ODBC?](oracle-odbc.md) !!! info "Если вы не нашли то, что искали" Загляните в другие подразделы F.A.Q. или поищите в остальных разделах документации, ориентируйтесь по оглавлению слева. -{## [Original article](https://clickhouse.tech/docs/ru/faq/integration/) ##} +[Original article](https://clickhouse.tech/docs/ru/faq/integration/) diff --git a/docs/ru/faq/integration/json-import.md b/docs/ru/faq/integration/json-import.md new file mode 100644 index 00000000000..17911dd1ef8 --- /dev/null +++ b/docs/ru/faq/integration/json-import.md @@ -0,0 +1,33 @@ +--- +title: Как импортировать JSON в ClickHouse? +toc_hidden: true +toc_priority: 11 +--- + +# Как импортировать JSON в ClickHouse? {#how-to-import-json-into-clickhouse} + +ClickHouse поддерживает широкий спектр [входных и выходных форматов данных](../../interfaces/formats.md). Среди них есть множество вариаций JSON, но чаще всего для импорта данных используют [JSONEachRow](../../interfaces/formats.md#jsoneachrow): один JSON-объект в строке, каждый объект с новой строки. + +## Примеры {#examples} + +С помощью [HTTP-интерфейса](../../interfaces/http.md): + +``` bash +$ echo '{"foo":"bar"}' | curl 'http://localhost:8123/?query=INSERT%20INTO%20test%20FORMAT%20JSONEachRow' --data-binary @- +``` + +При помощи [интефейса CLI](../../interfaces/cli.md): + +``` bash +$ echo '{"foo":"bar"}' | clickhouse-client ---query="INSERT INTO test FORMAT JSONEachRow" +``` + +Чтобы не вставлять данные вручную, используйте одну из [готовых библиотек](../../interfaces/index.md). + +## Полезные настройки {#useful-settings} + +- `input_format_skip_unknown_fields` позволяет импортировать JSON, даже если он содержит дополнительные поля, которых нет в таблице (отбрасывая лишние поля). +- `input_format_import_nested_json` позволяет импортировать вложенные JSON-объекты в столбцы типа [Nested](../../sql-reference/data-types/nested-data-structures/nested.md). + +!!! note "Примечание" + В HTTP-интерфейсе настройки передаются через параметры `GET` запроса, в `CLI` interface — как дополнительные аргументы командной строки, начинающиеся с `--`. diff --git a/docs/ru/faq/integration/oracle-odbc.md b/docs/ru/faq/integration/oracle-odbc.md index f41f1ae7fc1..1997cdcc1d2 100644 --- a/docs/ru/faq/integration/oracle-odbc.md +++ b/docs/ru/faq/integration/oracle-odbc.md @@ -1,10 +1,10 @@ --- -title: What if I have a problem with encodings when using Oracle via ODBC? +title: Что делать, если у меня проблема с кодировками при использовании Oracle через ODBC? toc_hidden: true toc_priority: 20 --- -## Что делать, если у меня проблема с кодировками при использовании Oracle через ODBC? {#oracle-odbc-encodings-rus} +# Что делать, если у меня проблема с кодировками при использовании Oracle через ODBC? {#oracle-odbc-encodings} Если вы используете Oracle через драйвер ODBC в качестве источника внешних словарей, необходимо задать правильное значение для переменной окружения `NLS_LANG` в `/etc/default/clickhouse`. Подробнее читайте в [Oracle NLS_LANG FAQ](https://www.oracle.com/technetwork/products/globalization/nls-lang-099431.html). diff --git a/docs/ru/faq/operations/delete-old-data.md b/docs/ru/faq/operations/delete-old-data.md new file mode 100644 index 00000000000..7870f9b3bfe --- /dev/null +++ b/docs/ru/faq/operations/delete-old-data.md @@ -0,0 +1,42 @@ +--- +title: Возможно ли удалить старые записи из таблицы ClickHouse? +toc_hidden: true +toc_priority: 20 +--- + +# Возможно ли удалить старые записи из таблицы ClickHouse? {#is-it-possible-to-delete-old-records-from-a-clickhouse-table} + +Если отвечать коротко, то да. В ClickHouse есть множество механизмов, которые позволяют освобождать место на диске, удаляя старые данные. Каждый механизм подходит для разных сценариев. + +## TTL {#ttl} + +ClickHouse позволяет автоматически удалять данные при выполнении некоторых условий. Эти условия задаются как выражение, вычисляемое на основе значений любых столбцов, обычно это просто разница между текущим моментом времени и значением какого-то столбца, содержащего дату и время. + +Ключевое преимущество такого подхода в том, что не нужно использовать внешнюю систему, чтобы запустить процесс — когда заданы условия TTL, удаление данных выполняется автоматически в фоновом режиме. + +!!! note "Note" + TTL можно использовать не только для перемещения в [/dev/null](https://en.wikipedia.org/wiki/Null_device), но еще и между дисками, например, с SSD на HDD. + +[Подробнее о конфигурировании TTL](../../engines/table-engines/mergetree-family/mergetree.md#table_engine-mergetree-ttl). + +## ALTER DELETE {#alter-delete} + +ClickHouse не удаляет данные в реальном времени, как СУБД [OLTP](https://en.wikipedia.org/wiki/Online_transaction_processing). Больше всего на такое удаление похожи мутации. Они выполняются с помощью запросов `ALTER ... DELETE` или `ALTER ... UPDATE`. В отличие от обычных запросов `DELETE` и `UPDATE`, мутации выполняются асинхронно, в пакетном режиме, не в реальном времени. В остальном после слов `ALTER TABLE` синтаксис обычных запросов и мутаций одинаковый. + +`ALTER DELETE` можно использовать для гибкого удаления устаревших данных. Если вам нужно делать это регулярно, единственный недостаток такого подхода будет заключаться в том, что потребуется внешняя система для запуска запроса. Кроме того, могут возникнуть некоторые проблемы с производительностью, поскольку мутации перезаписывают целые куски данных если в них содержится хотя бы одна строка, которую нужно удалить. + +Это самый распространенный подход к тому, чтобы обеспечить соблюдение принципов [GDPR](https://gdpr-info.eu) в вашей системе на ClickHouse. + +Подробнее смотрите в разделе [Мутации](../../sql-reference/statements/alter/index.md#alter-mutations). + +## DROP PARTITION {#drop-partition} + +Запрос `ALTER TABLE ... DROP PARTITION` позволяет эффективно удалять целые партиции. Этот способ не такой гибкий, важно правильно сконфигурировать партиции при создании таблицы, но он подходит для достаточно широкого спектра типовых задач. Как и для мутаций, для регулярного запуска таких запросов нужна внешняя система. + +Подробнее смотрите в разделе [Манипулирование с партициями и кусками](../../sql-reference/statements/alter/partition.md#alter_drop-partition). + +## TRUNCATE {#truncate} + +Это достаточно радикальный способ, он удаляет все данные в таблице, но хорошо подходит для отдельных случаевх. + +Подробнее смотрите в разделе об [удалении партиций](../../sql-reference/statements/alter/partition.md#alter_drop-partition). diff --git a/docs/ru/faq/operations/index.md b/docs/ru/faq/operations/index.md index 98a04213fb7..723ae2d10d3 100644 --- a/docs/ru/faq/operations/index.md +++ b/docs/ru/faq/operations/index.md @@ -1,18 +1,18 @@ --- -title: Question about operating ClickHouse servers and clusters +title: Вопросы о производительности серверов и кластеров ClickHouse toc_hidden_folder: true toc_priority: 3 toc_title: Операции --- -# Вопросы о производительности серверов и кластеров ClickHouse {#voprosy-ob-operating-clickhouse-servers-and-clusters} +# Вопросы о производительности серверов и кластеров ClickHouse {#question-about-operating-clickhouse-servers-and-clusters} Вопросы: -- Which ClickHouse version to use in production? -- Is it possible to delete old records from a ClickHouse table? +- [Какую версию ClickHouse использовать?](production.md) +- [Возможно ли удалить старые записи из таблицы ClickHouse?](delete-old-data.md) - !!! info "Don’t see what you were looking for?" - Check out [other F.A.Q. categories](../../faq/index.md) or browse around main documentation articles found in the left sidebar. +!!! info "Если вы не нашли то, что искали" + Загляните в другие подразделы F.A.Q. или поищите в остальных разделах документации, ориентируйтесь по оглавлению слева. - {## [Original article](https://clickhouse.tech/docs/en/faq/production/) ##} +[Original article](https://clickhouse.tech/docs/en/faq/operations/) diff --git a/docs/ru/faq/operations/production.md b/docs/ru/faq/operations/production.md new file mode 100644 index 00000000000..a82a7f5e888 --- /dev/null +++ b/docs/ru/faq/operations/production.md @@ -0,0 +1,70 @@ +--- +title: Какую версию ClickHouse использовать? +toc_hidden: true +toc_priority: 10 +--- + +# Какую версию ClickHouse использовать? {#which-clickhouse-version-to-use-in-production} + +Во-первых, давайте обсудим, почему возникает этот вопрос. Есть две основные причины: + +1. ClickHouse развивается достаточно быстро, и обычно мы выпускаем более 10 стабильных релизов в год. Так что есть из чего выбрать, а это не всегда просто. +2. Некоторые пользователи не хотят тратить время на анализ того, какая версия лучше подходит для их задач, и просто хотят получить совет от эксперта. + +Вторая причина более весомая, так что начнем с нее, а затем рассмотрим, какие бывают релизы ClickHouse. + +## Какую версию ClickHouse вы посоветуете? {#which-clickhouse-version-do-you-recommend} + +Казалось бы, самый удобный вариант — нанять консультанта или довериться эксперту, и делегировать ему ответственность за вашу систему. Вы устанавливаете ту версию ClickHouse, которую вам рекомендовали, и теперь если что-то пойдет не так — это уже не ваша вина. На самом деле это не так. Никто не может знать лучше вас, что происходит в вашей системе. + +Как же правильно выбрать версию ClickHouse, на которую стоит обновиться? Или как выбрать версию, с которой следует начать, если вы только внедряете ClickHouse? Во-первых, мы рекомендуем позаботиться о создании **реалистичной тестовой среды** (pre-production). В идеальном мире это была бы полная копия рабочей среды, но чаще всего такое решение оказывается слишком дорогостоящим. + +Чтобы тестовая среда была достаточно надежной, но не слишком дорогостоящей, учитывайте следующие моменты: + +- В тестовой среде нужно выполнять набор запросов, максимально близкий к тому, который будет выполняться в реальной среде: + - Не используйте тестовую среду в режиме "только для чтения", работая с каким-то статичным набором данных. + - Не используйте её в режиме "только для записи", проверяя лишь копирование данных, без построения типовых отчетов. + - Не очищайте её, удаляя все данные подчистую вместо тестирования рабочих схем миграции. +- Выполняйте реальные запросы на выборке из реальных рабочих данных. Постарайтесь подготовить репрезентативную выборку, на которой запрос `SELECT` будет возвращать адекватные результаты. Если регламенты безопасности не позволяют использовать реальные данные за пределами защищенной рабочей среды, используйте обфускацию. +- Убедитесь, что тестовая среда находится под контролем тех же систем мониторинга и оповещения, что и рабочая. +- Если ваша рабочая среда распределена между разными дата-центрами и регионами, тестовая среда должна быть такой же. +- Если в рабочей среде используются сложные инструменты типа репликации, распределённых таблиц или каскадных материализованных представлений, тестовая среда должна быть сконфигурирована так же. +- Обычно в тестовой среде стараются использовать то же количество серверов и виртуальных машин, что и в рабочей, но делают их меньшего объема. Либо наоборот, используют существенно меньшее число серверов и ВМ, но тех же объемов. Первый вариант скорее позволит обнаружить проблемы, связанные с работой сети, а второй вариант более прост в управлении. + +Второе направление — **автоматизированное тестирование**. Не думайте, что если какой-то запрос отработал успешно один раз, так будет всегда. Считается приемлемым выполнять некоторые юнит-тесты, используя "заглушки" вместо запросов к СУБД. Но вы должны проводить достаточное количество автотестов, где запросы выполняются в реальном ClickHouse, чтобы убедиться, что все важные задачи отрабатывают должным образом. + +В продолжение этой темы, вы можете поделиться вашими автотестами и передать их [в открытую тестовую среду ClickHouse](https://github.com/ClickHouse/ClickHouse/tree/master/tests), которая используется для постоянного развития нашей СУБД. Вам придётся потратить немного времени и сил, чтобы научиться [составлять и выполнять тесты](../../development/tests.md), а также чтобы перенести ваши тесты на эту платформу. Наградой за это станет уверенность в том, что новые стабильные релизы ClickHouse будут корректно работать на ваших задачах. Это гораздо лучше, чем тратить время на то, чтобы вновь отлавливать прежние ошибки в новых версиях, а затем ждать, пока их исправят и включат эти исправления в очередной релиз. Некоторые компании уже включили в корпоративные регламенты необходимость передачи своих тестов в ClickHouse, прежде всего стоит упомянуть [правило Beyonce](https://www.oreilly.com/library/view/software-engineering-at/9781492082781/ch01.html#policies_that_scale_well), действующее в Google. + +После того, как вы подготовили тестовую среду и инфраструктуру, выбор версии ClickHouse упрощается: + +1. Проверяйте новые релизы ClickHouse с помощью подготовленных автотестов. Вы можете проверять не только стабильные релизы, но и тестовые, хотя работать с такими релизами не рекомендуется. +2. Если новый релиз ClickHouse успешно прошел ваши автотесты, внедряйте его в тестовой среде и проверяйте работоспособность всех ваших задач. +3. Сообщайте обо всех обнаруженных проблемах в [ClickHouse GitHub Issues](https://github.com/ClickHouse/ClickHouse/issues). +4. Если никаких серьезных проблем не было выявлено, можно установить новый релиз ClickHouse в рабочую среду. Чтобы еще больше снизить риски, вы можете внедрить специальные техники поэтапного перехода на новые релизы, такие как [canary releases](https://martinfowler.com/bliki/CanaryRelease.html) или [green-blue deployments](https://martinfowler.com/bliki/BlueGreenDeployment.html). + +Как вы уже поняли, ClickHouse не требует какого-то особенного подхода — описанные выше правила широко используются для любых элементов инфраструктуры, если нужно обеспечить ее надежность и если компании серьезно подходят к вопросам стабильности своих систем. + +## Какой вид релиза ClickHouse выбрать? {#how-to-choose-between-clickhouse-releases} + +Если вы заглянете в раздел, где публикуются установочные пакеты ClickHouse, вы увидите там следующие виды пакетов: + +1. `testing` +2. `prestable` +3. `stable` +4. `lts` (long-term support) + +Как уже упоминалось выше, тестовые релизы (`testing`) стоит использовать для раннего обнаружения ошибок, в рабочей среде мы не рекомендуем использовать такие релизы, поскольку они еще не протестированы так же тщательно, как остальные. + +Подготовительные (`prestable`) — это релизы-кандидаты, которые с большой вероятностью скоро будут доведены до стабильного состояния. Вы можете использовать их в тестовой среде и сообщать нам об обнаруженных ошибках. + +В рабочей среде мы рекомендуем использвать либо стабильный релиз (`stable`), либо релиз с долговременной поддержкой (`lts`). Если вы выбираете между этими двуми видами релизов, примите во внимание следующее: + +- По умолчанию мы рекомендуем релизы `stable`. Новый стабильный релиз выпускается примерно раз в месяц, что открывает доступ к новым функциям. Три последних стабильных релиза находятся на поддержке — это означает, что в них интегрируются исправленные ошибки и доработки. +- Релизы `lts` выпускаются дважды в год и находятся на поддержке в течение года с момента выхода. Они более предочтительны в следующих случаях: + - ваши корпоративные регламенты запрещают частые обновления или использование любых релизов, кроме LTS; + - вы используете ClickHouse в продуктах, которые не задействуют сложные инструменты ClickHouse, или у вас не хватает ресурсов для частого их обновления. + +Часто компании, которые изначально ориентировались на релизы `lts`, позднее переходят на `stable`, поскольку хотят быстрее получать доступ к новым возможностям. + +!!! warning "Важно" + Мы всегда стремимся поддерживать совместимость релизов, но иногда это правило нарушается, и какие-то отдельные возможности в новых релизах становятся недоступны. Перед обновлением ClickHouse обязательно изучите [журнал изменений](../../whats-new/changelog/index.md), чтобы убедиться, что в нем нет объявлений о нарушении обратной совместимости. diff --git a/docs/ru/faq/use-cases/index.md b/docs/ru/faq/use-cases/index.md index 6e7f2b36fe0..3507d69ad7c 100644 --- a/docs/ru/faq/use-cases/index.md +++ b/docs/ru/faq/use-cases/index.md @@ -1,14 +1,13 @@ --- -title: Questions about ClickHouse use cases +title: Вопросы о применении ClickHouse toc_hidden_folder: true toc_priority: 2 toc_title: Применение --- -# Вопросы о применении ClickHouse {#voprosy-o-primenenii} +# Вопросы о применении ClickHouse {#questions-about-clickhouse-use-cases} Вопросы: -- Can I use ClickHouse as a time-series database? -- Can I use ClickHouse as a key-value storage? - +- [Можно ли использовать ClickHouse как БД временных рядов?](time-series.md) +- [Можно ли использовать ClickHouse для хранения данных вида "ключ-значение"?](key-value.md) \ No newline at end of file diff --git a/docs/ru/faq/use-cases/key-value.md b/docs/ru/faq/use-cases/key-value.md new file mode 100644 index 00000000000..4daa9773f84 --- /dev/null +++ b/docs/ru/faq/use-cases/key-value.md @@ -0,0 +1,19 @@ +--- +title: Можно ли использовать ClickHouse для хранения данных вида "ключ-значение"? +toc_hidden: true +toc_priority: 101 +--- + +# Можно ли использовать ClickHouse для хранения данных вида "ключ-значение"? {#can-i-use-clickhouse-as-a-key-value-storage} + +Если отвечать коротко, то **"нет"**. Операции над данными вида "ключ-значение" занимают одну из верхних позиций в списке ситуаций, когда категорически **не стоит**{.text-danger} использовать ClickHouse. Это [OLAP](../../faq/general/olap.md) СУБД, в то время как есть много специализированных СУБД для данных вида "ключ-значение". + +Тем не менее, в некоторых ситуациях имеет смысл использовать ClickHouse для запросов над данными вида "ключ-значение". Чаще всего это относится к системам с относительно невысокой нагрузкой, в которых основной объем операций относится к аналитической обработке данных и отлично подходит для ClickHouse. Однако в них есть некий второстепенный процесс, в котором нужно обрабатывать данные вида "ключ-значение", при этом процесс не требует слишком высокой производительности и не имеет строгих ограничений по задержкам выполнения запросов. Если у вас нет ограничений по бюджету, вы можете использовать для таких операций вспомогательную базу данных "ключ-значение", но это увеличит расходы на обслуживание еще одной СУБД (мониторинг, бэкапы и т.д.). + +Если вы все же решите не следовать рекомендациям и использовать ClickHouse для работы с данными вида "ключ-значение", вот несколько советов: + +- Главная причина, по которой точечный запрос в ClickHouse становится ресурсозатратным — это разреженный индекс для первичного ключа в [таблице семейства MergeTree](../../engines/table-engines/mergetree-family/mergetree.md). Этот индекс не может обращаться напрямую к каждой строке данных, вместо этого он обращается к каждой N-ой строке, а затем сканирует соседние строки вплоть до указанной, обрабатывая по пути лишние данные. При обработке данных вида "ключ-значение" может быть полезно уменьшить значение N при помощи настройки `index_granularity`. + +- ClickHouse хранит столбцы в отдельных файлах, поэтому чтобы собрать одну полную строку, ему приходится обрабатывать все эти файлы. Их количество растет линейно в зависимости от количества столбцов, поэтому при обработке данных вида "ключ-значение" стоит избегать использования множества столбцов и поместить все нужные данные в один столбец с типом `String` в формате JSON, Protobuf или другом подходящем формате. + +- Подумайте об использовании табличного движка [Join](../../engines/table-engines/special/join.md) вместо обычных таблиц `MergeTree` и функции [joinGet](../../sql-reference/functions/other-functions.md#joinget) для получения данных. В этом случае производительность выполнения запросов может быть выше, но могут появиться проблемы с надежностью и удобством. Пример такого использования описан [здесь](https://github.com/ClickHouse/ClickHouse/blob/master/tests/queries/0_stateless/00800_versatile_storage_join.sql#L49-L51). diff --git a/docs/ru/faq/use-cases/time-series.md b/docs/ru/faq/use-cases/time-series.md new file mode 100644 index 00000000000..ea56660cc10 --- /dev/null +++ b/docs/ru/faq/use-cases/time-series.md @@ -0,0 +1,15 @@ +--- +title: Можно ли использовать ClickHouse как базу данных временных рядов? +toc_hidden: true +toc_priority: 101 +--- + +# Можно ли использовать ClickHouse как базу данных временных рядов? {#can-i-use-clickhouse-as-a-time-series-database} + +ClickHouse — это универсальное решение для [OLAP](../../faq/general/olap.md) операций, в то время как существует много специализированных СУБД временных рядов. Однако [высокая скорость выполнения запросов](../../faq/general/why-clickhouse-is-so-fast.md) позволяет CLickHouse во многих случаях "побеждать" специализированные аналоги. В подтверждение этому есть много [примеров](https://medium.com/@AltinityDB/clickhouse-for-time-series-scalability-benchmarks-e181132a895b) с конкретными показателями производительности, так что мы не будем останавливаться на этом подробно. Лучше рассмотрим те возможности ClickHouse, которые стоит использовать. + +Во-первых, есть **[специальные кодеки](../../sql-reference/statements/create/table.md#create-query-specialized-codecs)**, которые составляют типичные временные ряды. Это могут быть либо стандартные алгоритмы, такие как `DoubleDelta` или `Gorilla`, либо специфические для ClickHouse, например `T64`. + +Во-вторых, запросы по временным рядам часто затрагивают только недавние данные, не старше одного дня или недели. Имеет смысл использовать серверы, где есть как быстрые диски nVME/SSD, так и более медленные, но ёмкие HDD диски. С помощью [TTL](../../engines/table-engines/mergetree-family/mergetree.md#table_engine-mergetree-multiple-volumes) можно сконфигурировать таблицы так, чтобы свежие данные хранились на быстрых дисках, а по мере устаревания перемещались на медленные диски. Для архивных данных можно также настроить сворачивание или даже удаление, если это необходимо. + +Несмотря на то, что работа с "сырыми" данными противоречит философии ClickHouse, если нужно соответствовать очень жестким требованиям по скорости обработки данных, вы можете использовать [материализованные представления](../../sql-reference/statements/create/view.md). diff --git a/docs/ru/getting-started/example-datasets/brown-benchmark.md b/docs/ru/getting-started/example-datasets/brown-benchmark.md new file mode 100644 index 00000000000..23702e07fcd --- /dev/null +++ b/docs/ru/getting-started/example-datasets/brown-benchmark.md @@ -0,0 +1,416 @@ +--- +toc_priority: 20 +toc_title: Brown University Benchmark +--- + +# Brown University Benchmark + +`MgBench` — это аналитический тест производительности для данных журнала событий, сгенерированных машиной. Бенчмарк разработан [Andrew Crotty](http://cs.brown.edu/people/acrotty/). + +Скачать данные: +``` +wget https://datasets.clickhouse.tech/mgbench{1..3}.csv.xz +``` + +Распаковать данные: +``` +xz -v -d mgbench{1..3}.csv.xz +``` + +Создание таблиц: +``` +CREATE DATABASE mgbench; + + +CREATE TABLE mgbench.logs1 ( + log_time DateTime, + machine_name LowCardinality(String), + machine_group LowCardinality(String), + cpu_idle Nullable(Float32), + cpu_nice Nullable(Float32), + cpu_system Nullable(Float32), + cpu_user Nullable(Float32), + cpu_wio Nullable(Float32), + disk_free Nullable(Float32), + disk_total Nullable(Float32), + part_max_used Nullable(Float32), + load_fifteen Nullable(Float32), + load_five Nullable(Float32), + load_one Nullable(Float32), + mem_buffers Nullable(Float32), + mem_cached Nullable(Float32), + mem_free Nullable(Float32), + mem_shared Nullable(Float32), + swap_free Nullable(Float32), + bytes_in Nullable(Float32), + bytes_out Nullable(Float32) +) +ENGINE = MergeTree() +ORDER BY (machine_group, machine_name, log_time); + + +CREATE TABLE mgbench.logs2 ( + log_time DateTime, + client_ip IPv4, + request String, + status_code UInt16, + object_size UInt64 +) +ENGINE = MergeTree() +ORDER BY log_time; + + +CREATE TABLE mgbench.logs3 ( + log_time DateTime64, + device_id FixedString(15), + device_name LowCardinality(String), + device_type LowCardinality(String), + device_floor UInt8, + event_type LowCardinality(String), + event_unit FixedString(1), + event_value Nullable(Float32) +) +ENGINE = MergeTree() +ORDER BY (event_type, log_time); +``` + +Вставка данных: + +``` +clickhouse-client --query "INSERT INTO mgbench.logs1 FORMAT CSVWithNames" < mgbench1.csv +clickhouse-client --query "INSERT INTO mgbench.logs2 FORMAT CSVWithNames" < mgbench2.csv +clickhouse-client --query "INSERT INTO mgbench.logs3 FORMAT CSVWithNames" < mgbench3.csv +``` + +Запуск тестов производительности: +``` +-- Q1.1: What is the CPU/network utilization for each web server since midnight? + +SELECT machine_name, + MIN(cpu) AS cpu_min, + MAX(cpu) AS cpu_max, + AVG(cpu) AS cpu_avg, + MIN(net_in) AS net_in_min, + MAX(net_in) AS net_in_max, + AVG(net_in) AS net_in_avg, + MIN(net_out) AS net_out_min, + MAX(net_out) AS net_out_max, + AVG(net_out) AS net_out_avg +FROM ( + SELECT machine_name, + COALESCE(cpu_user, 0.0) AS cpu, + COALESCE(bytes_in, 0.0) AS net_in, + COALESCE(bytes_out, 0.0) AS net_out + FROM logs1 + WHERE machine_name IN ('anansi','aragog','urd') + AND log_time >= TIMESTAMP '2017-01-11 00:00:00' +) AS r +GROUP BY machine_name; + + +-- Q1.2: Which computer lab machines have been offline in the past day? + +SELECT machine_name, + log_time +FROM logs1 +WHERE (machine_name LIKE 'cslab%' OR + machine_name LIKE 'mslab%') + AND load_one IS NULL + AND log_time >= TIMESTAMP '2017-01-10 00:00:00' +ORDER BY machine_name, + log_time; + + +-- Q1.3: What are the hourly average metrics during the past 10 days for a specific workstation? + +SELECT dt, + hr, + AVG(load_fifteen) AS load_fifteen_avg, + AVG(load_five) AS load_five_avg, + AVG(load_one) AS load_one_avg, + AVG(mem_free) AS mem_free_avg, + AVG(swap_free) AS swap_free_avg +FROM ( + SELECT CAST(log_time AS DATE) AS dt, + EXTRACT(HOUR FROM log_time) AS hr, + load_fifteen, + load_five, + load_one, + mem_free, + swap_free + FROM logs1 + WHERE machine_name = 'babbage' + AND load_fifteen IS NOT NULL + AND load_five IS NOT NULL + AND load_one IS NOT NULL + AND mem_free IS NOT NULL + AND swap_free IS NOT NULL + AND log_time >= TIMESTAMP '2017-01-01 00:00:00' +) AS r +GROUP BY dt, + hr +ORDER BY dt, + hr; + + +-- Q1.4: Over 1 month, how often was each server blocked on disk I/O? + +SELECT machine_name, + COUNT(*) AS spikes +FROM logs1 +WHERE machine_group = 'Servers' + AND cpu_wio > 0.99 + AND log_time >= TIMESTAMP '2016-12-01 00:00:00' + AND log_time < TIMESTAMP '2017-01-01 00:00:00' +GROUP BY machine_name +ORDER BY spikes DESC +LIMIT 10; + + +-- Q1.5: Which externally reachable VMs have run low on memory? + +SELECT machine_name, + dt, + MIN(mem_free) AS mem_free_min +FROM ( + SELECT machine_name, + CAST(log_time AS DATE) AS dt, + mem_free + FROM logs1 + WHERE machine_group = 'DMZ' + AND mem_free IS NOT NULL +) AS r +GROUP BY machine_name, + dt +HAVING MIN(mem_free) < 10000 +ORDER BY machine_name, + dt; + + +-- Q1.6: What is the total hourly network traffic across all file servers? + +SELECT dt, + hr, + SUM(net_in) AS net_in_sum, + SUM(net_out) AS net_out_sum, + SUM(net_in) + SUM(net_out) AS both_sum +FROM ( + SELECT CAST(log_time AS DATE) AS dt, + EXTRACT(HOUR FROM log_time) AS hr, + COALESCE(bytes_in, 0.0) / 1000000000.0 AS net_in, + COALESCE(bytes_out, 0.0) / 1000000000.0 AS net_out + FROM logs1 + WHERE machine_name IN ('allsorts','andes','bigred','blackjack','bonbon', + 'cadbury','chiclets','cotton','crows','dove','fireball','hearts','huey', + 'lindt','milkduds','milkyway','mnm','necco','nerds','orbit','peeps', + 'poprocks','razzles','runts','smarties','smuggler','spree','stride', + 'tootsie','trident','wrigley','york') +) AS r +GROUP BY dt, + hr +ORDER BY both_sum DESC +LIMIT 10; + + +-- Q2.1: Which requests have caused server errors within the past 2 weeks? + +SELECT * +FROM logs2 +WHERE status_code >= 500 + AND log_time >= TIMESTAMP '2012-12-18 00:00:00' +ORDER BY log_time; + + +-- Q2.2: During a specific 2-week period, was the user password file leaked? + +SELECT * +FROM logs2 +WHERE status_code >= 200 + AND status_code < 300 + AND request LIKE '%/etc/passwd%' + AND log_time >= TIMESTAMP '2012-05-06 00:00:00' + AND log_time < TIMESTAMP '2012-05-20 00:00:00'; + + +-- Q2.3: What was the average path depth for top-level requests in the past month? + +SELECT top_level, + AVG(LENGTH(request) - LENGTH(REPLACE(request, '/', ''))) AS depth_avg +FROM ( + SELECT SUBSTRING(request FROM 1 FOR len) AS top_level, + request + FROM ( + SELECT POSITION(SUBSTRING(request FROM 2), '/') AS len, + request + FROM logs2 + WHERE status_code >= 200 + AND status_code < 300 + AND log_time >= TIMESTAMP '2012-12-01 00:00:00' + ) AS r + WHERE len > 0 +) AS s +WHERE top_level IN ('/about','/courses','/degrees','/events', + '/grad','/industry','/news','/people', + '/publications','/research','/teaching','/ugrad') +GROUP BY top_level +ORDER BY top_level; + + +-- Q2.4: During the last 3 months, which clients have made an excessive number of requests? + +SELECT client_ip, + COUNT(*) AS num_requests +FROM logs2 +WHERE log_time >= TIMESTAMP '2012-10-01 00:00:00' +GROUP BY client_ip +HAVING COUNT(*) >= 100000 +ORDER BY num_requests DESC; + + +-- Q2.5: What are the daily unique visitors? + +SELECT dt, + COUNT(DISTINCT client_ip) +FROM ( + SELECT CAST(log_time AS DATE) AS dt, + client_ip + FROM logs2 +) AS r +GROUP BY dt +ORDER BY dt; + + +-- Q2.6: What are the average and maximum data transfer rates (Gbps)? + +SELECT AVG(transfer) / 125000000.0 AS transfer_avg, + MAX(transfer) / 125000000.0 AS transfer_max +FROM ( + SELECT log_time, + SUM(object_size) AS transfer + FROM logs2 + GROUP BY log_time +) AS r; + + +-- Q3.1: Did the indoor temperature reach freezing over the weekend? + +SELECT * +FROM logs3 +WHERE event_type = 'temperature' + AND event_value <= 32.0 + AND log_time >= '2019-11-29 17:00:00.000'; + + +-- Q3.4: Over the past 6 months, how frequently were each door opened? + +SELECT device_name, + device_floor, + COUNT(*) AS ct +FROM logs3 +WHERE event_type = 'door_open' + AND log_time >= '2019-06-01 00:00:00.000' +GROUP BY device_name, + device_floor +ORDER BY ct DESC; + + +-- Q3.5: Where in the building do large temperature variations occur in winter and summer? + +WITH temperature AS ( + SELECT dt, + device_name, + device_type, + device_floor + FROM ( + SELECT dt, + hr, + device_name, + device_type, + device_floor, + AVG(event_value) AS temperature_hourly_avg + FROM ( + SELECT CAST(log_time AS DATE) AS dt, + EXTRACT(HOUR FROM log_time) AS hr, + device_name, + device_type, + device_floor, + event_value + FROM logs3 + WHERE event_type = 'temperature' + ) AS r + GROUP BY dt, + hr, + device_name, + device_type, + device_floor + ) AS s + GROUP BY dt, + device_name, + device_type, + device_floor + HAVING MAX(temperature_hourly_avg) - MIN(temperature_hourly_avg) >= 25.0 +) +SELECT DISTINCT device_name, + device_type, + device_floor, + 'WINTER' +FROM temperature +WHERE dt >= DATE '2018-12-01' + AND dt < DATE '2019-03-01' +UNION +SELECT DISTINCT device_name, + device_type, + device_floor, + 'SUMMER' +FROM temperature +WHERE dt >= DATE '2019-06-01' + AND dt < DATE '2019-09-01'; + + +-- Q3.6: For each device category, what are the monthly power consumption metrics? + +SELECT yr, + mo, + SUM(coffee_hourly_avg) AS coffee_monthly_sum, + AVG(coffee_hourly_avg) AS coffee_monthly_avg, + SUM(printer_hourly_avg) AS printer_monthly_sum, + AVG(printer_hourly_avg) AS printer_monthly_avg, + SUM(projector_hourly_avg) AS projector_monthly_sum, + AVG(projector_hourly_avg) AS projector_monthly_avg, + SUM(vending_hourly_avg) AS vending_monthly_sum, + AVG(vending_hourly_avg) AS vending_monthly_avg +FROM ( + SELECT dt, + yr, + mo, + hr, + AVG(coffee) AS coffee_hourly_avg, + AVG(printer) AS printer_hourly_avg, + AVG(projector) AS projector_hourly_avg, + AVG(vending) AS vending_hourly_avg + FROM ( + SELECT CAST(log_time AS DATE) AS dt, + EXTRACT(YEAR FROM log_time) AS yr, + EXTRACT(MONTH FROM log_time) AS mo, + EXTRACT(HOUR FROM log_time) AS hr, + CASE WHEN device_name LIKE 'coffee%' THEN event_value END AS coffee, + CASE WHEN device_name LIKE 'printer%' THEN event_value END AS printer, + CASE WHEN device_name LIKE 'projector%' THEN event_value END AS projector, + CASE WHEN device_name LIKE 'vending%' THEN event_value END AS vending + FROM logs3 + WHERE device_type = 'meter' + ) AS r + GROUP BY dt, + yr, + mo, + hr +) AS s +GROUP BY yr, + mo +ORDER BY yr, + mo; +``` + +Данные также доступны для работы с интерактивными запросами через [Playground](https://gh-api.clickhouse.tech/play?user=play), [пример](https://gh-api.clickhouse.tech/play?user=play#U0VMRUNUIG1hY2hpbmVfbmFtZSwKICAgICAgIE1JTihjcHUpIEFTIGNwdV9taW4sCiAgICAgICBNQVgoY3B1KSBBUyBjcHVfbWF4LAogICAgICAgQVZHKGNwdSkgQVMgY3B1X2F2ZywKICAgICAgIE1JTihuZXRfaW4pIEFTIG5ldF9pbl9taW4sCiAgICAgICBNQVgobmV0X2luKSBBUyBuZXRfaW5fbWF4LAogICAgICAgQVZHKG5ldF9pbikgQVMgbmV0X2luX2F2ZywKICAgICAgIE1JTihuZXRfb3V0KSBBUyBuZXRfb3V0X21pbiwKICAgICAgIE1BWChuZXRfb3V0KSBBUyBuZXRfb3V0X21heCwKICAgICAgIEFWRyhuZXRfb3V0KSBBUyBuZXRfb3V0X2F2ZwpGUk9NICgKICBTRUxFQ1QgbWFjaGluZV9uYW1lLAogICAgICAgICBDT0FMRVNDRShjcHVfdXNlciwgMC4wKSBBUyBjcHUsCiAgICAgICAgIENPQUxFU0NFKGJ5dGVzX2luLCAwLjApIEFTIG5ldF9pbiwKICAgICAgICAgQ09BTEVTQ0UoYnl0ZXNfb3V0LCAwLjApIEFTIG5ldF9vdXQKICBGUk9NIG1nYmVuY2gubG9nczEKICBXSEVSRSBtYWNoaW5lX25hbWUgSU4gKCdhbmFuc2knLCdhcmFnb2cnLCd1cmQnKQogICAgQU5EIGxvZ190aW1lID49IFRJTUVTVEFNUCAnMjAxNy0wMS0xMSAwMDowMDowMCcKKSBBUyByCkdST1VQIEJZIG1hY2hpbmVfbmFtZQ==). + +[Оригинальная статья](https://clickhouse.tech/docs/ru/getting_started/example_datasets/brown-benchmark/) diff --git a/docs/ru/getting-started/example-datasets/criteo.md b/docs/ru/getting-started/example-datasets/criteo.md index 7a58da5b695..ecdc5f5fa41 100644 --- a/docs/ru/getting-started/example-datasets/criteo.md +++ b/docs/ru/getting-started/example-datasets/criteo.md @@ -1,6 +1,6 @@ --- toc_priority: 18 -toc_title: "\u0422\u0435\u0440\u0430\u0431\u0430\u0439\u0442\u0020\u043b\u043e\u0433\u043e\u0432\u0020\u043a\u043b\u0438\u043a\u043e\u0432\u0020\u043e\u0442\u0020\u0043\u0072\u0069\u0074\u0065\u006f" +toc_title: "Терабайт логов кликов от Criteo" --- # Терабайт логов кликов от Criteo {#terabait-logov-klikov-ot-criteo} diff --git a/docs/ru/getting-started/example-datasets/index.md b/docs/ru/getting-started/example-datasets/index.md index eff944a7980..fd89bb122e3 100644 --- a/docs/ru/getting-started/example-datasets/index.md +++ b/docs/ru/getting-started/example-datasets/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0435\u0020\u043c\u0430\u0441\u0441\u0438\u0432\u044b\u0020\u0434\u0430\u043d\u043d\u044b\u0445" +toc_folder_title: "Тестовые массивы данных" toc_priority: 14 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435" +toc_title: "Введение" --- # Тестовые массивы данных {#testovye-massivy-dannykh} diff --git a/docs/ru/getting-started/example-datasets/metrica.md b/docs/ru/getting-started/example-datasets/metrica.md index 3246eb5178c..7deacdb836c 100644 --- a/docs/ru/getting-started/example-datasets/metrica.md +++ b/docs/ru/getting-started/example-datasets/metrica.md @@ -1,6 +1,6 @@ --- toc_priority: 15 -toc_title: "\u0410\u043d\u043e\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435\u0020\u0434\u0430\u043d\u043d\u044b\u0435\u0020\u042f\u043d\u0434\u0435\u043a\u0441\u002e\u041c\u0435\u0442\u0440\u0438\u043a\u0438" +toc_title: "Анонимизированные данные Яндекс.Метрики" --- # Анонимизированные данные Яндекс.Метрики {#anonimizirovannye-dannye-iandeks-metriki} diff --git a/docs/ru/getting-started/example-datasets/nyc-taxi.md b/docs/ru/getting-started/example-datasets/nyc-taxi.md index a4472751a99..891a92e2fa7 100644 --- a/docs/ru/getting-started/example-datasets/nyc-taxi.md +++ b/docs/ru/getting-started/example-datasets/nyc-taxi.md @@ -1,6 +1,6 @@ --- toc_priority: 20 -toc_title: "\u0414\u0430\u043d\u043d\u044b\u0435\u0020\u043e\u0020\u0442\u0430\u043a\u0441\u0438\u0020\u0432\u0020\u041d\u044c\u044e\u002d\u0419\u043e\u0440\u043a\u0435" +toc_title: "Данные о такси в Нью-Йорке" --- # Данные о такси в Нью-Йорке {#dannye-o-taksi-v-niu-iorke} diff --git a/docs/ru/getting-started/index.md b/docs/ru/getting-started/index.md index ab72ce4a1d2..78b56092740 100644 --- a/docs/ru/getting-started/index.md +++ b/docs/ru/getting-started/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u041d\u0430\u0447\u0430\u043b\u043e\u0020\u0440\u0430\u0431\u043e\u0442\u044b" +toc_folder_title: "Начало работы" toc_hidden: true toc_priority: 8 toc_title: hidden diff --git a/docs/ru/getting-started/install.md b/docs/ru/getting-started/install.md index 04efe77712b..aa5e8d77512 100644 --- a/docs/ru/getting-started/install.md +++ b/docs/ru/getting-started/install.md @@ -1,6 +1,6 @@ --- toc_priority: 11 -toc_title: "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430" +toc_title: "Установка" --- # Установка {#ustanovka} diff --git a/docs/ru/guides/apply-catboost-model.md b/docs/ru/guides/apply-catboost-model.md index 026b4d9d75e..11964c57fc7 100644 --- a/docs/ru/guides/apply-catboost-model.md +++ b/docs/ru/guides/apply-catboost-model.md @@ -1,6 +1,6 @@ --- toc_priority: 41 -toc_title: "\u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u0020\u043c\u043e\u0434\u0435\u043b\u0438\u0020\u0043\u0061\u0074\u0042\u006f\u006f\u0073\u0074\u0020\u0432\u0020\u0043\u006c\u0069\u0063\u006b\u0048\u006f\u0075\u0073\u0065" +toc_title: "Применение модели CatBoost в ClickHouse" --- # Применение модели CatBoost в ClickHouse {#applying-catboost-model-in-clickhouse} diff --git a/docs/ru/guides/index.md b/docs/ru/guides/index.md index 2c38de275a7..5b305a6a135 100644 --- a/docs/ru/guides/index.md +++ b/docs/ru/guides/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u0420\u0443\u043A\u043E\u0432\u043E\u0434\u0441\u0442\u0432\u0430" +toc_folder_title: "Руководства" toc_priority: 38 -toc_title: "\u041E\u0431\u0437\u043E\u0440" +toc_title: "Обзор" --- # Руководства {#rukovodstva} diff --git a/docs/ru/index.md b/docs/ru/index.md index 7c129f9d113..26d7dc3bf21 100644 --- a/docs/ru/index.md +++ b/docs/ru/index.md @@ -1,9 +1,9 @@ --- toc_priority: 0 -toc_title: "\u041E\u0431\u0437\u043E\u0440" +toc_title: "Обзор" --- -# Что такое ClickHouse {#chto-takoe-clickhouse} +# Что такое ClickHouse {#what-is-clickhouse} ClickHouse - столбцовая система управления базами данных (СУБД) для онлайн обработки аналитических запросов (OLAP). diff --git a/docs/ru/interfaces/cli.md b/docs/ru/interfaces/cli.md index b1d8c4f0732..3f6b288fc2b 100644 --- a/docs/ru/interfaces/cli.md +++ b/docs/ru/interfaces/cli.md @@ -1,6 +1,6 @@ --- toc_priority: 17 -toc_title: "\u041a\u043b\u0438\u0435\u043d\u0442\u0020\u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439\u0020\u0441\u0442\u0440\u043e\u043a\u0438" +toc_title: "Клиент командной строки" --- # Клиент командной строки {#klient-komandnoi-stroki} diff --git a/docs/ru/interfaces/cpp.md b/docs/ru/interfaces/cpp.md index 264b4f82500..018f4e22e34 100644 --- a/docs/ru/interfaces/cpp.md +++ b/docs/ru/interfaces/cpp.md @@ -1,6 +1,6 @@ --- toc_priority: 24 -toc_title: "\u0043\u002b\u002b\u0020\u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f\u0020\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430" +toc_title: "C++ клиентская библиотека" --- # C++ клиентская библиотека {#c-klientskaia-biblioteka} diff --git a/docs/ru/interfaces/formats.md b/docs/ru/interfaces/formats.md index 98426b489e8..edea533b642 100644 --- a/docs/ru/interfaces/formats.md +++ b/docs/ru/interfaces/formats.md @@ -1,6 +1,6 @@ --- toc_priority: 21 -toc_title: "\u0424\u043e\u0440\u043c\u0430\u0442\u044b\u0020\u0432\u0445\u043e\u0434\u043d\u044b\u0445\u0020\u0438\u0020\u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445\u0020\u0434\u0430\u043d\u043d\u044b\u0445" +toc_title: "Форматы входных и выходных данных" --- # Форматы входных и выходных данных {#formats} diff --git a/docs/ru/interfaces/http.md b/docs/ru/interfaces/http.md index 096fb6c05bc..5cb50d8f168 100644 --- a/docs/ru/interfaces/http.md +++ b/docs/ru/interfaces/http.md @@ -1,6 +1,6 @@ --- toc_priority: 19 -toc_title: "\u0048\u0054\u0054\u0050\u002d\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441" +toc_title: "HTTP-интерфейс" --- # HTTP-интерфейс {#http-interface} @@ -149,28 +149,48 @@ $ echo 'DROP TABLE t' | curl 'http://localhost:8123/' --data-binary @- Для запросов, которые не возвращают таблицу с данными, в случае успеха, выдаётся пустое тело ответа. -Вы можете использовать внутренний формат сжатия Clickhouse при передаче данных. Формат сжатых данных нестандартный, и вам придётся использовать для работы с ним специальную программу `clickhouse-compressor` (устанавливается вместе с пакетом `clickhouse-client`). Для повышения эффективности вставки данных можно отключить проверку контрольной суммы на стороне сервера с помощью настройки[http_native_compression_disable_checksumming_on_decompress](../operations/settings/settings.md#settings-http_native_compression_disable_checksumming_on_decompress). -Если вы указали `compress = 1` в URL, то сервер сжимает данные, которые он отправляет. -Если вы указали `decompress = 1` в URL, сервер распаковывает те данные, которые вы передаёте методом `POST`. +## Сжатие {#compression} -Также, можно использовать [HTTP compression](https://en.wikipedia.org/wiki/HTTP_compression). Для отправки сжатого запроса `POST`, добавьте заголовок `Content-Encoding: compression_method`. Чтобы ClickHouse сжимал ответ, добавьте заголовок `Accept-Encoding: compression_method`. ClickHouse поддерживает следующие [методы сжатия](https://en.wikipedia.org/wiki/HTTP_compression#Content-Encoding_tokens): `gzip`, `br`, and `deflate`. Чтобы включить HTTP compression, используйте настройку ClickHouse [enable_http_compression](../operations/settings/settings.md#settings-enable_http_compression). Уровень сжатия данных для всех методов сжатия можно настроить с помощью настройки [http_zlib_compression_level](#settings-http_zlib_compression_level). +Сжатие можно использовать для уменьшения трафика по сети при передаче большого количества данных, а также для создания сразу сжатых дампов. -Это может быть использовано для уменьшения трафика по сети при передаче большого количества данных, а также для создания сразу сжатых дампов. +Вы можете использовать внутренний формат сжатия Clickhouse при передаче данных. Формат сжатых данных нестандартный, и вам придётся использовать для работы с ним специальную программу `clickhouse-compressor`. Она устанавливается вместе с пакетом `clickhouse-client`. Для повышения эффективности вставки данных можно отключить проверку контрольной суммы на стороне сервера с помощью настройки [http_native_compression_disable_checksumming_on_decompress](../operations/settings/settings.md#settings-http_native_compression_disable_checksumming_on_decompress). -Примеры отправки данных со сжатием: +Если вы указали `compress=1` в URL, то сервер сжимает данные, которые он отправляет. Если вы указали `decompress=1` в URL, сервер распаковывает те данные, которые вы передаёте методом `POST`. -``` bash -$ #Отправка данных на сервер: -$ curl -vsS "http://localhost:8123/?enable_http_compression=1" -d 'SELECT number FROM system.numbers LIMIT 10' -H 'Accept-Encoding: gzip' +Также можно использовать [сжатие HTTP](https://en.wikipedia.org/wiki/HTTP_compression). ClickHouse поддерживает следующие [методы сжатия](https://en.wikipedia.org/wiki/HTTP_compression#Content-Encoding_tokens): -$ #Отправка данных клиенту: -$ echo "SELECT 1" | gzip -c | curl -sS --data-binary @- -H 'Content-Encoding: gzip' 'http://localhost:8123/' -``` +- `gzip` +- `br` +- `deflate` +- `xz` + +Для отправки сжатого запроса `POST`, добавьте заголовок `Content-Encoding: compression_method`. +Чтобы ClickHouse сжимал ответ, разрешите сжатие настройкой [enable_http_compression](../operations/settings/settings.md#settings-enable_http_compression) и добавьте заголовок `Accept-Encoding: compression_method`. Уровень сжатия данных для всех методов сжатия можно задать с помощью настройки [http_zlib_compression_level](../operations/settings/settings.md#settings-http_zlib_compression_level). !!! note "Примечание" Некоторые HTTP-клиенты могут по умолчанию распаковывать данные (`gzip` и `deflate`) с сервера в фоновом режиме и вы можете получить распакованные данные, даже если правильно используете настройки сжатия. +**Примеры** + +``` bash +# Отправка сжатых данных на сервер +$ echo "SELECT 1" | gzip -c | \ + curl -sS --data-binary @- -H 'Content-Encoding: gzip' 'http://localhost:8123/' +``` + +``` bash +# Получение сжатых данных с сервера +$ curl -vsS "http://localhost:8123/?enable_http_compression=1" \ + -H 'Accept-Encoding: gzip' --output result.gz -d 'SELECT number FROM system.numbers LIMIT 3' +$ zcat result.gz +0 +1 +2 +``` + +## База данных по умолчанию {#default-database} + Вы можете использовать параметр URL `database` или заголовок `X-ClickHouse-Database`, чтобы указать БД по умолчанию. ``` bash diff --git a/docs/ru/interfaces/index.md b/docs/ru/interfaces/index.md index ea381c46206..fc8743b3c1e 100644 --- a/docs/ru/interfaces/index.md +++ b/docs/ru/interfaces/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u0418\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044B" +toc_folder_title: "Интерфейсы" toc_priority: 14 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043D\u0438\u0435" +toc_title: "Введение" --- # Интерфейсы {#interfaces} diff --git a/docs/ru/interfaces/jdbc.md b/docs/ru/interfaces/jdbc.md index 196dba64933..ac86375c74f 100644 --- a/docs/ru/interfaces/jdbc.md +++ b/docs/ru/interfaces/jdbc.md @@ -1,6 +1,6 @@ --- toc_priority: 22 -toc_title: "\u004a\u0044\u0042\u0043\u002d\u0434\u0440\u0430\u0439\u0432\u0435\u0440" +toc_title: "JDBC-драйвер" --- # JDBC-драйвер {#jdbc-draiver} diff --git a/docs/ru/interfaces/mysql.md b/docs/ru/interfaces/mysql.md index fa0003e0bea..925b1113109 100644 --- a/docs/ru/interfaces/mysql.md +++ b/docs/ru/interfaces/mysql.md @@ -1,6 +1,6 @@ --- toc_priority: 20 -toc_title: "\u004d\u0079\u0053\u0051\u004c\u002d\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441" +toc_title: "MySQL-интерфейс" --- # MySQL-интерфейс {#mysql-interface} diff --git a/docs/ru/interfaces/odbc.md b/docs/ru/interfaces/odbc.md index 728c4bd6979..7843d3cb943 100644 --- a/docs/ru/interfaces/odbc.md +++ b/docs/ru/interfaces/odbc.md @@ -1,6 +1,6 @@ --- toc_priority: 23 -toc_title: "\u004f\u0044\u0042\u0043\u002d\u0434\u0440\u0430\u0439\u0432\u0435\u0440" +toc_title: "ODBC-драйвер" --- diff --git a/docs/ru/interfaces/tcp.md b/docs/ru/interfaces/tcp.md index d89646f15b7..ea8c170009d 100644 --- a/docs/ru/interfaces/tcp.md +++ b/docs/ru/interfaces/tcp.md @@ -1,6 +1,6 @@ --- toc_priority: 18 -toc_title: "\u0420\u043e\u0434\u043d\u043e\u0439\u0020\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0020\u0028\u0054\u0043\u0050\u0029" +toc_title: "Родной интерфейс (TCP)" --- # Родной интерфейс (TCP) {#rodnoi-interfeis-tcp} diff --git a/docs/ru/interfaces/third-party/client-libraries.md b/docs/ru/interfaces/third-party/client-libraries.md index 26e05b02509..65e93731300 100644 --- a/docs/ru/interfaces/third-party/client-libraries.md +++ b/docs/ru/interfaces/third-party/client-libraries.md @@ -1,6 +1,6 @@ --- toc_priority: 26 -toc_title: "\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435\u0020\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438\u0020\u043e\u0442\u0020\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445\u0020\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432" +toc_title: "Клиентские библиотеки от сторонних разработчиков" --- # Клиентские библиотеки от сторонних разработчиков {#klientskie-biblioteki-ot-storonnikh-razrabotchikov} @@ -22,6 +22,7 @@ toc_title: "\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435\u0020\u - [seva-code/php-click-house-client](https://packagist.org/packages/seva-code/php-click-house-client) - [SeasClick C++ client](https://github.com/SeasX/SeasClick) - [glushkovds/phpclickhouse-laravel](https://packagist.org/packages/glushkovds/phpclickhouse-laravel) + - [kolya7k ClickHouse PHP extension](https://github.com//kolya7k/clickhouse-php) - Go - [clickhouse](https://github.com/kshvakov/clickhouse/) - [go-clickhouse](https://github.com/roistat/go-clickhouse) diff --git a/docs/ru/interfaces/third-party/gui.md b/docs/ru/interfaces/third-party/gui.md index 1fabdb8a31c..c02c32e08f4 100644 --- a/docs/ru/interfaces/third-party/gui.md +++ b/docs/ru/interfaces/third-party/gui.md @@ -1,6 +1,6 @@ --- toc_priority: 28 -toc_title: "\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0435\u0020\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b\u0020\u043e\u0442\u0020\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445\u0020\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432" +toc_title: "Визуальные интерфейсы от сторонних разработчиков" --- diff --git a/docs/ru/interfaces/third-party/index.md b/docs/ru/interfaces/third-party/index.md index a57169df73b..8b59bb5fd28 100644 --- a/docs/ru/interfaces/third-party/index.md +++ b/docs/ru/interfaces/third-party/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0421\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0435\u0020\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b" +toc_folder_title: "Сторонние интерфейсы" toc_priority: 24 --- diff --git a/docs/ru/interfaces/third-party/integrations.md b/docs/ru/interfaces/third-party/integrations.md index 60d6181ab3f..84d5b93f92f 100644 --- a/docs/ru/interfaces/third-party/integrations.md +++ b/docs/ru/interfaces/third-party/integrations.md @@ -1,6 +1,6 @@ --- toc_priority: 27 -toc_title: "\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438\u0020\u0434\u043b\u044f\u0020\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438\u0020\u043e\u0442\u0020\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445\u0020\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432" +toc_title: "Библиотеки для интеграции от сторонних разработчиков" --- # Библиотеки для интеграции от сторонних разработчиков {#biblioteki-dlia-integratsii-ot-storonnikh-razrabotchikov} diff --git a/docs/ru/interfaces/third-party/proxy.md b/docs/ru/interfaces/third-party/proxy.md index fc66ecde293..48853cb352e 100644 --- a/docs/ru/interfaces/third-party/proxy.md +++ b/docs/ru/interfaces/third-party/proxy.md @@ -1,6 +1,6 @@ --- toc_priority: 29 -toc_title: "\u041f\u0440\u043e\u043a\u0441\u0438\u002d\u0441\u0435\u0440\u0432\u0435\u0440\u044b\u0020\u043e\u0442\u0020\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445\u0020\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432" +toc_title: "Прокси-серверы от сторонних разработчиков" --- # Прокси-серверы от сторонних разработчиков {#proksi-servery-ot-storonnikh-razrabotchikov} diff --git a/docs/ru/introduction/distinctive-features.md b/docs/ru/introduction/distinctive-features.md index 4eeeef4a443..852f5cecd5b 100644 --- a/docs/ru/introduction/distinctive-features.md +++ b/docs/ru/introduction/distinctive-features.md @@ -1,6 +1,6 @@ --- toc_priority: 4 -toc_title: "\u041e\u0442\u043b\u0438\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435\u0020\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\u0020\u0043\u006c\u0069\u0063\u006b\u0048\u006f\u0075\u0073\u0065" +toc_title: "Отличительные возможности ClickHouse" --- # Отличительные возможности ClickHouse {#otlichitelnye-vozmozhnosti-clickhouse} diff --git a/docs/ru/introduction/history.md b/docs/ru/introduction/history.md index ab740954bbe..ad17b2be27d 100644 --- a/docs/ru/introduction/history.md +++ b/docs/ru/introduction/history.md @@ -1,6 +1,6 @@ --- toc_priority: 7 -toc_title: "\u0418\u0441\u0442\u043e\u0440\u0438\u044f\u0020\u0043\u006c\u0069\u0063\u006b\u0048\u006f\u0075\u0073\u0065" +toc_title: "История ClickHouse" --- diff --git a/docs/ru/introduction/index.md b/docs/ru/introduction/index.md index 28a8e10e15b..c37cde09060 100644 --- a/docs/ru/introduction/index.md +++ b/docs/ru/introduction/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0412\u0432\u0435\u0434\u0435\u043D\u0438\u0435" +toc_folder_title: "Введение" toc_priority: 1 --- diff --git a/docs/ru/introduction/performance.md b/docs/ru/introduction/performance.md index c449e76a6ea..dd92d3df9f5 100644 --- a/docs/ru/introduction/performance.md +++ b/docs/ru/introduction/performance.md @@ -1,6 +1,6 @@ --- toc_priority: 6 -toc_title: "\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c" +toc_title: "Производительность" --- # Производительность {#proizvoditelnost} diff --git a/docs/ru/operations/access-rights.md b/docs/ru/operations/access-rights.md index 00e55da7a82..9aa4e5f2561 100644 --- a/docs/ru/operations/access-rights.md +++ b/docs/ru/operations/access-rights.md @@ -1,6 +1,6 @@ --- toc_priority: 48 -toc_title: "\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u0020\u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c" +toc_title: "Управление доступом" --- # Управление доступом {#access-control} diff --git a/docs/ru/operations/backup.md b/docs/ru/operations/backup.md index 165b54d9b62..703217e8547 100644 --- a/docs/ru/operations/backup.md +++ b/docs/ru/operations/backup.md @@ -1,6 +1,6 @@ --- toc_priority: 49 -toc_title: "\u0420\u0435\u0437\u0435\u0440\u0432\u043d\u043e\u0435\u0020\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u0020\u0434\u0430\u043d\u043d\u044b\u0445" +toc_title: "Резервное копирование данных" --- # Резервное копирование данных {#rezervnoe-kopirovanie-dannykh} diff --git a/docs/ru/operations/caches.md b/docs/ru/operations/caches.md new file mode 100644 index 00000000000..7744c596cd9 --- /dev/null +++ b/docs/ru/operations/caches.md @@ -0,0 +1,29 @@ +--- +toc_priority: 65 +toc_title: Кеши +--- + +# Типы кеша {#cache-types} + +При выполнении запросов ClickHouse использует различные типы кеша. + +Основные типы кеша: + +- `mark_cache` — кеш засечек, используемых движками таблиц семейства [MergeTree](../engines/table-engines/mergetree-family/mergetree.md). +- `uncompressed_cache` — кеш несжатых данных, используемых движками таблиц семейства [MergeTree](../engines/table-engines/mergetree-family/mergetree.md). + +Дополнительные типы кеша: + +- DNS-кеш. +- Кеш данных формата [regexp](../interfaces/formats.md#data-format-regexp). +- Кеш скомпилированных выражений. +- Кеш схем формата [Avro](../interfaces/formats.md#data-format-avro). +- Кеш данных в [словарях](../sql-reference/dictionaries/index.md). + +Непрямое использование: + +- Кеш страницы ОС. + +Чтобы очистить кеш, используйте выражение [SYSTEM DROP ... CACHE](../sql-reference/statements/system.md). + +[Оригинальная статья](https://clickhouse.tech/docs/ru/operations/caches/) diff --git a/docs/ru/operations/configuration-files.md b/docs/ru/operations/configuration-files.md index a4cc9182427..84b26d0ba2a 100644 --- a/docs/ru/operations/configuration-files.md +++ b/docs/ru/operations/configuration-files.md @@ -1,6 +1,6 @@ --- toc_priority: 50 -toc_title: "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435\u0020\u0444\u0430\u0439\u043b\u044b" +toc_title: "Конфигурационные файлы" --- diff --git a/docs/ru/operations/index.md b/docs/ru/operations/index.md index 74a1d135967..99dcf652891 100644 --- a/docs/ru/operations/index.md +++ b/docs/ru/operations/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u042d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u044f" +toc_folder_title: "Эксплуатация" toc_priority: 41 -toc_title: "\u042d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u044f" +toc_title: "Эксплуатация" --- # Эксплуатация {#operations} diff --git a/docs/ru/operations/monitoring.md b/docs/ru/operations/monitoring.md index 52d0b5ecc8a..7656b04d011 100644 --- a/docs/ru/operations/monitoring.md +++ b/docs/ru/operations/monitoring.md @@ -1,6 +1,6 @@ --- toc_priority: 45 -toc_title: "\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433" +toc_title: "Мониторинг" --- # Мониторинг {#monitoring} diff --git a/docs/ru/operations/opentelemetry.md b/docs/ru/operations/opentelemetry.md new file mode 100644 index 00000000000..a60f1b3e085 --- /dev/null +++ b/docs/ru/operations/opentelemetry.md @@ -0,0 +1,37 @@ +--- +toc_priority: 62 +toc_title: Поддержка OpenTelemetry +--- + +# [экспериментально] Поддержка OpenTelemetry + +ClickHouse поддерживает [OpenTelemetry](https://opentelemetry.io/) — открытый стандарт для сбора трассировок и метрик из распределенного приложения. + +!!! warning "Предупреждение" +Поддержка стандарта экспериментальная и будет со временем меняться. + +## Обеспечение поддержки контекста трассировки в ClickHouse + +ClickHouse принимает контекстную информацию трассировки через HTTP заголовок `tracecontext`, как описано в [рекомендации W3C](https://www.w3.org/TR/trace-context/). Также он принимает контекстную информацию через нативный протокол, который используется для связи между серверами ClickHouse или между клиентом и сервером. Для ручного тестирования стандартный заголовок `tracecontext`, содержащий контекст трассировки, может быть передан в `clickhouse-client` через флаги: `--opentelemetry-traceparent` и `--opentelemetry-tracestate`. + +Если входящий контекст трассировки не указан, ClickHouse может начать трассировку с вероятностью, задаваемой настройкой [opentelemetry_start_trace_probability](../operations/settings/settings.md#opentelemetry-start-trace-probability). + +## Распространение контекста трассировки + +Контекст трассировки распространяется на нижестоящие сервисы в следующих случаях: + +* При использовании запросов к удаленным серверам ClickHouse, например, при использовании движка таблиц [Distributed](../engines/table-engines/special/distributed.md). + +* При использовании табличной функции [url](../sql-reference/table-functions/url.md). Информация контекста трассировки передается в HTTP заголовки. + +## Как ClickHouse выполняет трассировку + +ClickHouse создает `trace spans` для каждого запроса и некоторых этапов выполнения запроса, таких как планирование запросов или распределенные запросы. + +Чтобы анализировать информацию трассировки, ее следует экспортировать в систему мониторинга, поддерживающую OpenTelemetry, такую как [Jaeger](https://jaegertracing.io/) или [Prometheus](https://prometheus.io/). ClickHouse не зависит от конкретной системы мониторинга, вместо этого предоставляя данные трассировки только через системную таблицу. Информация о диапазоне трассировки в OpenTelemetry, [требуемая стандартом](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/overview.md#span), хранится в системной таблице [system.opentelemetry_span_log](../operations/system-tables/opentelemetry_span_log.md). + +Таблица должна быть включена в конфигурации сервера, смотрите элемент `opentelemetry_span_log` в файле конфигурации `config.xml`. По умолчанию таблица включена всегда. + +Теги или атрибуты сохраняются в виде двух параллельных массивов, содержащих ключи и значения. Для работы с ними используйте [ARRAY JOIN](../sql-reference/statements/select/array-join.md). + +[Оригинальная статья](https://clickhouse.tech/docs/ru/operations/opentelemetry/) diff --git a/docs/ru/operations/quotas.md b/docs/ru/operations/quotas.md index 92533eef0c1..31f3a66a1c3 100644 --- a/docs/ru/operations/quotas.md +++ b/docs/ru/operations/quotas.md @@ -1,6 +1,6 @@ --- toc_priority: 51 -toc_title: "\u041a\u0432\u043e\u0442\u044b" +toc_title: "Квоты" --- # Квоты {#quotas} diff --git a/docs/ru/operations/requirements.md b/docs/ru/operations/requirements.md index 36a7dd30b34..6567dcc9695 100644 --- a/docs/ru/operations/requirements.md +++ b/docs/ru/operations/requirements.md @@ -1,6 +1,6 @@ --- toc_priority: 44 -toc_title: "\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f" +toc_title: "Требования" --- # Требования {#trebovaniia} diff --git a/docs/ru/operations/server-configuration-parameters/index.md b/docs/ru/operations/server-configuration-parameters/index.md index a691fe69fef..f511955ebc4 100644 --- a/docs/ru/operations/server-configuration-parameters/index.md +++ b/docs/ru/operations/server-configuration-parameters/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435\u0020\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b\u0020\u0441\u0435\u0440\u0432\u0435\u0440\u0430" +toc_folder_title: "Конфигурационные параметры сервера" toc_priority: 54 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435" +toc_title: "Введение" --- # Конфигурационные параметры сервера {#server-settings} diff --git a/docs/ru/operations/server-configuration-parameters/settings.md b/docs/ru/operations/server-configuration-parameters/settings.md index 15ab13836e3..f46d899a3b7 100644 --- a/docs/ru/operations/server-configuration-parameters/settings.md +++ b/docs/ru/operations/server-configuration-parameters/settings.md @@ -1,6 +1,6 @@ --- toc_priority: 57 -toc_title: "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435\u0020\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b\u0020\u0441\u0435\u0440\u0432\u0435\u0440\u0430" +toc_title: "Конфигурационные параметры сервера" --- # Конфигурационные параметры сервера {#server-configuration-parameters-reference} diff --git a/docs/ru/operations/settings/constraints-on-settings.md b/docs/ru/operations/settings/constraints-on-settings.md index b23be22958c..a4c1876574d 100644 --- a/docs/ru/operations/settings/constraints-on-settings.md +++ b/docs/ru/operations/settings/constraints-on-settings.md @@ -1,6 +1,6 @@ --- toc_priority: 62 -toc_title: "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u0020\u043d\u0430\u0020\u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u0020\u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a" +toc_title: "Ограничения на изменение настроек" --- # Ограничения на изменение настроек {#constraints-on-settings} diff --git a/docs/ru/operations/settings/permissions-for-queries.md b/docs/ru/operations/settings/permissions-for-queries.md index ae896dac77c..571f56fc3bd 100644 --- a/docs/ru/operations/settings/permissions-for-queries.md +++ b/docs/ru/operations/settings/permissions-for-queries.md @@ -1,6 +1,6 @@ --- toc_priority: 58 -toc_title: "\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f\u0020\u0434\u043b\u044f\u0020\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432" +toc_title: "Разрешения для запросов" --- # Разрешения для запросов {#permissions_for_queries} diff --git a/docs/ru/operations/settings/query-complexity.md b/docs/ru/operations/settings/query-complexity.md index b0eac5d96e7..c6e580a2209 100644 --- a/docs/ru/operations/settings/query-complexity.md +++ b/docs/ru/operations/settings/query-complexity.md @@ -1,6 +1,6 @@ --- toc_priority: 59 -toc_title: "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u0020\u043d\u0430\u0020\u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u0020\u0437\u0430\u043f\u0440\u043e\u0441\u0430" +toc_title: "Ограничения на сложность запроса" --- # Ограничения на сложность запроса {#restrictions-on-query-complexity} diff --git a/docs/ru/operations/settings/settings-profiles.md b/docs/ru/operations/settings/settings-profiles.md index 10feda01850..e8082919d89 100644 --- a/docs/ru/operations/settings/settings-profiles.md +++ b/docs/ru/operations/settings/settings-profiles.md @@ -1,6 +1,6 @@ --- toc_priority: 61 -toc_title: "\u041f\u0440\u043e\u0444\u0438\u043b\u0438\u0020\u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a" +toc_title: "Профили настроек" --- # Профили настроек {#settings-profiles} diff --git a/docs/ru/operations/settings/settings-users.md b/docs/ru/operations/settings/settings-users.md index 2069922d0ea..21cd78569df 100644 --- a/docs/ru/operations/settings/settings-users.md +++ b/docs/ru/operations/settings/settings-users.md @@ -1,6 +1,6 @@ --- toc_priority: 63 -toc_title: "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u0020\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439" +toc_title: "Настройки пользователей" --- # Настройки пользователей {#nastroiki-polzovatelei} diff --git a/docs/ru/operations/settings/settings.md b/docs/ru/operations/settings/settings.md index 1352fe850df..663821158bd 100644 --- a/docs/ru/operations/settings/settings.md +++ b/docs/ru/operations/settings/settings.md @@ -1,6 +1,6 @@ --- toc_priority: 60 -toc_title: "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438" +toc_title: "Настройки" --- # Настройки {#settings} @@ -283,12 +283,10 @@ INSERT INTO test VALUES (lower('Hello')), (lower('world')), (lower('INSERT')), ( ## input_format_tsv_empty_as_default {#settings-input-format-tsv-empty-as-default} -Если эта настройка включена, замените пустые поля ввода в TSV значениями по умолчанию. Для сложных выражений по умолчанию также должна быть включена настройка `input_format_defaults_for_omitted_fields`. +Если эта настройка включена, все пустые поля во входящем TSV заменяются значениями по умолчанию. Для сложных выражений по умолчанию также должна быть включена настройка `input_format_defaults_for_omitted_fields`. По умолчанию отключена. -Disabled by default. - ## input_format_tsv_enum_as_number {#settings-input_format_tsv_enum_as_number} Включает или отключает парсинг значений перечислений как идентификаторов перечислений для входного формата TSV. @@ -708,7 +706,7 @@ ClickHouse использует этот параметр при чтении д Установка логирования запроса. -Запросы, переданные в ClickHouse с этой установкой, логируются согласно правилам конфигурационного параметра сервера [query_log](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-query-log). +Запросы, переданные в ClickHouse с этой настройкой, логируются согласно правилам конфигурационного параметра сервера [query_log](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-query-log). Пример: @@ -1521,7 +1519,7 @@ ClickHouse генерирует исключение - Тип: секунды - Значение по умолчанию: 60 секунд -Управляет скоростью обнуления ошибок в распределенных таблицах. Если реплика недоступна в течение некоторого времени, накапливает 5 ошибок, а distributed_replica_error_half_life установлена на 1 секунду, то реплика считается нормальной через 3 секунды после последней ошибки. +Управляет скоростью обнуления счетчика ошибок в распределенных таблицах. Предположим, реплика остается недоступна в течение какого-то времени, и за этот период накопилось 5 ошибок. Если настройка `distributed_replica_error_half_life` установлена в значение 1 секунда, то реплика снова будет считаться доступной через 3 секунды после последней ошибки. См. также: @@ -1673,7 +1671,7 @@ ClickHouse генерирует исключение - Тип: bool - Значение по умолчанию: True -Обеспечивает параллельный анализ форматов данных с сохранением порядка. Поддерживается только для форматов TSV, TKSV, CSV и JSONEachRow. +Включает режим, при котором входящие данные парсятся параллельно, но с сохранением исходного порядка следования. Поддерживается только для форматов TSV, TKSV, CSV и JSONEachRow. ## min_chunk_bytes_for_parallel_parsing {#min-chunk-bytes-for-parallel-parsing} @@ -1939,6 +1937,21 @@ SELECT idx, i FROM null_in WHERE i IN (1, NULL) SETTINGS transform_null_in = 1; Значение по умолчанию: 16. +## background_message_broker_schedule_pool_size {#background_message_broker_schedule_pool_size} + +Задает количество потоков для фонового потокового вывода сообщений. Настройка применяется при запуске сервера ClickHouse и не может быть изменена в пользовательском сеансе. + +Допустимые значения: + +- Положительное целое число. + +Значение по умолчанию: 16. + +**Смотрите также** + +- Движок [Kafka](../../engines/table-engines/integrations/kafka.md#kafka). +- Движок [RabbitMQ](../../engines/table-engines/integrations/rabbitmq.md#rabbitmq-engine). + ## format_avro_schema_registry_url {#format_avro_schema_registry_url} Задает URL реестра схем [Confluent](https://docs.confluent.io/current/schema-registry/index.html) для использования с форматом [AvroConfluent](../../interfaces/formats.md#data-format-avro-confluent). @@ -1987,7 +2000,7 @@ SELECT idx, i FROM null_in WHERE i IN (1, NULL) SETTINGS transform_null_in = 1; ## output_format_pretty_grid_charset {#output-format-pretty-grid-charset} -Позволяет изменить кодировку, которая используется для печати грид-границ. Доступны следующие кодировки: UTF-8, ASCII. +Позволяет изменить кодировку, которая используется для отрисовки таблицы при выводе результатов запросов. Доступны следующие кодировки: UTF-8, ASCII. **Пример** @@ -2473,6 +2486,18 @@ SELECT SUM(-1), MAX(0) FROM system.one WHERE 0; Значение по умолчанию: `16`. +## opentelemetry_start_trace_probability {#opentelemetry-start-trace-probability} + +Задает вероятность того, что ClickHouse начнет трассировку для выполненных запросов (если не указан [входящий контекст](https://www.w3.org/TR/trace-context/) трассировки). + +Возможные значения: + +- 0 — трассировка для выполненных запросов отключена (если не указан входящий контекст трассировки). +- Положительное число с плавающей точкой в диапазоне [0..1]. Например, при значении настройки, равной `0,5`, ClickHouse начнет трассировку в среднем для половины запросов. +- 1 — трассировка для всех выполненных запросов включена. + +Значение по умолчанию: `0`. + ## optimize_on_insert {#optimize-on-insert} Включает или выключает преобразование данных перед добавлением в таблицу, как будто над добавляемым блоком предварительно было произведено слияние (в соответствии с движком таблицы). @@ -2527,4 +2552,15 @@ SELECT * FROM test2; Обратите внимание на то, что эта настройка влияет на поведение [материализованных представлений](../../sql-reference/statements/create/view.md#materialized) и БД [MaterializeMySQL](../../engines/database-engines/materialize-mysql.md). +## allow_experimental_geo_types {#allow-experimental-geo-types} + +Разрешает использование экспериментальных типов данных для работы с [географическими структурами](../../sql-reference/data-types/geo.md). + +Возможные значения: + +- 0 — Использование типов данных для работы с географическими структурами не поддерживается. +- 1 — Использование типов данных для работы с географическими структурами поддерживается. + +Значение по умолчанию: `0`. + [Оригинальная статья](https://clickhouse.tech/docs/ru/operations/settings/settings/) diff --git a/docs/ru/operations/system-tables/distributed_ddl_queue.md b/docs/ru/operations/system-tables/distributed_ddl_queue.md index 058ed06f639..71be69e98d7 100644 --- a/docs/ru/operations/system-tables/distributed_ddl_queue.md +++ b/docs/ru/operations/system-tables/distributed_ddl_queue.md @@ -14,7 +14,7 @@ - `initiator` ([String](../../sql-reference/data-types/string.md)) — узел, выполнивший запрос. - `query_start_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — время начала запроса. - `query_finish_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — время окончания запроса. -- `query_duration_ms` ([UInt64](../../sql-reference/data-types/datetime64.md)) — продолжительность выполнения запроса (в миллисекундах). +- `query_duration_ms` ([UInt64](../../sql-reference/data-types/int-uint.md)) — продолжительность выполнения запроса (в миллисекундах). - `exception_code` ([Enum8](../../sql-reference/data-types/enum.md)) — код исключения из [ZooKeeper](../../operations/tips.md#zookeeper). **Пример** diff --git a/docs/ru/operations/system-tables/index.md b/docs/ru/operations/system-tables/index.md index 93ea1c92068..e4b6f5beb9d 100644 --- a/docs/ru/operations/system-tables/index.md +++ b/docs/ru/operations/system-tables/index.md @@ -1,6 +1,6 @@ --- toc_priority: 52 -toc_title: "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435\u0020\u0442\u0430\u0431\u043b\u0438\u0446\u044b" +toc_title: "Системные таблицы" --- # Системные таблицы {#system-tables} @@ -9,25 +9,54 @@ toc_title: "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435\u0020\u0442\u Системные таблицы содержат информацию о: -- Состоянии сервера, процессов и окружении. -- Внутренних процессах сервера. +- состоянии сервера, процессов и окружении. +- внутренних процессах сервера. Системные таблицы: -- Находятся в базе данных `system`. -- Доступны только для чтения данных. -- Не могут быть удалены или изменены, но их можно отсоединить. +- находятся в базе данных `system`. +- доступны только для чтения данных. +- не могут быть удалены или изменены, но их можно отсоединить. -Системные таблицы `metric_log`, `query_log`, `query_thread_log`, `trace_log` системные таблицы хранят данные в файловой системе. Остальные системные таблицы хранят свои данные в оперативной памяти. Сервер ClickHouse создает такие системные таблицы при запуске. +Большинство системных таблиц хранят свои данные в оперативной памяти. Сервер ClickHouse создает эти системные таблицы при старте. + +В отличие от других системных таблиц, таблицы с системными логами [metric_log](../../operations/system-tables/metric_log.md), [query_log](../../operations/system-tables/query_log.md), [query_thread_log](../../operations/system-tables/query_thread_log.md), [trace_log](../../operations/system-tables/trace_log.md), [part_log](../../operations/system-tables/part_log.md), [crash_log](../../operations/system-tables/crash-log.md) и [text_log](../../operations/system-tables/text_log.md) используют движок таблиц [MergeTree](../../engines/table-engines/mergetree-family/mergetree.md) и по умолчанию хранят свои данные в файловой системе. Если удалить таблицу из файловой системы, сервер ClickHouse снова создаст пустую таблицу во время следующей записи данных. Если схема системной таблицы изменилась в новом релизе, то ClickHouse переименует текущую таблицу и создаст новую. + +Таблицы с системными логами `log` можно настроить, создав конфигурационный файл с тем же именем, что и таблица в разделе `/etc/clickhouse-server/config.d/`, или указав соответствующие элементы в `/etc/clickhouse-server/config.xml`. Настраиваться могут следующие элементы: + +- `database` — база данных, к которой принадлежит системная таблица. Эта опция на текущий момент устарела. Все системные таблицы находятся в базе данных `system`. +- `table` — таблица для добавления данных. +- `partition_by` — [ключ партиционирования](../../engines/table-engines/mergetree-family/custom-partitioning-key.md). +- `ttl` — [время жизни](../../sql-reference/statements/alter/ttl.md) таблицы. +- `flush_interval_milliseconds` — интервал сброса данных на диск, в миллисекундах. +- `engine` — полное имя движка (начиная с `ENGINE =` ) с параметрами. Эта опция противоречит `partition_by` и `ttl`. Если указать оба параметра вместе, сервер вернет ошибку и завершит работу. + +Пример: + +```xml + + + system + query_log
+ toYYYYMM(event_date) + event_date + INTERVAL 30 DAY DELETE + + 7500 +
+
+``` + +По умолчанию размер таблицы не ограничен. Управлять размером таблицы можно используя [TTL](../../sql-reference/statements/alter/ttl.md#manipuliatsii-s-ttl-tablitsy) для удаления устаревших записей журнала. Также вы можете использовать функцию партиционирования для таблиц `MergeTree`. ### Источники системных показателей Для сбора системных показателей сервер ClickHouse использует: -- Возможности `CAP_NET_ADMIN`. +- возможности `CAP_NET_ADMIN`. - [procfs](https://ru.wikipedia.org/wiki/Procfs) (только Linux). -**procfs** Если для сервера ClickHouse не включено `CAP_NET_ADMIN`, он пытается обратиться к `ProcfsMetricsProvider`. `ProcfsMetricsProvider` позволяет собирать системные показатели для каждого запроса (для CPU и I/O). diff --git a/docs/ru/operations/system-tables/opentelemetry_span_log.md b/docs/ru/operations/system-tables/opentelemetry_span_log.md new file mode 100644 index 00000000000..96555064b0e --- /dev/null +++ b/docs/ru/operations/system-tables/opentelemetry_span_log.md @@ -0,0 +1,49 @@ +# system.opentelemetry_span_log {#system_tables-opentelemetry_span_log} + +Содержит информацию о [trace spans](https://opentracing.io/docs/overview/spans/) для выполненных запросов. + +Столбцы: + +- `trace_id` ([UUID](../../sql-reference/data-types/uuid.md) — идентификатор трассировки для выполненного запроса. + +- `span_id` ([UInt64](../../sql-reference/data-types/int-uint.md)) — идентификатор `trace span`. + +- `parent_span_id` ([UInt64](../../sql-reference/data-types/int-uint.md)) — идентификатор родительского `trace span`. + +- `operation_name` ([String](../../sql-reference/data-types/string.md)) — имя операции. + +- `start_time_us` ([UInt64](../../sql-reference/data-types/int-uint.md)) — время начала `trace span` (в микросекундах). + +- `finish_time_us` ([UInt64](../../sql-reference/data-types/int-uint.md)) — время окончания `trace span` (в микросекундах). + +- `finish_date` ([Date](../../sql-reference/data-types/date.md)) — дата окончания `trace span`. + +- `attribute.names` ([Array](../../sql-reference/data-types/array.md)([String](../../sql-reference/data-types/string.md))) — имена [атрибутов](https://opentelemetry.io/docs/go/instrumentation/#attributes) в зависимости от `trace span`. Заполняются согласно рекомендациям в стандарте [OpenTelemetry](https://opentelemetry.io/). + +- `attribute.values` ([Array](../../sql-reference/data-types/array.md)([String](../../sql-reference/data-types/string.md))) — значения атрибутов в зависимости от `trace span`. Заполняются согласно рекомендациям в стандарте `OpenTelemetry`. + +**Пример** + +Запрос: + +``` sql +SELECT * FROM system.opentelemetry_span_log LIMIT 1 FORMAT Vertical; +``` + +Результат: + +``` text +Row 1: +────── +trace_id: cdab0847-0d62-61d5-4d38-dd65b19a1914 +span_id: 701487461015578150 +parent_span_id: 2991972114672045096 +operation_name: DB::Block DB::InterpreterSelectQuery::getSampleBlockImpl() +start_time_us: 1612374594529090 +finish_time_us: 1612374594529108 +finish_date: 2021-02-03 +attribute.names: [] +attribute.values: [] +``` + +[Оригинальная статья](https://clickhouse.tech/docs/ru/operations/system_tables/opentelemetry_span_log) diff --git a/docs/ru/operations/system-tables/part_log.md b/docs/ru/operations/system-tables/part_log.md index bba4fda6135..4157cd41bff 100644 --- a/docs/ru/operations/system-tables/part_log.md +++ b/docs/ru/operations/system-tables/part_log.md @@ -16,6 +16,7 @@ - `MOVE_PART` — перемещение куска между дисками. - `event_date` ([Date](../../sql-reference/data-types/date.md)) — дата события. - `event_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — время события. +- `event_time_microseconds` ([DateTime64](../../sql-reference/data-types/datetime64.md)) — время события с точностью до микросекунд. - `duration_ms` ([UInt64](../../sql-reference/data-types/int-uint.md)) — длительность. - `database` ([String](../../sql-reference/data-types/string.md)) — имя базы данных, в которой находится кусок. - `table` ([String](../../sql-reference/data-types/string.md)) — имя таблицы, в которой находится кусок. @@ -47,6 +48,7 @@ query_id: 983ad9c7-28d5-4ae1-844e-603116b7de31 event_type: NewPart event_date: 2021-02-02 event_time: 2021-02-02 11:14:28 +event_time_microseconds: 2021-02-02 11:14:28.861919 duration_ms: 35 database: default table: log_mt_2 diff --git a/docs/ru/operations/system-tables/settings.md b/docs/ru/operations/system-tables/settings.md index c1ada37131c..50ccac684c4 100644 --- a/docs/ru/operations/system-tables/settings.md +++ b/docs/ru/operations/system-tables/settings.md @@ -48,5 +48,6 @@ SELECT * FROM system.settings WHERE changed AND name='load_balancing' - [Настройки](../settings/index.md#settings) - [Разрешения для запросов](../settings/permissions-for-queries.md#settings_readonly) - [Ограничения для значений настроек](../settings/constraints-on-settings.md) +- Выражение [SHOW SETTINGS](../../sql-reference/statements/show.md#show-settings) [Оригинальная статья](https://clickhouse.tech/docs/ru/operations/system_tables/settings) diff --git a/docs/ru/operations/system-tables/trace_log.md b/docs/ru/operations/system-tables/trace_log.md index 3f0a16199d5..88f4b29651b 100644 --- a/docs/ru/operations/system-tables/trace_log.md +++ b/docs/ru/operations/system-tables/trace_log.md @@ -12,7 +12,7 @@ ClickHouse создает эту таблицу когда утсановлен - `event_time`([DateTime](../../sql-reference/data-types/datetime.md)) — дата и время в момент снятия экземпляра стэка адресов вызова. -- `event_time_microseconds` ([DateTime](../../sql-reference/data-types/datetime.md)) — дата и время в момент снятия экземпляра стэка адресов вызова с точностью до микросекунд. +- `event_time_microseconds` ([DateTime64](../../sql-reference/data-types/datetime64.md)) — дата и время в момент снятия экземпляра стэка адресов вызова с точностью до микросекунд. - `revision`([UInt32](../../sql-reference/data-types/int-uint.md)) — ревизия сборки сервера ClickHouse. @@ -50,4 +50,4 @@ trace: [371912858,371912789,371798468,371799717,371801313,3717 size: 5244400 ``` -[Оригинальная статья](https://clickhouse.tech/docs/ru/operations/system_tables/trace_log) +[Оригинальная статья](https://clickhouse.tech/docs/ru/operations/system-tables/trace_log) diff --git a/docs/ru/operations/tips.md b/docs/ru/operations/tips.md index 40035309c03..0a2ca5ecac1 100644 --- a/docs/ru/operations/tips.md +++ b/docs/ru/operations/tips.md @@ -1,6 +1,6 @@ --- toc_priority: 58 -toc_title: "\u0421\u043e\u0432\u0435\u0442\u044b\u0020\u043f\u043e\u0020\u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438" +toc_title: "Советы по эксплуатации" --- # Советы по эксплуатации {#sovety-po-ekspluatatsii} diff --git a/docs/ru/operations/troubleshooting.md b/docs/ru/operations/troubleshooting.md index 3df2a1dd46c..5882bc36f9e 100644 --- a/docs/ru/operations/troubleshooting.md +++ b/docs/ru/operations/troubleshooting.md @@ -1,6 +1,6 @@ --- toc_priority: 46 -toc_title: "\u0423\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u0020\u043d\u0435\u0438\u0441\u043f\u0440\u0430\u0432\u043d\u043e\u0441\u0442\u0435\u0439" +toc_title: "Устранение неисправностей" --- # Устранение неисправностей {#ustranenie-neispravnostei} diff --git a/docs/ru/operations/update.md b/docs/ru/operations/update.md index c74b28b3fd7..5c187ed1604 100644 --- a/docs/ru/operations/update.md +++ b/docs/ru/operations/update.md @@ -1,6 +1,6 @@ --- toc_priority: 47 -toc_title: "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u0020\u0043\u006c\u0069\u0063\u006b\u0048\u006f\u0075\u0073\u0065" +toc_title: "Обновление ClickHouse" --- # Обновление ClickHouse {#obnovlenie-clickhouse} diff --git a/docs/ru/operations/utilities/clickhouse-local.md b/docs/ru/operations/utilities/clickhouse-local.md index 2b5c9b119e2..137472fa993 100644 --- a/docs/ru/operations/utilities/clickhouse-local.md +++ b/docs/ru/operations/utilities/clickhouse-local.md @@ -14,14 +14,15 @@ toc_title: clickhouse-local !!! warning "Warning" Мы не рекомендуем подключать серверную конфигурацию к `clickhouse-local`, поскольку данные можно легко повредить неосторожными действиями. -Для временных данных по умолчанию создается специальный каталог. Если вы хотите обойти это действие, каталог данных можно указать с помощью опции `-- --path`. +Для временных данных по умолчанию создается специальный каталог. -## Вызов программы {#vyzov-programmy} +## Вызов программы {#usage} Основной формат вызова: ``` bash -$ clickhouse-local --structure "table_structure" --input-format "format_of_incoming_data" -q "query" +$ clickhouse-local --structure "table_structure" --input-format "format_of_incoming_data" \ + --query "query" ``` Ключи команды: @@ -30,15 +31,23 @@ $ clickhouse-local --structure "table_structure" --input-format "format_of_incom - `-if`, `--input-format` — формат входящих данных. По умолчанию — `TSV`. - `-f`, `--file` — путь к файлу с данными. По умолчанию — `stdin`. - `-q`, `--query` — запросы на выполнение. Разделитель запросов — `;`. +- `-qf`, `--queries-file` - путь к файлу с запросами для выполнения. Необходимо задать либо параметр `query`, либо `queries-file`. - `-N`, `--table` — имя таблицы, в которую будут помещены входящие данные. По умолчанию - `table`. - `-of`, `--format`, `--output-format` — формат выходных данных. По умолчанию — `TSV`. +- `-d`, `--database` — база данных по умолчанию. Если не указано, используется значение `_local`. - `--stacktrace` — вывод отладочной информации при исключениях. +- `--echo` — перед выполнением запрос выводится в консоль. - `--verbose` — подробный вывод при выполнении запроса. -- `-s` — отключает вывод системных логов в `stderr`. -- `--config-file` — путь к файлу конфигурации. По умолчанию `clickhouse-local` запускается с пустой конфигурацией. Конфигурационный файл имеет тот же формат, что и для сервера ClickHouse и в нём можно использовать все конфигурационные параметры сервера. Обычно подключение конфигурации не требуется, если требуется установить отдельный параметр, то это можно сделать ключом с именем параметра. +- `--logger.console` — логирование действий в консоль. +- `--logger.log` — логирование действий в файл с указанным именем. +- `--logger.level` — уровень логирования. +- `--ignore-error` — не прекращать обработку если запрос выдал ошибку. +- `-c`, `--config-file` — путь к файлу конфигурации. По умолчанию `clickhouse-local` запускается с пустой конфигурацией. Конфигурационный файл имеет тот же формат, что и для сервера ClickHouse, и в нём можно использовать все конфигурационные параметры сервера. Обычно подключение конфигурации не требуется; если требуется установить отдельный параметр, то это можно сделать ключом с именем параметра. +- `--no-system-tables` — запуск без использования системных таблиц. - `--help` — вывод справочной информации о `clickhouse-local`. +- `-V`, `--version` — вывод текущей версии и выход. -## Примеры вызова {#primery-vyzova} +## Примеры вызова {#examples} ``` bash $ echo -e "1,2\n3,4" | clickhouse-local --structure "a Int64, b Int64" \ @@ -76,7 +85,9 @@ $ clickhouse-local --query " 1 2 ``` -А теперь давайте выведем на экран объём оперативной памяти, занимаемой пользователями (Unix): +Объём оперативной памяти, занимаемой процессами, которые запустил пользователь (Unix): + +Запрос: ``` bash $ ps aux | tail -n +2 | awk '{ printf("%s\t%s\n", $1, $4) }' \ @@ -85,6 +96,8 @@ $ ps aux | tail -n +2 | awk '{ printf("%s\t%s\n", $1, $4) }' \ FROM table GROUP BY user ORDER BY memTotal DESC FORMAT Pretty" ``` +Результат: + ``` text Read 186 rows, 4.15 KiB in 0.035 sec., 5302 rows/sec., 118.34 KiB/sec. ┏━━━━━━━━━━┳━━━━━━━━━━┓ diff --git a/docs/ru/operations/utilities/index.md b/docs/ru/operations/utilities/index.md index 5b55ebd798d..8b533c29ff5 100644 --- a/docs/ru/operations/utilities/index.md +++ b/docs/ru/operations/utilities/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u0423\u0442\u0438\u043b\u0438\u0442\u044b" +toc_folder_title: "Утилиты" toc_priority: 56 -toc_title: "\u041e\u0431\u0437\u043e\u0440" +toc_title: "Обзор" --- # Утилиты ClickHouse {#utility-clickhouse} diff --git a/docs/ru/sql-reference/aggregate-functions/combinators.md b/docs/ru/sql-reference/aggregate-functions/combinators.md index 592c61f87ff..3b35716ec27 100644 --- a/docs/ru/sql-reference/aggregate-functions/combinators.md +++ b/docs/ru/sql-reference/aggregate-functions/combinators.md @@ -1,6 +1,6 @@ --- toc_priority: 37 -toc_title: "\u041a\u043e\u043c\u0431\u0438\u043d\u0430\u0442\u043e\u0440\u044b\u0020\u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043d\u044b\u0445\u0020\u0444\u0443\u043d\u043a\u0446\u0438\u0439" +toc_title: "Комбинаторы агрегатных функций" --- diff --git a/docs/ru/sql-reference/aggregate-functions/index.md b/docs/ru/sql-reference/aggregate-functions/index.md index 4a7768f587f..3c931222f58 100644 --- a/docs/ru/sql-reference/aggregate-functions/index.md +++ b/docs/ru/sql-reference/aggregate-functions/index.md @@ -1,8 +1,7 @@ --- -toc_folder_title: "\u0410\u0433\u0440\u0435\u0433\u0430\u0442\u043D\u044B\u0435 \u0444\ - \u0443\u043D\u043A\u0446\u0438\u0438" +toc_folder_title: "Агрегатные функции" toc_priority: 33 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043D\u0438\u0435" +toc_title: "Введение" --- # Агрегатные функции {#aggregate-functions} diff --git a/docs/ru/sql-reference/aggregate-functions/parametric-functions.md b/docs/ru/sql-reference/aggregate-functions/parametric-functions.md index f20acaa45c3..61518cb6f02 100644 --- a/docs/ru/sql-reference/aggregate-functions/parametric-functions.md +++ b/docs/ru/sql-reference/aggregate-functions/parametric-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 38 -toc_title: "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0435\u0020\u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043d\u044b\u0435\u0020\u0444\u0443\u043d\u043a\u0446\u0438\u0438" +toc_title: "Параметрические агрегатные функции" --- # Параметрические агрегатные функции {#aggregate_functions_parametric} @@ -239,7 +239,7 @@ windowFunnel(window, [mode])(timestamp, cond1, cond2, ..., condN) **Параметры** -- `window` — ширина скользящего окна по времени в секундах. [UInt](../../sql-reference/aggregate-functions/parametric-functions.md). +- `window` — ширина скользящего окна по времени. Единица измерения зависит от `timestamp` и может варьироваться. Должно соблюдаться условие `timestamp события cond2 <= timestamp события cond1 + window`. - `mode` - необязательный параметр. Если установлено значение `'strict'`, то функция `windowFunnel()` применяет условия только для уникальных значений. - `timestamp` — имя столбца, содержащего временные отметки. [Date](../../sql-reference/aggregate-functions/parametric-functions.md), [DateTime](../../sql-reference/aggregate-functions/parametric-functions.md#data_type-datetime) и другие параметры с типом `Integer`. В случае хранения меток времени в столбцах с типом `UInt64`, максимально допустимое значение соответствует ограничению для типа `Int64`, т.е. равно `2^63-1`. - `cond` — условия или данные, описывающие цепочку событий. [UInt8](../../sql-reference/aggregate-functions/parametric-functions.md). diff --git a/docs/ru/sql-reference/aggregate-functions/reference/argmax.md b/docs/ru/sql-reference/aggregate-functions/reference/argmax.md index f44e65831a9..dd2df23e1cd 100644 --- a/docs/ru/sql-reference/aggregate-functions/reference/argmax.md +++ b/docs/ru/sql-reference/aggregate-functions/reference/argmax.md @@ -27,13 +27,13 @@ argMax(tuple(arg, val)) **Возвращаемое значение** -- Значение `arg`, соответствующее максимальному значению `val`. +- значение `arg`, соответствующее максимальному значению `val`. Тип: соответствует типу `arg`. Если передан кортеж: -- Кортеж `(arg, val)` c максимальным значением `val` и соответствующим ему `arg`. +- кортеж `(arg, val)` c максимальным значением `val` и соответствующим ему `arg`. Тип: [Tuple](../../../sql-reference/data-types/tuple.md). @@ -52,15 +52,15 @@ argMax(tuple(arg, val)) Запрос: ``` sql -SELECT argMax(user, salary), argMax(tuple(user, salary)) FROM salary; +SELECT argMax(user, salary), argMax(tuple(user, salary), salary), argMax(tuple(user, salary)) FROM salary; ``` Результат: ``` text -┌─argMax(user, salary)─┬─argMax(tuple(user, salary))─┐ -│ director │ ('director',5000) │ -└──────────────────────┴─────────────────────────────┘ +┌─argMax(user, salary)─┬─argMax(tuple(user, salary), salary)─┬─argMax(tuple(user, salary))─┐ +│ director │ ('director',5000) │ ('director',5000) │ +└──────────────────────┴─────────────────────────────────────┴─────────────────────────────┘ ``` [Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/aggregate-functions/reference/argmax/) diff --git a/docs/ru/sql-reference/aggregate-functions/reference/avg.md b/docs/ru/sql-reference/aggregate-functions/reference/avg.md index b0bee64ec66..c032199aa32 100644 --- a/docs/ru/sql-reference/aggregate-functions/reference/avg.md +++ b/docs/ru/sql-reference/aggregate-functions/reference/avg.md @@ -4,8 +4,61 @@ toc_priority: 5 # avg {#agg_function-avg} -Вычисляет среднее. -Работает только для чисел. -Результат всегда Float64. +Вычисляет среднее арифметическое. -[Оригинальная статья](https://clickhouse.tech/docs/en/sql-reference/aggregate-functions/reference/avg/) +**Синтаксис** + +``` sql +avg(x) +``` + +**Аргументы** + +- `x` — входное значение типа [Integer](../../../sql-reference/data-types/int-uint.md), [Float](../../../sql-reference/data-types/float.md) или [Decimal](../../../sql-reference/data-types/decimal.md). + +**Возвращаемое значение** + +- среднее арифметическое, всегда типа [Float64](../../../sql-reference/data-types/float.md). +- `NaN`, если входное значение `x` — пустое. + +**Пример** + +Запрос: + +``` sql +SELECT avg(x) FROM values('x Int8', 0, 1, 2, 3, 4, 5); +``` + +Результат: + +``` text +┌─avg(x)─┐ +│ 2.5 │ +└────────┘ +``` + +**Пример** + +Создайте временную таблицу: + +Запрос: + +``` sql +CREATE table test (t UInt8) ENGINE = Memory; +``` + +Выполните запрос: + +``` sql +SELECT avg(t) FROM test; +``` + +Результат: + +``` text +┌─avg(x)─┐ +│ nan │ +└────────┘ +``` + +[Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/aggregate-functions/reference/avg/) diff --git a/docs/ru/sql-reference/aggregate-functions/reference/index.md b/docs/ru/sql-reference/aggregate-functions/reference/index.md index 4c0060581fd..e496893a771 100644 --- a/docs/ru/sql-reference/aggregate-functions/reference/index.md +++ b/docs/ru/sql-reference/aggregate-functions/reference/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0421\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a" +toc_folder_title: "Справочник" toc_priority: 36 toc_hidden: true --- diff --git a/docs/ru/sql-reference/aggregate-functions/reference/mannwhitneyutest.md b/docs/ru/sql-reference/aggregate-functions/reference/mannwhitneyutest.md index fb73fff5f00..a4647ecfb34 100644 --- a/docs/ru/sql-reference/aggregate-functions/reference/mannwhitneyutest.md +++ b/docs/ru/sql-reference/aggregate-functions/reference/mannwhitneyutest.md @@ -31,6 +31,7 @@ mannWhitneyUTest[(alternative[, continuity_correction])](sample_data, sample_ind **Возвращаемые значения** [Кортеж](../../../sql-reference/data-types/tuple.md) с двумя элементами: + - вычисленное значение критерия Манна — Уитни. [Float64](../../../sql-reference/data-types/float.md). - вычисленное p-значение. [Float64](../../../sql-reference/data-types/float.md). diff --git a/docs/ru/sql-reference/aggregate-functions/reference/studentttest.md b/docs/ru/sql-reference/aggregate-functions/reference/studentttest.md index 5361e06c5e2..77378de95d1 100644 --- a/docs/ru/sql-reference/aggregate-functions/reference/studentttest.md +++ b/docs/ru/sql-reference/aggregate-functions/reference/studentttest.md @@ -24,6 +24,7 @@ studentTTest(sample_data, sample_index) **Возвращаемые значения** [Кортеж](../../../sql-reference/data-types/tuple.md) с двумя элементами: + - вычисленное значение критерия Стьюдента. [Float64](../../../sql-reference/data-types/float.md). - вычисленное p-значение. [Float64](../../../sql-reference/data-types/float.md). diff --git a/docs/ru/sql-reference/aggregate-functions/reference/welchttest.md b/docs/ru/sql-reference/aggregate-functions/reference/welchttest.md index 1f36b2d04ee..16c122d1b49 100644 --- a/docs/ru/sql-reference/aggregate-functions/reference/welchttest.md +++ b/docs/ru/sql-reference/aggregate-functions/reference/welchttest.md @@ -24,6 +24,7 @@ welchTTest(sample_data, sample_index) **Возвращаемые значения** [Кортеж](../../../sql-reference/data-types/tuple.md) с двумя элементами: + - вычисленное значение критерия Уэлча. [Float64](../../../sql-reference/data-types/float.md). - вычисленное p-значение. [Float64](../../../sql-reference/data-types/float.md). diff --git a/docs/ru/sql-reference/data-types/boolean.md b/docs/ru/sql-reference/data-types/boolean.md index bb0cd50c739..b0fad6d7446 100644 --- a/docs/ru/sql-reference/data-types/boolean.md +++ b/docs/ru/sql-reference/data-types/boolean.md @@ -1,6 +1,6 @@ --- toc_priority: 43 -toc_title: "\u0411\u0443\u043b\u0435\u0432\u044b\u0020\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f" +toc_title: "Булевы значения" --- # Булевы значения {#bulevy-znacheniia} diff --git a/docs/ru/sql-reference/data-types/domains/index.md b/docs/ru/sql-reference/data-types/domains/index.md index 4449469b1bc..6a968a76ff6 100644 --- a/docs/ru/sql-reference/data-types/domains/index.md +++ b/docs/ru/sql-reference/data-types/domains/index.md @@ -1,6 +1,6 @@ --- -toc_folder_title: "\u0414\u043e\u043c\u0435\u043d\u044b" -toc_title_title: "\u041e\u0431\u0437\u043e\u0440" +toc_folder_title: "Домены" +toc_title_title: "Обзор" toc_priority: 56 --- diff --git a/docs/ru/sql-reference/data-types/geo.md b/docs/ru/sql-reference/data-types/geo.md new file mode 100644 index 00000000000..23293b30927 --- /dev/null +++ b/docs/ru/sql-reference/data-types/geo.md @@ -0,0 +1,106 @@ +--- +toc_priority: 62 +toc_title: Географические структуры +--- + +# Типы данных для работы с географическими структурами {#geo-data-types} + +ClickHouse поддерживает типы данных для отображения географических объектов — точек (местоположений), территорий и т.п. + +!!! warning "Предупреждение" + Сейчас использование типов данных для работы с географическими структурами является экспериментальной возможностью. Чтобы использовать эти типы данных, включите настройку `allow_experimental_geo_types = 1`. + +**См. также** +- [Хранение географических структур данных](https://ru.wikipedia.org/wiki/GeoJSON). +- Настройка [allow_experimental_geo_types](../../operations/settings/settings.md#allow-experimental-geo-types). + +## Point {#point-data-type} + +Тип `Point` (точка) определяется парой координат X и Y и хранится в виде кортежа [Tuple](tuple.md)([Float64](float.md), [Float64](float.md)). + +**Пример** + +Запрос: + +```sql +SET allow_experimental_geo_types = 1; +CREATE TABLE geo_point (p Point) ENGINE = Memory(); +INSERT INTO geo_point VALUES((10, 10)); +SELECT p, toTypeName(p) FROM geo_point; +``` +Результат: + +``` text +┌─p─────┬─toTypeName(p)─┐ +│ (10,10) │ Point │ +└───────┴───────────────┘ +``` + +## Ring {#ring-data-type} + +Тип `Ring` описывает простой многоугольник без внутренних областей (дыр) и хранится в виде массива точек: [Array](array.md)([Point](#point-data-type)). + +**Пример** + +Запрос: + +```sql +SET allow_experimental_geo_types = 1; +CREATE TABLE geo_ring (r Ring) ENGINE = Memory(); +INSERT INTO geo_ring VALUES([(0, 0), (10, 0), (10, 10), (0, 10)]); +SELECT r, toTypeName(r) FROM geo_ring; +``` +Результат: + +``` text +┌─r─────────────────────────────┬─toTypeName(r)─┐ +│ [(0,0),(10,0),(10,10),(0,10)] │ Ring │ +└───────────────────────────────┴───────────────┘ +``` + +## Polygon {#polygon-data-type} + +Тип `Polygon` описывает многоугольник с внутренними областями (дырами) и хранится в виде массива: [Array](array.md)([Ring](#ring-data-type)). Первый элемент массива описывает внешний многоугольник (контур), а остальные элементы описывают дыры. + +**Пример** + +Запись в этой таблице описывает многоугольник с одной дырой: + +```sql +SET allow_experimental_geo_types = 1; +CREATE TABLE geo_polygon (pg Polygon) ENGINE = Memory(); +INSERT INTO geo_polygon VALUES([[(20, 20), (50, 20), (50, 50), (20, 50)], [(30, 30), (50, 50), (50, 30)]]); +SELECT pg, toTypeName(pg) FROM geo_polygon; +``` + +Результат: + +``` text +┌─pg────────────────────────────────────────────────────────────┬─toTypeName(pg)─┐ +│ [[(20,20),(50,20),(50,50),(20,50)],[(30,30),(50,50),(50,30)]] │ Polygon │ +└───────────────────────────────────────────────────────────────┴────────────────┘ +``` + +## MultiPolygon {#multipolygon-data-type} + +Тип `MultiPolygon` описывает элемент, состоящий из нескольких простых многоугольников (полигональную сетку). Он хранится в виде массива многоугольников: [Array](array.md)([Polygon](#polygon-data-type)). + +**Пример** + +Запись в этой таблице описывает элемент, состоящий из двух многоугольников — первый без дыр, а второй с одной дырой: + +```sql +SET allow_experimental_geo_types = 1; +CREATE TABLE geo_multipolygon (mpg MultiPolygon) ENGINE = Memory(); +INSERT INTO geo_multipolygon VALUES([[[(0, 0), (10, 0), (10, 10), (0, 10)]], [[(20, 20), (50, 20), (50, 50), (20, 50)],[(30, 30), (50, 50), (50, 30)]]]); +SELECT mpg, toTypeName(mpg) FROM geo_multipolygon; +``` +Result: + +``` text +┌─mpg─────────────────────────────────────────────────────────────────────────────────────────────┬─toTypeName(mpg)─┐ +│ [[[(0,0),(10,0),(10,10),(0,10)]],[[(20,20),(50,20),(50,50),(20,50)],[(30,30),(50,50),(50,30)]]] │ MultiPolygon │ +└─────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────┘ +``` + +[Оригинальная статья](https://clickhouse.tech/docs/ru/data-types/geo/) diff --git a/docs/ru/sql-reference/data-types/index.md b/docs/ru/sql-reference/data-types/index.md index 7a5618f4c5d..53c983a147a 100644 --- a/docs/ru/sql-reference/data-types/index.md +++ b/docs/ru/sql-reference/data-types/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u0422\u0438\u043F\u044B \u0434\u0430\u043D\u043D\u044B\u0445" +toc_folder_title: "Типы данных" toc_priority: 37 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043D\u0438\u0435" +toc_title: "Введение" --- # Типы данных {#data_types} diff --git a/docs/ru/sql-reference/data-types/lowcardinality.md b/docs/ru/sql-reference/data-types/lowcardinality.md index d94cedd29ce..52713e2d747 100644 --- a/docs/ru/sql-reference/data-types/lowcardinality.md +++ b/docs/ru/sql-reference/data-types/lowcardinality.md @@ -23,7 +23,7 @@ LowCardinality(data_type) Эффективность использования типа данных `LowCarditality` зависит от разнообразия данных. Если словарь содержит менее 10 000 различных значений, ClickHouse в основном показывает более высокую эффективность чтения и хранения данных. Если же словарь содержит более 100 000 различных значений, ClickHouse может работать хуже, чем при использовании обычных типов данных. -При работе со строками, использование `LowCardinality` вместо [Enum](enum.md). `LowCardinality` обеспечивает большую гибкость в использовании и часто показывает такую же или более высокую эффективность. +При работе со строками, использование `LowCardinality` вместо [Enum](enum.md) обеспечивает большую гибкость в использовании и часто показывает такую же или более высокую эффективность. ## Пример diff --git a/docs/ru/sql-reference/data-types/map.md b/docs/ru/sql-reference/data-types/map.md new file mode 100644 index 00000000000..6cb8ccf1143 --- /dev/null +++ b/docs/ru/sql-reference/data-types/map.md @@ -0,0 +1,69 @@ +--- +toc_priority: 65 +toc_title: Map(key, value) +--- + +# Map(key, value) {#data_type-map} + +Тип данных `Map(key, value)` хранит пары `ключ:значение`. + +**Параметры** +- `key` — ключ. [String](../../sql-reference/data-types/string.md) или [Integer](../../sql-reference/data-types/int-uint.md). +- `value` — значение. [String](../../sql-reference/data-types/string.md), [Integer](../../sql-reference/data-types/int-uint.md) или [Array](../../sql-reference/data-types/array.md). + +!!! warning "Предупреждение" + Сейчас использование типа данных `Map` является экспериментальной возможностью. Чтобы использовать этот тип данных, включите настройку `allow_experimental_map_type = 1`. + +Чтобы получить значение из колонки `a Map('key', 'value')`, используйте синтаксис `a['key']`. В настоящее время такая подстановка работает по алгоритму с линейной сложностью. + +**Примеры** + +Рассмотрим таблицу: + +``` sql +CREATE TABLE table_map (a Map(String, UInt64)) ENGINE=Memory; +INSERT INTO table_map VALUES ({'key1':1, 'key2':10}), ({'key1':2,'key2':20}), ({'key1':3,'key2':30}); +``` + +Выборка всех значений ключа `key2`: + +```sql +SELECT a['key2'] FROM table_map; +``` +Результат: + +```text +┌─arrayElement(a, 'key2')─┐ +│ 10 │ +│ 20 │ +│ 30 │ +└─────────────────────────┘ +``` + +Если для какого-то ключа `key` в колонке с типом `Map()` нет значения, запрос возвращает нули для числовых колонок, пустые строки или пустые массивы. + +```sql +INSERT INTO table_map VALUES ({'key3':100}), ({}); +SELECT a['key3'] FROM table_map; +``` + +Результат: + +```text +┌─arrayElement(a, 'key3')─┐ +│ 100 │ +│ 0 │ +└─────────────────────────┘ +┌─arrayElement(a, 'key3')─┐ +│ 0 │ +│ 0 │ +│ 0 │ +└─────────────────────────┘ +``` + +**См. также** + +- функция [map()](../../sql-reference/functions/tuple-map-functions.md#function-map) +- функция [CAST()](../../sql-reference/functions/type-conversion-functions.md#type_conversion_function-cast) + +[Original article](https://clickhouse.tech/docs/ru/data-types/map/) diff --git a/docs/ru/sql-reference/data-types/nested-data-structures/index.md b/docs/ru/sql-reference/data-types/nested-data-structures/index.md index d53cabc6652..db214b90c03 100644 --- a/docs/ru/sql-reference/data-types/nested-data-structures/index.md +++ b/docs/ru/sql-reference/data-types/nested-data-structures/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0412\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435\u0020\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b\u0020\u0434\u0430\u043d\u043d\u044b\u0445" +toc_folder_title: "Вложенные структуры данных" toc_hidden: true toc_priority: 54 toc_title: hidden diff --git a/docs/ru/sql-reference/data-types/simpleaggregatefunction.md b/docs/ru/sql-reference/data-types/simpleaggregatefunction.md index 52f0412a177..668b579ff78 100644 --- a/docs/ru/sql-reference/data-types/simpleaggregatefunction.md +++ b/docs/ru/sql-reference/data-types/simpleaggregatefunction.md @@ -1,8 +1,9 @@ -# SimpleAggregateFunction {#data-type-simpleaggregatefunction} +# SimpleAggregateFunction(func, type) {#data-type-simpleaggregatefunction} -`SimpleAggregateFunction(name, types_of_arguments…)` data type stores current value of the aggregate function, and does not store its full state as [`AggregateFunction`](../../sql-reference/data-types/aggregatefunction.md) does. This optimization can be applied to functions for which the following property holds: the result of applying a function `f` to a row set `S1 UNION ALL S2` can be obtained by applying `f` to parts of the row set separately, and then again applying `f` to the results: `f(S1 UNION ALL S2) = f(f(S1) UNION ALL f(S2))`. This property guarantees that partial aggregation results are enough to compute the combined one, so we don’t have to store and process any extra data. +Хранит только текущее значение агрегатной функции и не сохраняет ее полное состояние, как это делает [`AggregateFunction`](../../sql-reference/data-types/aggregatefunction.md). Такая оптимизация может быть применена к функциям, которые обладают следующим свойством: результат выполнения функции `f` к набору строк `S1 UNION ALL S2` может быть получен путем выполнения `f` к отдельным частям набора строк, +а затем повторного выполнения `f` к результатам: `f(S1 UNION ALL S2) = f(f(S1) UNION ALL f(S2))`. Это свойство гарантирует, что результатов частичной агрегации достаточно для вычисления комбинированной, поэтому хранить и обрабатывать какие-либо дополнительные данные не требуется. -The following aggregate functions are supported: +Поддерживаются следующие агрегатные функции: - [`any`](../../sql-reference/aggregate-functions/reference/any.md#agg_function-any) - [`anyLast`](../../sql-reference/aggregate-functions/reference/anylast.md#anylastx) @@ -15,22 +16,24 @@ The following aggregate functions are supported: - [`groupBitXor`](../../sql-reference/aggregate-functions/reference/groupbitxor.md#groupbitxor) - [`groupArrayArray`](../../sql-reference/aggregate-functions/reference/grouparray.md#agg_function-grouparray) - [`groupUniqArrayArray`](../../sql-reference/aggregate-functions/reference/groupuniqarray.md#groupuniqarray) +- [`sumMap`](../../sql-reference/aggregate-functions/reference/summap.md#agg_functions-summap) +- [`minMap`](../../sql-reference/aggregate-functions/reference/minmap.md#agg_functions-minmap) +- [`maxMap`](../../sql-reference/aggregate-functions/reference/maxmap.md#agg_functions-maxmap) -Values of the `SimpleAggregateFunction(func, Type)` look and stored the same way as `Type`, so you do not need to apply functions with `-Merge`/`-State` suffixes. `SimpleAggregateFunction` has better performance than `AggregateFunction` with same aggregation function. +!!! note "Примечание" + Значения `SimpleAggregateFunction(func, Type)` отображаются и хранятся так же, как и `Type`, поэтому комбинаторы [-Merge](../../sql-reference/aggregate-functions/combinators.md#aggregate_functions_combinators-merge) и [-State]((../../sql-reference/aggregate-functions/combinators.md#agg-functions-combinator-state) не требуются. + + `SimpleAggregateFunction` имеет лучшую производительность, чем `AggregateFunction` с той же агрегатной функцией. -**Parameters** +**Параметры** -- Name of the aggregate function. -- Types of the aggregate function arguments. +- `func` — имя агрегатной функции. +- `type` — типы аргументов агрегатной функции. -**Example** +**Пример** ``` sql -CREATE TABLE t -( - column1 SimpleAggregateFunction(sum, UInt64), - column2 SimpleAggregateFunction(any, String) -) ENGINE = ... +CREATE TABLE simple (id UInt64, val SimpleAggregateFunction(sum, Double)) ENGINE=AggregatingMergeTree ORDER BY id; ``` -[Original article](https://clickhouse.tech/docs/en/data_types/simpleaggregatefunction/) +[Оригинальная статья](https://clickhouse.tech/docs/en/sql-reference/data-types/simpleaggregatefunction/) diff --git a/docs/ru/sql-reference/data-types/special-data-types/index.md b/docs/ru/sql-reference/data-types/special-data-types/index.md index 29c057472ea..e6d9fa8b011 100644 --- a/docs/ru/sql-reference/data-types/special-data-types/index.md +++ b/docs/ru/sql-reference/data-types/special-data-types/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0421\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435\u0020\u0442\u0438\u043f\u044b\u0020\u0434\u0430\u043d\u043d\u044b\u0445" +toc_folder_title: "Служебные типы данных" toc_hidden: true toc_priority: 55 toc_title: hidden diff --git a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-hierarchical.md b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-hierarchical.md index 350e391dbed..9c0b731bc7d 100644 --- a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-hierarchical.md +++ b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-hierarchical.md @@ -1,6 +1,6 @@ --- toc_priority: 45 -toc_title: "\u0418\u0435\u0440\u0430\u0440\u0445\u0438\u0447\u0435\u0441\u043a\u0438\u0435\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u0438" +toc_title: "Иерархические словари" --- # Иерархические словари {#ierarkhicheskie-slovari} diff --git a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-layout.md b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-layout.md index f6b8b670563..0fd4a85c46f 100644 --- a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-layout.md +++ b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-layout.md @@ -1,6 +1,6 @@ --- toc_priority: 41 -toc_title: "\u0425\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u0435\u0439\u0020\u0432\u0020\u043f\u0430\u043c\u044f\u0442\u0438" +toc_title: "Хранение словарей в памяти" --- # Хранение словарей в памяти {#dicts-external-dicts-dict-layout} diff --git a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-lifetime.md b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-lifetime.md index ec0fb8e0ee5..cdf1b05fb37 100644 --- a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-lifetime.md +++ b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-lifetime.md @@ -1,6 +1,6 @@ --- toc_priority: 42 -toc_title: "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u0435\u0439" +toc_title: "Обновление словарей" --- # Обновление словарей {#obnovlenie-slovarei} diff --git a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-sources.md b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-sources.md index 3bb11b638b2..13b6a93b6ae 100644 --- a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-sources.md +++ b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-sources.md @@ -1,6 +1,6 @@ --- toc_priority: 43 -toc_title: "\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438\u0020\u0432\u043d\u0435\u0448\u043d\u0438\u0445\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u0435\u0439" +toc_title: "Источники внешних словарей" --- # Источники внешних словарей {#dicts-external-dicts-dict-sources} @@ -572,7 +572,7 @@ SOURCE(CLICKHOUSE( или ``` sql -SOURCE(MONGO( +SOURCE(MONGODB( host 'localhost' port 27017 user '' diff --git a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-structure.md b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-structure.md index bf87ce61b9e..6efbe706110 100644 --- a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-structure.md +++ b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-structure.md @@ -1,6 +1,6 @@ --- toc_priority: 44 -toc_title: "\u041a\u043b\u044e\u0447\u0020\u0438\u0020\u043f\u043e\u043b\u044f\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u044f" +toc_title: "Ключ и поля словаря" --- # Ключ и поля словаря {#kliuch-i-polia-slovaria} diff --git a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict.md b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict.md index ff18f906926..7e35f59609d 100644 --- a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict.md +++ b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict.md @@ -1,6 +1,6 @@ --- toc_priority: 40 -toc_title: "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0020\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u044f" +toc_title: "Настройка внешнего словаря" --- # Настройка внешнего словаря {#dicts-external-dicts-dict} diff --git a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts.md b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts.md index c18af68c15e..6467b5f82e4 100644 --- a/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts.md +++ b/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts.md @@ -1,6 +1,6 @@ --- toc_priority: 39 -toc_title: "\u0412\u043d\u0435\u0448\u043d\u0438\u0435\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u0438" +toc_title: "Внешние словари" --- diff --git a/docs/ru/sql-reference/dictionaries/external-dictionaries/index.md b/docs/ru/sql-reference/dictionaries/external-dictionaries/index.md index b448858b1fa..c0d954d6976 100644 --- a/docs/ru/sql-reference/dictionaries/external-dictionaries/index.md +++ b/docs/ru/sql-reference/dictionaries/external-dictionaries/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0412\u043d\u0435\u0448\u043d\u0438\u0435\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u0438" +toc_folder_title: "Внешние словари" toc_priority: 37 --- diff --git a/docs/ru/sql-reference/dictionaries/index.md b/docs/ru/sql-reference/dictionaries/index.md index 5a4119b4dd5..238aa244967 100644 --- a/docs/ru/sql-reference/dictionaries/index.md +++ b/docs/ru/sql-reference/dictionaries/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u0421\u043b\u043e\u0432\u0430\u0440\u0438" +toc_folder_title: "Словари" toc_priority: 35 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435" +toc_title: "Введение" --- # Словари {#slovari} diff --git a/docs/ru/sql-reference/dictionaries/internal-dicts.md b/docs/ru/sql-reference/dictionaries/internal-dicts.md index d8103efa6ae..af7f13f7133 100644 --- a/docs/ru/sql-reference/dictionaries/internal-dicts.md +++ b/docs/ru/sql-reference/dictionaries/internal-dicts.md @@ -1,6 +1,6 @@ --- toc_priority: 39 -toc_title: "\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u0438" +toc_title: "Встроенные словари" --- # Встроенные словари {#internal_dicts} diff --git a/docs/ru/sql-reference/distributed-ddl.md b/docs/ru/sql-reference/distributed-ddl.md index 275709320f6..17c38cfe820 100644 --- a/docs/ru/sql-reference/distributed-ddl.md +++ b/docs/ru/sql-reference/distributed-ddl.md @@ -1,6 +1,6 @@ --- toc_priority: 32 -toc_title: "\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435\u0020\u0044\u0044\u004c\u0020\u0437\u0430\u043f\u0440\u043e\u0441\u044b\u000a" +toc_title: "Распределенные DDL запросы" --- # Распределенные DDL запросы (секция ON CLUSTER) {#raspredelennye-ddl-zaprosy-sektsiia-on-cluster} diff --git a/docs/ru/sql-reference/functions/arithmetic-functions.md b/docs/ru/sql-reference/functions/arithmetic-functions.md index 16c3e8fd8f0..779e0a9fe4a 100644 --- a/docs/ru/sql-reference/functions/arithmetic-functions.md +++ b/docs/ru/sql-reference/functions/arithmetic-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 34 -toc_title: "\u0410\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435\u0020\u0444\u0443\u043d\u043a\u0446\u0438\u0438" +toc_title: "Арифметические функции" --- # Арифметические функции {#arifmeticheskie-funktsii} diff --git a/docs/ru/sql-reference/functions/array-functions.md b/docs/ru/sql-reference/functions/array-functions.md index 80057e6f0e0..dca645888a9 100644 --- a/docs/ru/sql-reference/functions/array-functions.md +++ b/docs/ru/sql-reference/functions/array-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 35 -toc_title: "\u041c\u0430\u0441\u0441\u0438\u0432\u044b" +toc_title: "Массивы" --- # Массивы {#functions-for-working-with-arrays} @@ -1355,6 +1355,52 @@ SELECT arrayAvg(x -> (x * x), [2, 4]) AS res; └─────┘ ``` +**Синтаксис** + +``` sql +arraySum(arr) +``` + +**Возвращаемое значение** + +- Число. + +Тип: [Int](../../sql-reference/data-types/int-uint.md) или [Float](../../sql-reference/data-types/float.md). + +**Параметры** + +- `arr` — [Массив](../../sql-reference/data-types/array.md). + +**Примеры** + +Запрос: + +```sql +SELECT arraySum([2,3]) AS res; +``` + +Результат: + +``` text +┌─res─┐ +│ 5 │ +└─────┘ +``` + +Запрос: + +``` sql +SELECT arraySum(x -> x*x, [2, 3]) AS res; +``` + +Результат: + +``` text +┌─res─┐ +│ 13 │ +└─────┘ +``` + ## arrayCumSum(\[func,\] arr1, …) {#arraycumsumfunc-arr1} Возвращает массив из частичных сумм элементов исходного массива (сумма с накоплением). Если указана функция `func`, то значения элементов массива преобразуются этой функцией перед суммированием. diff --git a/docs/ru/sql-reference/functions/array-join.md b/docs/ru/sql-reference/functions/array-join.md index 2ed3d25fa92..ed67d30062b 100644 --- a/docs/ru/sql-reference/functions/array-join.md +++ b/docs/ru/sql-reference/functions/array-join.md @@ -1,6 +1,6 @@ --- toc_priority: 61 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u044f\u0020\u0041\u0072\u0072\u0061\u0079\u004a\u006f\u0069\u006e" +toc_title: "Функция ArrayJoin" --- # Функция ArrayJoin {#functions_arrayjoin} diff --git a/docs/ru/sql-reference/functions/bit-functions.md b/docs/ru/sql-reference/functions/bit-functions.md index 8c7808437a5..79ea05f4bd7 100644 --- a/docs/ru/sql-reference/functions/bit-functions.md +++ b/docs/ru/sql-reference/functions/bit-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 48 -toc_title: "\u0411\u0438\u0442\u043e\u0432\u044b\u0435\u0020\u0444\u0443\u043d\u043a\u0446\u0438\u0438" +toc_title: "Битовые функции" --- # Битовые функции {#bitovye-funktsii} diff --git a/docs/ru/sql-reference/functions/bitmap-functions.md b/docs/ru/sql-reference/functions/bitmap-functions.md index b21ddea94e4..cd0ddee01a6 100644 --- a/docs/ru/sql-reference/functions/bitmap-functions.md +++ b/docs/ru/sql-reference/functions/bitmap-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 49 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0431\u0438\u0442\u043c\u0430\u043f\u043e\u0432" +toc_title: "Функции для битмапов" --- # Функции для битовых масок {#bitmap-functions} diff --git a/docs/ru/sql-reference/functions/comparison-functions.md b/docs/ru/sql-reference/functions/comparison-functions.md index a98c97ec96c..179df5c2ed5 100644 --- a/docs/ru/sql-reference/functions/comparison-functions.md +++ b/docs/ru/sql-reference/functions/comparison-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 36 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f" +toc_title: "Функции сравнения" --- # Функции сравнения {#funktsii-sravneniia} diff --git a/docs/ru/sql-reference/functions/conditional-functions.md b/docs/ru/sql-reference/functions/conditional-functions.md index 83268b68959..888e9427a79 100644 --- a/docs/ru/sql-reference/functions/conditional-functions.md +++ b/docs/ru/sql-reference/functions/conditional-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 43 -toc_title: "\u0423\u0441\u043b\u043e\u0432\u043d\u044b\u0435\u0020\u0444\u0443\u043d\u043a\u0446\u0438\u0438" +toc_title: "Условные функции" --- # Условные функции {#uslovnye-funktsii} diff --git a/docs/ru/sql-reference/functions/date-time-functions.md b/docs/ru/sql-reference/functions/date-time-functions.md index 31482cde77f..9f3df92922f 100644 --- a/docs/ru/sql-reference/functions/date-time-functions.md +++ b/docs/ru/sql-reference/functions/date-time-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 39 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u0020\u0434\u0430\u0442\u0430\u043c\u0438\u0020\u0438\u0020\u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c" +toc_title: "Функции для работы с датами и временем" --- # Функции для работы с датами и временем {#funktsii-dlia-raboty-s-datami-i-vremenem} @@ -23,8 +23,6 @@ SELECT └─────────────────────┴────────────┴────────────┴─────────────────────┘ ``` -Поддерживаются только часовые пояса, отличающиеся от UTC на целое число часов. - ## toTimeZone {#totimezone} Переводит дату или дату-с-временем в указанный часовой пояс. Часовой пояс (таймзона) это атрибут типов Date/DateTime, внутреннее значение (количество секунд) поля таблицы или колонки результата не изменяется, изменяется тип поля и автоматически его текстовое отображение. @@ -63,40 +61,58 @@ int32samoa: 1546300800 Переводит дату или дату-с-временем в число типа UInt16, содержащее номер года (AD). +Синоним: `YEAR`. + ## toQuarter {#toquarter} Переводит дату или дату-с-временем в число типа UInt8, содержащее номер квартала. +Синоним: `QUARTER`. + ## toMonth {#tomonth} Переводит дату или дату-с-временем в число типа UInt8, содержащее номер месяца (1-12). +Синоним: `MONTH`. + ## toDayOfYear {#todayofyear} Переводит дату или дату-с-временем в число типа UInt16, содержащее номер дня года (1-366). +Синоним: `DAYOFYEAR`. + ## toDayOfMonth {#todayofmonth} Переводит дату или дату-с-временем в число типа UInt8, содержащее номер дня в месяце (1-31). +Синонимы: `DAYOFMONTH`, `DAY`. + ## toDayOfWeek {#todayofweek} Переводит дату или дату-с-временем в число типа UInt8, содержащее номер дня в неделе (понедельник - 1, воскресенье - 7). +Синоним: `DAYOFWEEK`. + ## toHour {#tohour} Переводит дату-с-временем в число типа UInt8, содержащее номер часа в сутках (0-23). Функция исходит из допущения, что перевод стрелок вперёд, если осуществляется, то на час, в два часа ночи, а перевод стрелок назад, если осуществляется, то на час, в три часа ночи (что, в общем, не верно - даже в Москве два раза перевод стрелок был осуществлён в другое время). +Синоним: `HOUR`. + ## toMinute {#tominute} Переводит дату-с-временем в число типа UInt8, содержащее номер минуты в часе (0-59). +Синоним: `MINUTE`. + ## toSecond {#tosecond} Переводит дату-с-временем в число типа UInt8, содержащее номер секунды в минуте (0-59). Секунды координации не учитываются. +Синоним: `SECOND`. + ## toUnixTimestamp {#to-unix-timestamp} Переводит дату-с-временем в число типа UInt32 -- Unix Timestamp (https://en.wikipedia.org/wiki/Unix_time). @@ -305,7 +321,9 @@ WITH toDateTime64('2020-01-01 10:20:30.999', 3) AS dt64 SELECT toStartOfSecond(d Переводит дату-с-временем или дату в число типа UInt16, содержащее номер ISO года. ISO год отличается от обычного года, потому что в соответствии с [ISO 8601:1988](https://en.wikipedia.org/wiki/ISO_8601) ISO год начинается необязательно первого января. -Пример: +**Пример** + +Запрос: ```sql SELECT @@ -313,6 +331,9 @@ SELECT toYear(date), toISOYear(date) ``` + +Результат: + ```text ┌───────date─┬─toYear(toDate('2017-01-01'))─┬─toISOYear(toDate('2017-01-01'))─┐ │ 2017-01-01 │ 2017 │ 2016 │ @@ -326,12 +347,18 @@ SELECT 1 Января 2017 г. - воскресение, т.е. первая ISO неделя 2017 года началась в понедельник 2 января, поэтому 1 января 2017 это последняя неделя 2016 года. +**Пример** + +Запрос: + ```sql SELECT toISOWeek(toDate('2017-01-01')) AS ISOWeek20170101, toISOWeek(toDate('2017-01-02')) AS ISOWeek20170102 ``` +Результат: + ```text ┌─ISOWeek20170101─┬─ISOWeek20170102─┐ │ 52 │ 1 │ @@ -368,10 +395,14 @@ SELECT **Пример** +Запрос: + ```sql SELECT toDate('2016-12-27') AS date, toWeek(date) AS week0, toWeek(date,1) AS week1, toWeek(date,9) AS week9; ``` +Результат: + ```text ┌───────date─┬─week0─┬─week1─┬─week9─┐ │ 2016-12-27 │ 52 │ 52 │ 1 │ @@ -387,10 +418,14 @@ SELECT toDate('2016-12-27') AS date, toWeek(date) AS week0, toWeek(date,1) AS we **Пример** +Запрос: + ```sql SELECT toDate('2016-12-27') AS date, toYearWeek(date) AS yearWeek0, toYearWeek(date,1) AS yearWeek1, toYearWeek(date,9) AS yearWeek9; ``` +Результат: + ```text ┌───────date─┬─yearWeek0─┬─yearWeek1─┬─yearWeek9─┐ │ 2016-12-27 │ 201652 │ 201652 │ 201701 │ @@ -409,9 +444,9 @@ date_trunc(unit, value[, timezone]) Синоним: `dateTrunc`. -**Параметры** +**Аргументы** -- `unit` — Название части даты или времени. [String](../syntax.md#syntax-string-literal). +- `unit` — единица измерения времени, в которой задана отсекаемая часть. [String Literal](../syntax.md#syntax-string-literal). Возможные значения: - `second` @@ -423,8 +458,8 @@ date_trunc(unit, value[, timezone]) - `quarter` - `year` -- `value` — Дата и время. [DateTime](../../sql-reference/data-types/datetime.md) или [DateTime64](../../sql-reference/data-types/datetime64.md). -- `timezone` — [Часовой пояс](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone) для возвращаемого значения (необязательно). Если параметр не задан, используется часовой пояс параметра `value`. [String](../../sql-reference/data-types/string.md) +- `value` — дата и время. [DateTime](../../sql-reference/data-types/datetime.md) или [DateTime64](../../sql-reference/data-types/datetime64.md). +- `timezone` — [часовой пояс](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone) для возвращаемого значения (необязательно). Если параметр не задан, используется часовой пояс параметра `value`. [String](../../sql-reference/data-types/string.md) **Возвращаемое значение** @@ -462,10 +497,267 @@ SELECT now(), date_trunc('hour', now(), 'Europe/Moscow'); └─────────────────────┴────────────────────────────────────────────┘ ``` -**См. также** +**Смотрите также** - [toStartOfInterval](#tostartofintervaltime-or-data-interval-x-unit-time-zone) +## date\_add {#date_add} + +Добавляет интервал времени или даты к указанной дате или дате со временем. + +**Синтаксис** + +``` sql +date_add(unit, value, date) +``` + +Синонимы: `dateAdd`, `DATE_ADD`. + +**Аргументы** + +- `unit` — единица измерения времени, в которой задан интервал для добавления. [String](../../sql-reference/data-types/string.md). + Возможные значения: + + - `second` + - `minute` + - `hour` + - `day` + - `week` + - `month` + - `quarter` + - `year` + +- `value` — значение интервала для добавления. [Int](../../sql-reference/data-types/int-uint.md). +- `date` — дата или дата со временем, к которой добавляется `value`. [Date](../../sql-reference/data-types/date.md) или [DateTime](../../sql-reference/data-types/datetime.md). + +**Возвращаемое значение** + +Дата или дата со временем, полученная в результате добавления `value`, выраженного в `unit`, к `date`. + +Тип: [Date](../../sql-reference/data-types/date.md) или [DateTime](../../sql-reference/data-types/datetime.md). + +**Пример** + +Запрос: + +```sql +SELECT date_add(YEAR, 3, toDate('2018-01-01')); +``` + +Результат: + +```text +┌─plus(toDate('2018-01-01'), toIntervalYear(3))─┐ +│ 2021-01-01 │ +└───────────────────────────────────────────────┘ +``` + +## date\_diff {#date_diff} + +Вычисляет разницу между двумя значениями дат или дат со временем. + +**Синтаксис** + +``` sql +date_diff('unit', startdate, enddate, [timezone]) +``` + +Синонимы: `dateDiff`, `DATE_DIFF`. + +**Аргументы** + +- `unit` — единица измерения времени, в которой будет выражено возвращаемое значение функции. [String](../../sql-reference/data-types/string.md). + Возможные значения: + + - `second` + - `minute` + - `hour` + - `day` + - `week` + - `month` + - `quarter` + - `year` + +- `startdate` — первая дата или дата со временем, которая вычитается из `enddate`. [Date](../../sql-reference/data-types/date.md) или [DateTime](../../sql-reference/data-types/datetime.md). + +- `enddate` — вторая дата или дата со временем, из которой вычитается `startdate`. [Date](../../sql-reference/data-types/date.md) или [DateTime](../../sql-reference/data-types/datetime.md). + +- `timezone` — [часовой пояс](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone) (необязательно). Если этот аргумент указан, то он применяется как для `startdate`, так и для `enddate`. Если этот аргумент не указан, то используются часовые пояса аргументов `startdate` и `enddate`. Если часовые пояса аргументов `startdate` и `enddate` не совпадают, то результат не определен. [String](../../sql-reference/data-types/string.md). + +**Возвращаемое значение** + +Разница между `enddate` и `startdate`, выраженная в `unit`. + +Тип: [Int](../../sql-reference/data-types/int-uint.md). + +**Пример** + +Запрос: + +``` sql +SELECT dateDiff('hour', toDateTime('2018-01-01 22:00:00'), toDateTime('2018-01-02 23:00:00')); +``` + +Результат: + +``` text +┌─dateDiff('hour', toDateTime('2018-01-01 22:00:00'), toDateTime('2018-01-02 23:00:00'))─┐ +│ 25 │ +└────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +## date\_sub {#date_sub} + +Вычитает интервал времени или даты из указанной даты или даты со временем. + +**Синтаксис** + +``` sql +date_sub(unit, value, date) +``` + +Синонимы: `dateSub`, `DATE_SUB`. + +**Аргументы** + +- `unit` — единица измерения времени, в которой задан интервал для вычитания. [String](../../sql-reference/data-types/string.md). + Возможные значения: + + - `second` + - `minute` + - `hour` + - `day` + - `week` + - `month` + - `quarter` + - `year` + +- `value` — значение интервала для вычитания. [Int](../../sql-reference/data-types/int-uint.md). +- `date` — дата или дата со временем, из которой вычитается `value`. [Date](../../sql-reference/data-types/date.md) или [DateTime](../../sql-reference/data-types/datetime.md). + +**Возвращаемое значение** + +Дата или дата со временем, полученная в результате вычитания `value`, выраженного в `unit`, из `date`. + +Тип: [Date](../../sql-reference/data-types/date.md) или [DateTime](../../sql-reference/data-types/datetime.md). + +**Пример** + +Запрос: + +``` sql +SELECT date_sub(YEAR, 3, toDate('2018-01-01')); +``` + +Результат: + +``` text +┌─minus(toDate('2018-01-01'), toIntervalYear(3))─┐ +│ 2015-01-01 │ +└────────────────────────────────────────────────┘ +``` + +## timestamp\_add {#timestamp_add} + +Добавляет интервал времени к указанной дате или дате со временем. + +**Синтаксис** + +``` sql +timestamp_add(date, INTERVAL value unit) +``` + +Синонимы: `timeStampAdd`, `TIMESTAMP_ADD`. + +**Аргументы** + +- `date` — дата или дата со временем. [Date](../../sql-reference/data-types/date.md) или [DateTime](../../sql-reference/data-types/datetime.md). +- `value` — значение интервала для добавления. [Int](../../sql-reference/data-types/int-uint.md). +- `unit` — единица измерения времени, в которой задан интервал для добавления. [String](../../sql-reference/data-types/string.md). + Возможные значения: + + - `second` + - `minute` + - `hour` + - `day` + - `week` + - `month` + - `quarter` + - `year` + +**Возвращаемое значение** + +Дата или дата со временем, полученная в результате добавления `value`, выраженного в `unit`, к `date`. + +Тип: [Date](../../sql-reference/data-types/date.md) или [DateTime](../../sql-reference/data-types/datetime.md). + +**Пример** + +Запрос: + +```sql +select timestamp_add(toDate('2018-01-01'), INTERVAL 3 MONTH); +``` + +Результат: + +```text +┌─plus(toDate('2018-01-01'), toIntervalMonth(3))─┐ +│ 2018-04-01 │ +└────────────────────────────────────────────────┘ +``` + +## timestamp\_sub {#timestamp_sub} + +Вычитает интервал времени из указанной даты или даты со временем. + +**Синтакис** + +``` sql +timestamp_sub(unit, value, date) +``` + +Синонимы: `timeStampSub`, `TIMESTAMP_SUB`. + +**Аргументы** + +- `unit` — единица измерения времени, в которой задан интервал для вычитания. [String](../../sql-reference/data-types/string.md). + Возможные значения: + + - `second` + - `minute` + - `hour` + - `day` + - `week` + - `month` + - `quarter` + - `year` + +- `value` — значение интервала для вычитания. [Int](../../sql-reference/data-types/int-uint.md). +- `date` — дата или дата со временем. [Date](../../sql-reference/data-types/date.md) или [DateTime](../../sql-reference/data-types/datetime.md). + +**Возвращаемое значение** + +Дата или дата со временем, полученная в результате вычитания `value`, выраженного в `unit`, из `date`. + +Тип: [Date](../../sql-reference/data-types/date.md) или [DateTime](../../sql-reference/data-types/datetime.md). + +**Пример** + +Запрос: + +```sql +select timestamp_sub(MONTH, 5, toDateTime('2018-12-18 01:02:03')); +``` + +Результат: + +```text +┌─minus(toDateTime('2018-12-18 01:02:03'), toIntervalMonth(5))─┐ +│ 2018-07-18 01:02:03 │ +└──────────────────────────────────────────────────────────────┘ +``` + ## now {#now} Возвращает текущую дату и время. @@ -478,7 +770,7 @@ now([timezone]) **Параметры** -- `timezone` — [часовой пояс](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone) для возвращаемого значения (необязательно). [String](../../sql-reference/data-types/string.md) +- `timezone` — [часовой пояс](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone) для возвращаемого значения (необязательно). [String](../../sql-reference/data-types/string.md). **Возвращаемое значение** @@ -518,68 +810,13 @@ SELECT now('Europe/Moscow'); ## today {#today} -Принимает ноль аргументов и возвращает текущую дату на один из моментов выполнения запроса. +Возвращает текущую дату на момент выполнения запроса. Функция не требует аргументов. То же самое, что toDate(now()) ## yesterday {#yesterday} -Принимает ноль аргументов и возвращает вчерашнюю дату на один из моментов выполнения запроса. -Делает то же самое, что today() - 1. - -## dateDiff {#datediff} - -Вычисляет разницу между двумя значениями дат с временем. - -**Синтаксис** - -``` sql -dateDiff('unit', startdate, enddate, [timezone]) -``` - -**Параметры** - -- `unit` — Единица измерения времени, в которой будет вычислена разница между `startdate` и `enddate`. [String](../syntax.md#syntax-string-literal). - - Поддерживаемые значения: - - | unit | - | ------ | - |second | - |minute | - |hour | - |day | - |week | - |month | - |quarter | - |year | - -- `startdate` — Первая дата. [Date](../../sql-reference/functions/date-time-functions.md) или [DateTime](../../sql-reference/functions/date-time-functions.md). - -- `enddate` — Вторая дата. [Date](../../sql-reference/functions/date-time-functions.md) или [DateTime](../../sql-reference/functions/date-time-functions.md). - -- `timezone` — Опциональный параметр. Если определен, применяется к обоим значениям: `startdate` и `enddate`. Если не определен, используются часовые пояса `startdate` и `enddate`. Если часовые пояса не совпадают, вернется неожидаемый результат. - -**Возвращаемое значение** - -Разница между `startdate` и `enddate`, выраженная в `unit`. - -Тип: `int`. - -**Пример** - -Запрос: - -``` sql -SELECT dateDiff('hour', toDateTime('2018-01-01 22:00:00'), toDateTime('2018-01-02 23:00:00')); -``` - -Ответ: - -``` text -┌─dateDiff('hour', toDateTime('2018-01-01 22:00:00'), toDateTime('2018-01-02 23:00:00'))─┐ -│ 25 │ -└────────────────────────────────────────────────────────────────────────────────────────┘ -``` +Возвращает вчерашнюю дату на момент выполнения запроса. +Делает то же самое, что today() - 1. Функция не требует аргументов. ## timeSlot {#timeslot} @@ -654,10 +891,10 @@ formatDateTime(Time, Format\[, Timezone\]) Запрос: ``` sql -SELECT formatDateTime(toDate('2010-01-04'), '%g') +SELECT formatDateTime(toDate('2010-01-04'), '%g'); ``` -Ответ: +Результат: ``` ┌─formatDateTime(toDate('2010-01-04'), '%g')─┐ @@ -665,4 +902,43 @@ SELECT formatDateTime(toDate('2010-01-04'), '%g') └────────────────────────────────────────────┘ ``` +## FROM\_UNIXTIME {#fromunixtime} + +Функция преобразует Unix timestamp в календарную дату и время. + +**Примеры** + +Если указан только один аргумент типа [Integer](../../sql-reference/data-types/int-uint.md), то функция действует так же, как [toDateTime](../../sql-reference/functions/type-conversion-functions.md#todatetime), и возвращает тип [DateTime](../../sql-reference/data-types/datetime.md). + +Запрос: + +```sql +SELECT FROM_UNIXTIME(423543535); +``` + +Результат: + +```text +┌─FROM_UNIXTIME(423543535)─┐ +│ 1983-06-04 10:58:55 │ +└──────────────────────────┘ +``` + +В случае, когда есть два аргумента: первый типа [Integer](../../sql-reference/data-types/int-uint.md) или [DateTime](../../sql-reference/data-types/datetime.md), а второй является строкой постоянного формата — функция работает также, как [formatDateTime](#formatdatetime), и возвращает значение типа [String](../../sql-reference/data-types/string.md#string). + + +Запрос: + +```sql +SELECT FROM_UNIXTIME(1234334543, '%Y-%m-%d %R:%S') AS DateTime; +``` + +Результат: + +```text +┌─DateTime────────────┐ +│ 2009-02-11 14:42:23 │ +└─────────────────────┘ +``` + [Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/functions/date_time_functions/) diff --git a/docs/ru/sql-reference/functions/encoding-functions.md b/docs/ru/sql-reference/functions/encoding-functions.md index 6f1c2aad6cb..951c6c60e38 100644 --- a/docs/ru/sql-reference/functions/encoding-functions.md +++ b/docs/ru/sql-reference/functions/encoding-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 52 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f" +toc_title: "Функции кодирования" --- # Функции кодирования {#funktsii-kodirovaniia} @@ -75,6 +75,8 @@ SELECT char(0xE4, 0xBD, 0xA0, 0xE5, 0xA5, 0xBD) AS hello; Returns a string containing the argument’s hexadecimal representation. +Синоним: `HEX`. + **Syntax** ``` sql diff --git a/docs/ru/sql-reference/functions/encryption-functions.md b/docs/ru/sql-reference/functions/encryption-functions.md index f1f6516d453..a7adb40e631 100644 --- a/docs/ru/sql-reference/functions/encryption-functions.md +++ b/docs/ru/sql-reference/functions/encryption-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 67 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f" +toc_title: "Функции для шифрования" --- # Функции шифрования {#encryption-functions} @@ -11,7 +11,7 @@ toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0448 Длина инициализирующего вектора всегда 16 байт (лишнии байты игнорируются). -Обратите внимание, что эти функции работают медленно. +Обратите внимание, что до версии Clickhouse 21.1 эти функции работали медленно. ## encrypt {#encrypt} @@ -41,7 +41,7 @@ encrypt('mode', 'plaintext', 'key' [, iv, aad]) **Возвращаемое значение** -- Зашифрованная строка. [String](../../sql-reference/data-types/string.md#string). +- Бинарная зашифрованная строка. [String](../../sql-reference/data-types/string.md#string). **Примеры** @@ -52,57 +52,38 @@ encrypt('mode', 'plaintext', 'key' [, iv, aad]) ``` sql CREATE TABLE encryption_test ( - input String, - key String DEFAULT unhex('fb9958e2e897ef3fdb49067b51a24af645b3626eed2f9ea1dc7fd4dd71b7e38f9a68db2a3184f952382c783785f9d77bf923577108a88adaacae5c141b1576b0'), - iv String DEFAULT unhex('8CA3554377DFF8A369BC50A89780DD85'), - key32 String DEFAULT substring(key, 1, 32), - key24 String DEFAULT substring(key, 1, 24), - key16 String DEFAULT substring(key, 1, 16) -) Engine = Memory; + `comment` String, + `secret` String +) +ENGINE = Memory; ``` -Вставим эти данные: +Вставим некоторые данные (замечание: не храните ключи или инициализирующие векторы в базе данных, так как это компрометирует всю концепцию шифрования), также хранение "подсказок" небезопасно и используется только для наглядности: Запрос: ``` sql -INSERT INTO encryption_test (input) VALUES (''), ('text'), ('What Is ClickHouse?'); +INSERT INTO encryption_test VALUES('aes-256-cfb128 no IV', encrypt('aes-256-cfb128', 'Secret', '12345678910121314151617181920212')),\ +('aes-256-cfb128 no IV, different key', encrypt('aes-256-cfb128', 'Secret', 'keykeykeykeykeykeykeykeykeykeyke')),\ +('aes-256-cfb128 with IV', encrypt('aes-256-cfb128', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv')),\ +('aes-256-cbc no IV', encrypt('aes-256-cbc', 'Secret', '12345678910121314151617181920212')); ``` -Пример без `iv`: - Запрос: ``` sql -SELECT 'aes-128-ecb' AS mode, hex(encrypt(mode, input, key16)) FROM encryption_test; +SELECT comment, hex(secret) FROM encryption_test; ``` Результат: ``` text -┌─mode────────┬─hex(encrypt('aes-128-ecb', input, key16))────────────────────────┐ -│ aes-128-ecb │ 4603E6862B0D94BBEC68E0B0DF51D60F │ -│ aes-128-ecb │ 3004851B86D3F3950672DE7085D27C03 │ -│ aes-128-ecb │ E807F8C8D40A11F65076361AFC7D8B68D8658C5FAA6457985CAA380F16B3F7E4 │ -└─────────────┴──────────────────────────────────────────────────────────────────┘ -``` - -Пример с `iv`: - -Запрос: - -``` sql -SELECT 'aes-256-ctr' AS mode, hex(encrypt(mode, input, key32, iv)) FROM encryption_test; -``` - -Результат: - -``` text -┌─mode────────┬─hex(encrypt('aes-256-ctr', input, key32, iv))─┐ -│ aes-256-ctr │ │ -│ aes-256-ctr │ 7FB039F7 │ -│ aes-256-ctr │ 5CBD20F7ABD3AC41FCAA1A5C0E119E2B325949 │ -└─────────────┴───────────────────────────────────────────────┘ +┌─comment─────────────────────────────┬─hex(secret)──────────────────────┐ +│ aes-256-cfb128 no IV │ B4972BDC4459 │ +│ aes-256-cfb128 no IV, different key │ 2FF57C092DC9 │ +│ aes-256-cfb128 with IV │ 5E6CB398F653 │ +│ aes-256-cbc no IV │ 1BC0629A92450D9E73A00E7D02CF4142 │ +└─────────────────────────────────────┴──────────────────────────────────┘ ``` Пример в режиме `-gcm`: @@ -110,41 +91,27 @@ SELECT 'aes-256-ctr' AS mode, hex(encrypt(mode, input, key32, iv)) FROM encrypti Запрос: ``` sql -SELECT 'aes-256-gcm' AS mode, hex(encrypt(mode, input, key32, iv)) FROM encryption_test; +INSERT INTO encryption_test VALUES('aes-256-gcm', encrypt('aes-256-gcm', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv')), \ +('aes-256-gcm with AAD', encrypt('aes-256-gcm', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv', 'aad')); + +SELECT comment, hex(secret) FROM encryption_test WHERE comment LIKE '%gcm%'; ``` Результат: ``` text -┌─mode────────┬─hex(encrypt('aes-256-gcm', input, key32, iv))──────────────────────────┐ -│ aes-256-gcm │ E99DBEBC01F021758352D7FBD9039EFA │ -│ aes-256-gcm │ 8742CE3A7B0595B281C712600D274CA881F47414 │ -│ aes-256-gcm │ A44FD73ACEB1A64BDE2D03808A2576EDBB60764CC6982DB9AF2C33C893D91B00C60DC5 │ -└─────────────┴────────────────────────────────────────────────────────────────────────┘ -``` - -Пример в режиме `-gcm` и с `aad`: - -Запрос: - -``` sql -SELECT 'aes-192-gcm' AS mode, hex(encrypt(mode, input, key24, iv, 'AAD')) FROM encryption_test; -``` - -Результат: - -``` text -┌─mode────────┬─hex(encrypt('aes-192-gcm', input, key24, iv, 'AAD'))───────────────────┐ -│ aes-192-gcm │ 04C13E4B1D62481ED22B3644595CB5DB │ -│ aes-192-gcm │ 9A6CF0FD2B329B04EAD18301818F016DF8F77447 │ -│ aes-192-gcm │ B961E9FD9B940EBAD7ADDA75C9F198A40797A5EA1722D542890CC976E21113BBB8A7AA │ -└─────────────┴────────────────────────────────────────────────────────────────────────┘ +┌─comment──────────────┬─hex(secret)──────────────────────────────────┐ +│ aes-256-gcm │ A8A3CCBC6426CFEEB60E4EAE03D3E94204C1B09E0254 │ +│ aes-256-gcm with AAD │ A8A3CCBC6426D9A1017A0A932322F1852260A4AD6837 │ +└──────────────────────┴──────────────────────────────────────────────┘ ``` ## aes_encrypt_mysql {#aes_encrypt_mysql} Совместима с шифрованием myqsl, результат может быть расшифрован функцией [AES_DECRYPT](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_aes-decrypt). +При одинаковых входящих значениях зашифрованный текст будет совпадать с результатом, возвращаемым функцией `encrypt`. Однако если `key` или `iv` длиннее, чем должны быть, `aes_encrypt_mysql` будет работать аналогично функции `aes_encrypt` в MySQL: свернет ключ и проигнорирует лишнюю часть `iv`. + Функция поддерживает шифрофание данных следующими режимами: - aes-128-ecb, aes-192-ecb, aes-256-ecb @@ -156,7 +123,7 @@ SELECT 'aes-192-gcm' AS mode, hex(encrypt(mode, input, key24, iv, 'AAD')) FROM e **Синтаксис** -```sql +``` sql aes_encrypt_mysql('mode', 'plaintext', 'key' [, iv]) ``` @@ -164,78 +131,96 @@ aes_encrypt_mysql('mode', 'plaintext', 'key' [, iv]) - `mode` — режим шифрования. [String](../../sql-reference/data-types/string.md#string). - `plaintext` — текст, который будет зашифрован. [String](../../sql-reference/data-types/string.md#string). -- `key` — ключ шифрования. [String](../../sql-reference/data-types/string.md#string). -- `iv` — инициализирующий вектор. Необязателен. [String](../../sql-reference/data-types/string.md#string). +- `key` — ключ шифрования. Если ключ длиннее, чем требует режим шифрования, производится специфичная для MySQL свертка ключа. [String](../../sql-reference/data-types/string.md#string). +- `iv` — инициализирующий вектор. Необязателен, учитываются только первые 16 байтов. [String](../../sql-reference/data-types/string.md#string). **Возвращаемое значение** -- Зашифрованная строка. [String](../../sql-reference/data-types/string.md#string). +- Бинарная зашифрованная строка. [String](../../sql-reference/data-types/string.md#string). **Примеры** -Создадим такую таблицу: +При одинаковых входящих значениях результаты шифрования у функций `encrypt` и `aes_encrypt_mysql` совпадают. Запрос: ``` sql -CREATE TABLE encryption_test -( - input String, - key String DEFAULT unhex('fb9958e2e897ef3fdb49067b51a24af645b3626eed2f9ea1dc7fd4dd71b7e38f9a68db2a3184f952382c783785f9d77bf923577108a88adaacae5c141b1576b0'), - iv String DEFAULT unhex('8CA3554377DFF8A369BC50A89780DD85'), - key32 String DEFAULT substring(key, 1, 32), - key24 String DEFAULT substring(key, 1, 24), - key16 String DEFAULT substring(key, 1, 16) -) Engine = Memory; -``` - -Вставим эти данные: - -Запрос: - -``` sql -INSERT INTO encryption_test (input) VALUES (''), ('text'), ('What Is ClickHouse?'); -``` - -Пример без `iv`: - -Запрос: - -``` sql -SELECT 'aes-128-cbc' AS mode, hex(aes_encrypt_mysql(mode, input, key32)) FROM encryption_test; +SELECT encrypt('aes-256-cfb128', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv') = aes_encrypt_mysql('aes-256-cfb128', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv') AS ciphertexts_equal; ``` Результат: ``` text -┌─mode────────┬─hex(aes_encrypt_mysql('aes-128-cbc', input, key32))──────────────┐ -│ aes-128-cbc │ FEA8CFDE6EE2C6E7A2CC6ADDC9F62C83 │ -│ aes-128-cbc │ 78B16CD4BE107660156124C5FEE6454A │ -│ aes-128-cbc │ 67C0B119D96F18E2823968D42871B3D179221B1E7EE642D628341C2B29BA2E18 │ -└─────────────┴──────────────────────────────────────────────────────────────────┘ +┌─ciphertexts_equal─┐ +│ 1 │ +└───────────────────┘ ``` -Пример с `iv`: +Функция `encrypt` генерирует исключение, если `key` или `iv` длиннее чем нужно: Запрос: ``` sql -SELECT 'aes-256-cfb128' AS mode, hex(aes_encrypt_mysql(mode, input, key32, iv)) FROM encryption_test; +SELECT encrypt('aes-256-cfb128', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123'); ``` Результат: ``` text -┌─mode───────────┬─hex(aes_encrypt_mysql('aes-256-cfb128', input, key32, iv))─┐ -│ aes-256-cfb128 │ │ -│ aes-256-cfb128 │ 7FB039F7 │ -│ aes-256-cfb128 │ 5CBD20F7ABD3AC41FCAA1A5C0E119E2BB5174F │ -└────────────────┴────────────────────────────────────────────────────────────┘ +Received exception from server (version 21.1.2): +Code: 36. DB::Exception: Received from localhost:9000. DB::Exception: Invalid key size: 33 expected 32: While processing encrypt('aes-256-cfb128', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123'). +``` + +Однако функция `aes_encrypt_mysql` в аналогичном случае возвращает результат, который может быть обработан MySQL: + +Запрос: + +``` sql +SELECT hex(aes_encrypt_mysql('aes-256-cfb128', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123')) AS ciphertext; +``` + +Результат: + +```text +┌─ciphertext───┐ +│ 24E9E4966469 │ +└──────────────┘ +``` + +Если передать `iv` еще длиннее, результат останется таким же: + +Запрос: + +``` sql +SELECT hex(aes_encrypt_mysql('aes-256-cfb128', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123456')) AS ciphertext +``` + +Результат: + +``` text +┌─ciphertext───┐ +│ 24E9E4966469 │ +└──────────────┘ +``` + +Это совпадает с результатом, возвращаемым MySQL при таких же входящих значениях: + +``` sql +mysql> SET block_encryption_mode='aes-256-cfb128'; +Query OK, 0 rows affected (0.00 sec) + +mysql> SELECT aes_encrypt('Secret', '123456789101213141516171819202122', 'iviviviviviviviv123456') as ciphertext; ++------------------------+ +| ciphertext | ++------------------------+ +| 0x24E9E4966469 | ++------------------------+ +1 row in set (0.00 sec) ``` ## decrypt {#decrypt} -Функция поддерживает расшифровку данных следующими режимами: +Функция расшифровывает зашифрованный текст и может работать в следующих режимах: - aes-128-ecb, aes-192-ecb, aes-256-ecb - aes-128-cbc, aes-192-cbc, aes-256-cbc @@ -247,7 +232,7 @@ SELECT 'aes-256-cfb128' AS mode, hex(aes_encrypt_mysql(mode, input, key32, iv)) **Синтаксис** -```sql +``` sql decrypt('mode', 'ciphertext', 'key' [, iv, aad]) ``` @@ -265,52 +250,58 @@ decrypt('mode', 'ciphertext', 'key' [, iv, aad]) **Примеры** -Создадим такую таблицу: +Рассмотрим таблицу из примера для функции [encrypt](#encrypt). Запрос: ``` sql -CREATE TABLE encryption_test -( - input String, - key String DEFAULT unhex('fb9958e2e897ef3fdb49067b51a24af645b3626eed2f9ea1dc7fd4dd71b7e38f9a68db2a3184f952382c783785f9d77bf923577108a88adaacae5c141b1576b0'), - iv String DEFAULT unhex('8CA3554377DFF8A369BC50A89780DD85'), - key32 String DEFAULT substring(key, 1, 32), - key24 String DEFAULT substring(key, 1, 24), - key16 String DEFAULT substring(key, 1, 16) -) Engine = Memory; -``` - -Вставим эти данные: - -Запрос: - -``` sql -INSERT INTO encryption_test (input) VALUES (''), ('text'), ('What Is ClickHouse?'); -``` - -Запрос: - -``` sql - -SELECT 'aes-128-ecb' AS mode, decrypt(mode, encrypt(mode, input, key16), key16) FROM encryption_test; +SELECT comment, hex(secret) FROM encryption_test; ``` Результат: -```text -┌─mode────────┬─decrypt('aes-128-ecb', encrypt('aes-128-ecb', input, key16), key16)─┐ -│ aes-128-ecb │ │ -│ aes-128-ecb │ text │ -│ aes-128-ecb │ What Is ClickHouse? │ -└─────────────┴─────────────────────────────────────────────────────────────────────┘ +``` text +┌─comment──────────────┬─hex(secret)──────────────────────────────────┐ +│ aes-256-gcm │ A8A3CCBC6426CFEEB60E4EAE03D3E94204C1B09E0254 │ +│ aes-256-gcm with AAD │ A8A3CCBC6426D9A1017A0A932322F1852260A4AD6837 │ +└──────────────────────┴──────────────────────────────────────────────┘ +┌─comment─────────────────────────────┬─hex(secret)──────────────────────┐ +│ aes-256-cfb128 no IV │ B4972BDC4459 │ +│ aes-256-cfb128 no IV, different key │ 2FF57C092DC9 │ +│ aes-256-cfb128 with IV │ 5E6CB398F653 │ +│ aes-256-cbc no IV │ 1BC0629A92450D9E73A00E7D02CF4142 │ +└─────────────────────────────────────┴──────────────────────────────────┘ ``` +Теперь попытаемся расшифровать эти данные: + +Запрос: + +``` sql +SELECT comment, decrypt('aes-256-cfb128', secret, '12345678910121314151617181920212') as plaintext FROM encryption_test; +``` + +Результат: + +``` text +┌─comment─────────────────────────────┬─plaintext─┐ +│ aes-256-cfb128 no IV │ Secret │ +│ aes-256-cfb128 no IV, different key │ �4� + � │ +│ aes-256-cfb128 with IV │ ���6�~ │ + │aes-256-cbc no IV │ �2*4�h3c�4w��@ +└─────────────────────────────────────┴───────────┘ +``` + +Обратите внимание, что только часть данных была расшифрована верно. Оставшаяся часть расшифрована некорректно, так как при шифровании использовались другие значения `mode`, `key`, или `iv`. + ## aes_decrypt_mysql {#aes_decrypt_mysql} Совместима с шифрованием myqsl и может расшифровать данные, зашифрованные функцией [AES_ENCRYPT](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_aes-encrypt). -Функция поддерживает расшифровку данных следующими режимами: +При одинаковых входящих значениях расшифрованный текст будет совпадать с результатом, возвращаемым функцией `decrypt`. Однако если `key` или `iv` длиннее, чем должны быть, `aes_decrypt_mysql` будет работать аналогично функции `aes_decrypt` в MySQL: свернет ключ и проигнорирует лишнюю часть `iv`. + +Функция поддерживает расшифровку данных в следующих режимах: - aes-128-ecb, aes-192-ecb, aes-256-ecb - aes-128-cbc, aes-192-cbc, aes-256-cbc @@ -321,7 +312,7 @@ SELECT 'aes-128-ecb' AS mode, decrypt(mode, encrypt(mode, input, key16), key16) **Синтаксис** -```sql +``` sql aes_decrypt_mysql('mode', 'ciphertext', 'key' [, iv]) ``` @@ -332,51 +323,39 @@ aes_decrypt_mysql('mode', 'ciphertext', 'key' [, iv]) - `key` — ключ шифрования. [String](../../sql-reference/data-types/string.md#string). - `iv` — инициализирующий вектор. Необязателен. [String](../../sql-reference/data-types/string.md#string). - **Возвращаемое значение** - Расшифрованная строка. [String](../../sql-reference/data-types/string.md#string). **Примеры** -Создадим такую таблицу: +Расшифруем данные, которые до этого были зашифрованы в MySQL: -Запрос: ``` sql -CREATE TABLE encryption_test -( - input String, - key String DEFAULT unhex('fb9958e2e897ef3fdb49067b51a24af645b3626eed2f9ea1dc7fd4dd71b7e38f9a68db2a3184f952382c783785f9d77bf923577108a88adaacae5c141b1576b0'), - iv String DEFAULT unhex('8CA3554377DFF8A369BC50A89780DD85'), - key32 String DEFAULT substring(key, 1, 32), - key24 String DEFAULT substring(key, 1, 24), - key16 String DEFAULT substring(key, 1, 16) -) Engine = Memory; -``` +mysql> SET block_encryption_mode='aes-256-cfb128'; +Query OK, 0 rows affected (0.00 sec) -Вставим эти данные: - -Запрос: - -``` sql -INSERT INTO encryption_test (input) VALUES (''), ('text'), ('What Is ClickHouse?'); +mysql> SELECT aes_encrypt('Secret', '123456789101213141516171819202122', 'iviviviviviviviv123456') as ciphertext; ++------------------------+ +| ciphertext | ++------------------------+ +| 0x24E9E4966469 | ++------------------------+ +1 row in set (0.00 sec) ``` Запрос: ``` sql -SELECT 'aes-128-cbc' AS mode, aes_decrypt_mysql(mode, aes_encrypt_mysql(mode, input, key), key) FROM encryption_test; +SELECT aes_decrypt_mysql('aes-256-cfb128', unhex('24E9E4966469'), '123456789101213141516171819202122', 'iviviviviviviviv123456') AS plaintext; ``` Результат: ``` text -┌─mode────────┬─aes_decrypt_mysql('aes-128-cbc', aes_encrypt_mysql('aes-128-cbc', input, key), key)─┐ -│ aes-128-cbc │ │ -│ aes-128-cbc │ text │ -│ aes-128-cbc │ What Is ClickHouse? │ -└─────────────┴─────────────────────────────────────────────────────────────────────────────────────┘ +┌─plaintext─┐ +│ Secret │ +└───────────┘ ``` - [Original article](https://clickhouse.tech/docs/ru/sql-reference/functions/encryption_functions/) diff --git a/docs/ru/sql-reference/functions/ext-dict-functions.md b/docs/ru/sql-reference/functions/ext-dict-functions.md index 6054ed141d4..8d018e8e9ac 100644 --- a/docs/ru/sql-reference/functions/ext-dict-functions.md +++ b/docs/ru/sql-reference/functions/ext-dict-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 58 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u0020\u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u044f\u043c\u0438" +toc_title: "Функции для работы с внешними словарями" --- # Функции для работы с внешними словарями {#ext_dict_functions} diff --git a/docs/ru/sql-reference/functions/functions-for-nulls.md b/docs/ru/sql-reference/functions/functions-for-nulls.md index 17da1ea9194..f0277a59699 100644 --- a/docs/ru/sql-reference/functions/functions-for-nulls.md +++ b/docs/ru/sql-reference/functions/functions-for-nulls.md @@ -1,6 +1,6 @@ --- toc_priority: 63 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u0020\u004e\u0075\u006c\u006c\u0061\u0062\u006c\u0065\u002d\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438" +toc_title: "Функции для работы с Nullable-аргументами" --- # Функции для работы с Nullable-аргументами {#funktsii-dlia-raboty-s-nullable-argumentami} @@ -13,6 +13,8 @@ toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u isNull(x) ``` +Синоним: `ISNULL`. + **Параметры** - `x` — значение с не составным типом данных. diff --git a/docs/ru/sql-reference/functions/geo/coordinates.md b/docs/ru/sql-reference/functions/geo/coordinates.md index 1931a9b932f..09e2d7d01bf 100644 --- a/docs/ru/sql-reference/functions/geo/coordinates.md +++ b/docs/ru/sql-reference/functions/geo/coordinates.md @@ -1,5 +1,5 @@ --- -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u0020\u0433\u0435\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438\u0020\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438" +toc_title: "Функции для работы с географическими координатами" toc_priority: 62 --- diff --git a/docs/ru/sql-reference/functions/geo/geohash.md b/docs/ru/sql-reference/functions/geo/geohash.md index 38c64f11b10..2dd3f83ddf1 100644 --- a/docs/ru/sql-reference/functions/geo/geohash.md +++ b/docs/ru/sql-reference/functions/geo/geohash.md @@ -1,5 +1,5 @@ --- -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u0020\u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439\u0020\u0047\u0065\u006f\u0068\u0061\u0073\u0068" +toc_title: "Функции для работы с системой Geohash" --- # Функции для работы с системой Geohash {#geohash} diff --git a/docs/ru/sql-reference/functions/geo/h3.md b/docs/ru/sql-reference/functions/geo/h3.md index 69d06b5dfa6..7046833f7ec 100644 --- a/docs/ru/sql-reference/functions/geo/h3.md +++ b/docs/ru/sql-reference/functions/geo/h3.md @@ -1,5 +1,5 @@ --- -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u0020\u0438\u043d\u0434\u0435\u043a\u0441\u0430\u043c\u0438\u0020\u0048\u0033" +toc_title: "Функции для работы с индексами H3" --- # Функции для работы с индексами H3 {#h3index} diff --git a/docs/ru/sql-reference/functions/geo/index.md b/docs/ru/sql-reference/functions/geo/index.md index cedaafaa31d..6b9a14e4d02 100644 --- a/docs/ru/sql-reference/functions/geo/index.md +++ b/docs/ru/sql-reference/functions/geo/index.md @@ -1,6 +1,6 @@ --- toc_priority: 62 -toc_folder_title: "\u0413\u0435\u043e\u002d\u0434\u0430\u043d\u043d\u044b\u0435" +toc_folder_title: "Гео-данные" toc_title: hidden --- diff --git a/docs/ru/sql-reference/functions/hash-functions.md b/docs/ru/sql-reference/functions/hash-functions.md index f7820889ea9..1742abe5b56 100644 --- a/docs/ru/sql-reference/functions/hash-functions.md +++ b/docs/ru/sql-reference/functions/hash-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 50 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0445\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f" +toc_title: "Функции хэширования" --- # Функции хэширования {#funktsii-kheshirovaniia} diff --git a/docs/ru/sql-reference/functions/in-functions.md b/docs/ru/sql-reference/functions/in-functions.md index b732f67303b..7326d087610 100644 --- a/docs/ru/sql-reference/functions/in-functions.md +++ b/docs/ru/sql-reference/functions/in-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 60 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\u0020\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u0020\u0049\u004e" +toc_title: "Функции для реализации оператора IN" --- # Функции для реализации оператора IN {#funktsii-dlia-realizatsii-operatora-in} diff --git a/docs/ru/sql-reference/functions/index.md b/docs/ru/sql-reference/functions/index.md index 25d3b6de067..ae3879b6c96 100644 --- a/docs/ru/sql-reference/functions/index.md +++ b/docs/ru/sql-reference/functions/index.md @@ -1,7 +1,7 @@ --- -toc_folder_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438" +toc_folder_title: "Функции" toc_priority: 32 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435" +toc_title: "Введение" --- # Функции {#funktsii} diff --git a/docs/ru/sql-reference/functions/introspection.md b/docs/ru/sql-reference/functions/introspection.md index 00dd660bc16..4cd7e5d273b 100644 --- a/docs/ru/sql-reference/functions/introspection.md +++ b/docs/ru/sql-reference/functions/introspection.md @@ -1,6 +1,6 @@ --- toc_priority: 65 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0438\u043d\u0442\u0440\u043e\u0441\u043f\u0435\u043a\u0446\u0438\u0438" +toc_title: "Функции интроспекции" --- # Функции интроспекции {#introspection-functions} diff --git a/docs/ru/sql-reference/functions/ip-address-functions.md b/docs/ru/sql-reference/functions/ip-address-functions.md index 724fb97c0d5..a2a08b1938e 100644 --- a/docs/ru/sql-reference/functions/ip-address-functions.md +++ b/docs/ru/sql-reference/functions/ip-address-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 55 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u0020\u0049\u0050\u002d\u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0438" +toc_title: "Функции для работы с IP-адресами" --- # Функции для работы с IP-адресами {#funktsii-dlia-raboty-s-ip-adresami} @@ -9,10 +9,14 @@ toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u Принимает число типа UInt32. Интерпретирует его, как IPv4-адрес в big endian. Возвращает строку, содержащую соответствующий IPv4-адрес в формате A.B.C.D (числа в десятичной форме через точки). +Синоним: `INET_NTOA`. + ## IPv4StringToNum(s) {#ipv4stringtonums} Функция, обратная к IPv4NumToString. Если IPv4 адрес в неправильном формате, то возвращает 0. +Синоним: `INET_ATON`. + ## IPv4NumToStringClassC(num) {#ipv4numtostringclasscnum} Похоже на IPv4NumToString, но вместо последнего октета используется xxx. @@ -49,7 +53,11 @@ LIMIT 10 ### IPv6NumToString(x) {#ipv6numtostringx} Принимает значение типа FixedString(16), содержащее IPv6-адрес в бинарном виде. Возвращает строку, содержащую этот адрес в текстовом виде. -IPv6-mapped IPv4 адреса выводится в формате ::ffff:111.222.33.44. Примеры: +IPv6-mapped IPv4 адреса выводится в формате ::ffff:111.222.33.44. + +Примеры: `INET6_NTOA`. + +Примеры: ``` sql SELECT IPv6NumToString(toFixedString(unhex('2A0206B8000000000000000000000011'), 16)) AS addr @@ -113,11 +121,54 @@ LIMIT 10 └────────────────────────────┴────────┘ ``` -## IPv6StringToNum(s) {#ipv6stringtonums} +## IPv6StringToNum {#ipv6stringtonums} + +Функция, обратная к [IPv6NumToString](#ipv6numtostringx). Если IPv6 адрес передан в неправильном формате, то возвращает строку из нулевых байт. + +Если IP адрес является корректным IPv4 адресом, функция возвращает его IPv6 эквивалент. -Функция, обратная к IPv6NumToString. Если IPv6 адрес в неправильном формате, то возвращает строку из нулевых байт. HEX может быть в любом регистре. +Синоним: `INET6_ATON`. + +**Синтаксис** + +``` sql +IPv6StringToNum(string) +``` + +**Аргумент** + +- `string` — IP адрес. [String](../../sql-reference/data-types/string.md). + +**Возвращаемое значение** + +- Адрес IPv6 в двоичном представлении. + +Тип: [FixedString(16)](../../sql-reference/data-types/fixedstring.md). + +**Пример** + +Запрос: + +``` sql +SELECT addr, cutIPv6(IPv6StringToNum(addr), 0, 0) FROM (SELECT ['notaddress', '127.0.0.1', '1111::ffff'] AS addr) ARRAY JOIN addr; +``` + +Результат: + +``` text +┌─addr───────┬─cutIPv6(IPv6StringToNum(addr), 0, 0)─┐ +│ notaddress │ :: │ +│ 127.0.0.1 │ ::ffff:127.0.0.1 │ +│ 1111::ffff │ 1111::ffff │ +└────────────┴──────────────────────────────────────┘ +``` + +**Смотрите также** + +- [cutIPv6](#cutipv6x-bytestocutforipv6-bytestocutforipv4). + ## IPv4ToIPv6(x) {#ipv4toipv6x} Принимает число типа `UInt32`. Интерпретирует его, как IPv4-адрес в [big endian](https://en.wikipedia.org/wiki/Endianness). Возвращает значение `FixedString(16)`, содержащее адрес IPv6 в двоичном формате. Примеры: @@ -211,36 +262,137 @@ SELECT └───────────────────────────────────┴──────────────────────────┘ ``` -## toIPv6(string) {#toipv6string} +## toIPv6 {#toipv6string} -Псевдоним функции `IPv6StringToNum()` которая принимает строку с адресом IPv6 и возвращает значение типа [IPv6](../../sql-reference/functions/ip-address-functions.md), которое равно значению, возвращаемому функцией `IPv6StringToNum()`. +Приводит строку с адресом в формате IPv6 к типу [IPv6](../../sql-reference/data-types/domains/ipv6.md). Возвращает пустое значение, если входящая строка не является корректным IP адресом. +Похоже на функцию [IPv6StringToNum](#ipv6stringtonums), которая представляет адрес IPv6 в двоичном виде. -``` sql -WITH - '2001:438:ffff::407d:1bc1' as IPv6_string -SELECT - toTypeName(IPv6StringToNum(IPv6_string)), - toTypeName(toIPv6(IPv6_string)) +Если входящая строка содержит корректный IPv4 адрес, функция возвращает его IPv6 эквивалент. + +**Синтаксис** + +```sql +toIPv6(string) ``` -``` text -┌─toTypeName(IPv6StringToNum(IPv6_string))─┬─toTypeName(toIPv6(IPv6_string))─┐ -│ FixedString(16) │ IPv6 │ -└──────────────────────────────────────────┴─────────────────────────────────┘ -``` +**Аргумент** + +- `string` — IP адрес. [String](../../sql-reference/data-types/string.md) + +**Возвращаемое значение** + +- IP адрес. + +Тип: [IPv6](../../sql-reference/data-types/domains/ipv6.md). + +**Примеры** + +Запрос: ``` sql -WITH - '2001:438:ffff::407d:1bc1' as IPv6_string +WITH '2001:438:ffff::407d:1bc1' AS IPv6_string SELECT hex(IPv6StringToNum(IPv6_string)), - hex(toIPv6(IPv6_string)) + hex(toIPv6(IPv6_string)); ``` +Результат: + ``` text ┌─hex(IPv6StringToNum(IPv6_string))─┬─hex(toIPv6(IPv6_string))─────────┐ │ 20010438FFFF000000000000407D1BC1 │ 20010438FFFF000000000000407D1BC1 │ └───────────────────────────────────┴──────────────────────────────────┘ ``` +Запрос: + +``` sql +SELECT toIPv6('127.0.0.1'); +``` + +Результат: + +``` text +┌─toIPv6('127.0.0.1')─┐ +│ ::ffff:127.0.0.1 │ +└─────────────────────┘ +``` + +## isIPv4String {#isipv4string} + +Определяет, является ли строка адресом IPv4 или нет. Также вернет `0`, если `string` — адрес IPv6. + +**Синтаксис** + +```sql +isIPv4String(string) +``` + +**Параметры** + +- `string` — IP адрес. [String](../../sql-reference/data-types/string.md). + +**Возвращаемое значение** + +- `1` если `string` является адресом IPv4 , иначе — `0`. + +Тип: [UInt8](../../sql-reference/data-types/int-uint.md). + +**Примеры** + +Запрос: + +```sql +SELECT addr, isIPv4String(addr) FROM ( SELECT ['0.0.0.0', '127.0.0.1', '::ffff:127.0.0.1'] AS addr ) ARRAY JOIN addr +``` + +Результат: + +``` text +┌─addr─────────────┬─isIPv4String(addr)─┐ +│ 0.0.0.0 │ 1 │ +│ 127.0.0.1 │ 1 │ +│ ::ffff:127.0.0.1 │ 0 │ +└──────────────────┴────────────────────┘ +``` + +## isIPv6String {#isipv6string} + +Определяет, является ли строка адресом IPv6 или нет. Также вернет `0`, если `string` — адрес IPv4. + +**Синтаксис** + +```sql +isIPv6String(string) +``` + +**Параметры** + +- `string` — IP адрес. [String](../../sql-reference/data-types/string.md). + +**Возвращаемое значение** + +- `1` если `string` является адресом IPv6 , иначе — `0`. + +Тип: [UInt8](../../sql-reference/data-types/int-uint.md). + +**Примеры** + +Запрос: + +``` sql +SELECT addr, isIPv6String(addr) FROM ( SELECT ['::', '1111::ffff', '::ffff:127.0.0.1', '127.0.0.1'] AS addr ) ARRAY JOIN addr +``` + +Результат: + +``` text +┌─addr─────────────┬─isIPv6String(addr)─┐ +│ :: │ 1 │ +│ 1111::ffff │ 1 │ +│ ::ffff:127.0.0.1 │ 1 │ +│ 127.0.0.1 │ 0 │ +└──────────────────┴────────────────────┘ +``` + [Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/functions/ip_address_functions/) diff --git a/docs/ru/sql-reference/functions/logical-functions.md b/docs/ru/sql-reference/functions/logical-functions.md index 9b1ee6a66a7..2d71c60a509 100644 --- a/docs/ru/sql-reference/functions/logical-functions.md +++ b/docs/ru/sql-reference/functions/logical-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 37 -toc_title: "\u041b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435\u0020\u0444\u0443\u043d\u043a\u0446\u0438\u0438" +toc_title: "Логические функции" --- # Логические функции {#logicheskie-funktsii} diff --git a/docs/ru/sql-reference/functions/machine-learning-functions.md b/docs/ru/sql-reference/functions/machine-learning-functions.md index 2ffdfd05613..decbff56646 100644 --- a/docs/ru/sql-reference/functions/machine-learning-functions.md +++ b/docs/ru/sql-reference/functions/machine-learning-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 64 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e\u0020\u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f" +toc_title: "Функции машинного обучения" --- # Функции машинного обучения {#funktsii-mashinnogo-obucheniia} diff --git a/docs/ru/sql-reference/functions/math-functions.md b/docs/ru/sql-reference/functions/math-functions.md index 2e57aca6a0a..a5ba01f6282 100644 --- a/docs/ru/sql-reference/functions/math-functions.md +++ b/docs/ru/sql-reference/functions/math-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 44 -toc_title: "\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435\u0020\u0444\u0443\u043d\u043a\u0446\u0438\u0438" +toc_title: "Математические функции" --- # Математические функции {#matematicheskie-funktsii} @@ -405,4 +405,67 @@ SELECT log1p(0); - [log(x)](../../sql-reference/functions/math-functions.md#logx) +## sign(x) {#signx} + +Возвращает знак действительного числа. + +**Синтаксис** + +``` sql +sign(x) +``` + +**Аргумент** + +- `x` — Значения от `-∞` до `+∞`. Любой числовой тип, поддерживаемый ClickHouse. + +**Возвращаемое значение** + +- -1 если `x < 0` +- 0 если `x = 0` +- 1 если `x > 0` + +**Примеры** + +Результат sign() для нуля: + +``` sql +SELECT sign(0); +``` +Результат: + +``` text +┌─sign(0)─┐ +│ 0 │ +└─────────┘ +``` + +Результат sign() для положительного аргумента: + +``` sql +SELECT sign(1); +``` + +Результат: + +``` text +┌─sign(1)─┐ +│ 1 │ +└─────────┘ +``` + +Результат sign() для отрицательного аргумента: + +``` sql +SELECT sign(-1); +``` + +Результат: + +``` text +┌─sign(-1)─┐ +│ -1 │ +└──────────┘ +``` + [Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/functions/math_functions/) diff --git a/docs/ru/sql-reference/functions/other-functions.md b/docs/ru/sql-reference/functions/other-functions.md index a738ba755b1..595d2458ca9 100644 --- a/docs/ru/sql-reference/functions/other-functions.md +++ b/docs/ru/sql-reference/functions/other-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 66 -toc_title: "\u041f\u0440\u043e\u0447\u0438\u0435\u0020\u0444\u0443\u043d\u043a\u0446\u0438\u0438" +toc_title: "Прочие функции" --- # Прочие функции {#other-functions} @@ -659,7 +659,7 @@ SELECT ## neighbor {#neighbor} -Функция позволяет получить доступ к значению в колонке `column`, находящемуся на смещении `offset` относительно текущей строки. Является частичной реализацией [оконных функций](https://en.wikipedia.org/wiki/SQL_window_function) `LEAD()` и `LAG()`. +Функция позволяет получить доступ к значению в столбце `column`, находящемуся на смещении `offset` относительно текущей строки. Является частичной реализацией [оконных функций](https://en.wikipedia.org/wiki/SQL_window_function) `LEAD()` и `LAG()`. **Синтаксис** @@ -667,7 +667,13 @@ SELECT neighbor(column, offset[, default_value]) ``` -Результат функции зависит от затронутых блоков данных и порядка данных в блоке. Если сделать подзапрос с ORDER BY и вызывать функцию извне подзапроса, можно будет получить ожидаемый результат. +Результат функции зависит от затронутых блоков данных и порядка данных в блоке. + +!!! warning "Предупреждение" + Функция может получить доступ к значению в столбце соседней строки только внутри обрабатываемого в данный момент блока данных. + +Порядок строк, используемый при вычислении функции `neighbor`, может отличаться от порядка строк, возвращаемых пользователю. +Чтобы этого не случилось, вы можете сделать подзапрос с [ORDER BY](../../sql-reference/statements/select/order-by.md) и вызвать функцию изне подзапроса. **Параметры** @@ -772,8 +778,13 @@ FROM numbers(16) Считает разницу между последовательными значениями строк в блоке данных. Возвращает 0 для первой строки и разницу с предыдущей строкой для каждой последующей строки. +!!! warning "Предупреждение" + Функция может взять значение предыдущей строки только внутри текущего обработанного блока данных. + Результат функции зависит от затронутых блоков данных и порядка данных в блоке. -Если сделать подзапрос с ORDER BY и вызывать функцию извне подзапроса, можно будет получить ожидаемый результат. + +Порядок строк, используемый при вычислении функции `runningDifference`, может отличаться от порядка строк, возвращаемых пользователю. +Чтобы этого не случилось, вы можете сделать подзапрос с [ORDER BY](../../sql-reference/statements/select/order-by.md) и вызвать функцию извне подзапроса. Пример: diff --git a/docs/ru/sql-reference/functions/random-functions.md b/docs/ru/sql-reference/functions/random-functions.md index f3889504fa6..a09f5159309 100644 --- a/docs/ru/sql-reference/functions/random-functions.md +++ b/docs/ru/sql-reference/functions/random-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 51 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438\u0020\u043f\u0441\u0435\u0432\u0434\u043e\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445\u0020\u0447\u0438\u0441\u0435\u043b" +toc_title: "Функции генерации псевдослучайных чисел" --- # Функции генерации псевдослучайных чисел {#functions-for-generating-pseudo-random-numbers} diff --git a/docs/ru/sql-reference/functions/rounding-functions.md b/docs/ru/sql-reference/functions/rounding-functions.md index 78033160396..704e7f5dd52 100644 --- a/docs/ru/sql-reference/functions/rounding-functions.md +++ b/docs/ru/sql-reference/functions/rounding-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 45 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u043e\u043a\u0440\u0443\u0433\u043b\u0435\u043d\u0438\u044f" +toc_title: "Функции округления" --- # Функции округления {#funktsii-okrugleniia} diff --git a/docs/ru/sql-reference/functions/splitting-merging-functions.md b/docs/ru/sql-reference/functions/splitting-merging-functions.md index d451eabc407..cacce5f4ba2 100644 --- a/docs/ru/sql-reference/functions/splitting-merging-functions.md +++ b/docs/ru/sql-reference/functions/splitting-merging-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 47 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0440\u0430\u0437\u0431\u0438\u0435\u043d\u0438\u044f\u0020\u0438\u0020\u0441\u043b\u0438\u044f\u043d\u0438\u044f\u0020\u0441\u0442\u0440\u043e\u043a\u0020\u0438\u0020\u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432" +toc_title: "Функции разбиения и слияния строк и массивов" --- # Функции разбиения и слияния строк и массивов {#funktsii-razbieniia-i-sliianiia-strok-i-massivov} diff --git a/docs/ru/sql-reference/functions/string-functions.md b/docs/ru/sql-reference/functions/string-functions.md index aeb0652cc18..65a1cd63563 100644 --- a/docs/ru/sql-reference/functions/string-functions.md +++ b/docs/ru/sql-reference/functions/string-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 40 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u043e\u0020\u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438" +toc_title: "Функции для работы со строками" --- # Функции для работы со строками {#funktsii-dlia-raboty-so-strokami} @@ -95,6 +95,8 @@ SELECT toValidUTF8('\x61\xF0\x80\x80\x80b') Повторяет строку определенное количество раз и объединяет повторяемые значения в одну строку. +Синоним: `REPEAT`. + **Синтаксис** ``` sql @@ -273,10 +275,14 @@ SELECT concat(key1, key2), sum(value) FROM key_val GROUP BY (key1, key2) Производит кодирование строки s в base64-представление. +Синоним: `TO_BASE64`. + ## base64Decode(s) {#base64decode} Декодирует base64-представление s в исходную строку. При невозможности декодирования выбрасывает исключение +Синоним: `FROM_BASE64`. + ## tryBase64Decode(s) {#trybase64decode} Функционал аналогичен base64Decode, но при невозможности декодирования возвращает пустую строку. @@ -597,4 +603,46 @@ Hello, "world"! 'foo' ``` + +## decodeXMLComponent {#decode-xml-component} + +Заменяет символами предопределенные мнемоники XML: `"` `&` `'` `>` `<` +Также эта функция заменяет числовые ссылки соответствующими символами юникод. Поддерживаются десятичная (например, `✓`) и шестнадцатеричная (`✓`) формы. + +**Синтаксис** + +``` sql +decodeXMLComponent(x) +``` + +**Параметры** + +- `x` — последовательность символов. [String](../../sql-reference/data-types/string.md). + +**Возвращаемое значение** + +- Строка с произведенными заменами. + +Тип: [String](../../sql-reference/data-types/string.md). + +**Пример** + +Запрос: + +``` sql +SELECT decodeXMLComponent(''foo''); +SELECT decodeXMLComponent('< Σ >'); +``` + +Результат: + +``` text +'foo' +< Σ > +``` + +**Смотрите также** + +- [Мнемоники в HTML](https://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%B5%D0%BC%D0%BE%D0%BD%D0%B8%D0%BA%D0%B8_%D0%B2_HTML) + [Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/functions/string_functions/) diff --git a/docs/ru/sql-reference/functions/string-replace-functions.md b/docs/ru/sql-reference/functions/string-replace-functions.md index f334d6804f9..f00a06d1560 100644 --- a/docs/ru/sql-reference/functions/string-replace-functions.md +++ b/docs/ru/sql-reference/functions/string-replace-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 42 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u043f\u043e\u0438\u0441\u043a\u0430\u0020\u0438\u0020\u0437\u0430\u043c\u0435\u043d\u044b\u0020\u0432\u0020\u0441\u0442\u0440\u043e\u043a\u0430\u0445" +toc_title: "Функции поиска и замены в строках" --- # Функции поиска и замены в строках {#funktsii-poiska-i-zameny-v-strokakh} diff --git a/docs/ru/sql-reference/functions/string-search-functions.md b/docs/ru/sql-reference/functions/string-search-functions.md index b7193da6f33..95ac922a4a8 100644 --- a/docs/ru/sql-reference/functions/string-search-functions.md +++ b/docs/ru/sql-reference/functions/string-search-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 41 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u043f\u043e\u0438\u0441\u043a\u0430\u0020\u0432\u0020\u0441\u0442\u0440\u043e\u043a\u0430\u0445" +toc_title: "Функции поиска в строках" --- # Функции поиска в строках {#funktsii-poiska-v-strokakh} diff --git a/docs/ru/sql-reference/functions/tuple-map-functions.md b/docs/ru/sql-reference/functions/tuple-map-functions.md index a2b25e68fe5..696fdb9e5ae 100644 --- a/docs/ru/sql-reference/functions/tuple-map-functions.md +++ b/docs/ru/sql-reference/functions/tuple-map-functions.md @@ -5,6 +5,66 @@ toc_title: Работа с контейнерами map # Функции для работы с контейнерами map {#functions-for-working-with-tuple-maps} +## map {#function-map} + +Преобразовывает пары `ключ:значение` в тип данных [Map(key, value)](../../sql-reference/data-types/map.md). + +**Синтаксис** + +``` sql +map(key1, value1[, key2, value2, ...]) +``` + +**Параметры** + +- `key` — ключ. [String](../../sql-reference/data-types/string.md) или [Integer](../../sql-reference/data-types/int-uint.md). +- `value` — значение. [String](../../sql-reference/data-types/string.md), [Integer](../../sql-reference/data-types/int-uint.md) или [Array](../../sql-reference/data-types/array.md). + +**Возвращаемое значение** + +- Структура данных в виде пар `ключ:значение`. + +Тип: [Map(key, value)](../../sql-reference/data-types/map.md). + +**Примеры** + +Запрос: + +``` sql +SELECT map('key1', number, 'key2', number * 2) FROM numbers(3); +``` + +Результат: + +``` text +┌─map('key1', number, 'key2', multiply(number, 2))─┐ +│ {'key1':0,'key2':0} │ +│ {'key1':1,'key2':2} │ +│ {'key1':2,'key2':4} │ +└──────────────────────────────────────────────────┘ +``` + +Запрос: + +``` sql +CREATE TABLE table_map (a Map(String, UInt64)) ENGINE = MergeTree() ORDER BY a; +INSERT INTO table_map SELECT map('key1', number, 'key2', number * 2) FROM numbers(3); +SELECT a['key2'] FROM table_map; +``` + +Результат: + +``` text +┌─arrayElement(a, 'key2')─┐ +│ 0 │ +│ 2 │ +│ 4 │ +└─────────────────────────┘ +``` + +**См. также** + +- тип данных [Map(key, value)](../../sql-reference/data-types/map.md) ## mapAdd {#function-mapadd} Собирает все ключи и суммирует соответствующие значения. @@ -116,4 +176,129 @@ select mapPopulateSeries([1,2,4], [11,22,44], 5) as res, toTypeName(res) as type └──────────────────────────────┴───────────────────────────────────┘ ``` -[Оригинальная статья](https://clickhouse.tech/docs/en/query_language/functions/tuple-map-functions/) +## mapContains {#mapcontains} + +Определяет, содержит ли контейнер `map` ключ `key`. + +**Синтаксис** + +``` sql +mapContains(map, key) +``` + +**Параметры** + +- `map` — контейнер Map. [Map](../../sql-reference/data-types/map.md). +- `key` — ключ. Тип соответстует типу ключей параметра `map`. + +**Возвращаемое значение** + +- `1` если `map` включает `key`, иначе `0`. + +Тип: [UInt8](../../sql-reference/data-types/int-uint.md). + +**Пример** + +Запрос: + +```sql +CREATE TABLE test (a Map(String,String)) ENGINE = Memory; + +INSERT INTO test VALUES ({'name':'eleven','age':'11'}), ({'number':'twelve','position':'6.0'}); + +SELECT mapContains(a, 'name') FROM test; + +``` + +Результат: + +```text +┌─mapContains(a, 'name')─┐ +│ 1 │ +│ 0 │ +└────────────────────────┘ +``` + +## mapKeys {#mapkeys} + +Возвращает все ключи контейнера `map`. + +**Синтаксис** + +```sql +mapKeys(map) +``` + +**Параметры** + +- `map` — контейнер Map. [Map](../../sql-reference/data-types/map.md). + +**Возвращаемое значение** + +- Массив со всеми ключами контейнера `map`. + +Тип: [Array](../../sql-reference/data-types/array.md). + +**Пример** + +Запрос: + +```sql +CREATE TABLE test (a Map(String,String)) ENGINE = Memory; + +INSERT INTO test VALUES ({'name':'eleven','age':'11'}), ({'number':'twelve','position':'6.0'}); + +SELECT mapKeys(a) FROM test; +``` + +Результат: + +```text +┌─mapKeys(a)────────────┐ +│ ['name','age'] │ +│ ['number','position'] │ +└───────────────────────┘ +``` + +## mapValues {#mapvalues} + +Возвращает все значения контейнера `map`. + +**Синтаксис** + +```sql +mapKeys(map) +``` + +**Параметры** + +- `map` — контейнер Map. [Map](../../sql-reference/data-types/map.md). + +**Возвращаемое значение** + +- Массив со всеми значениями контейнера `map`. + +Тип: [Array](../../sql-reference/data-types/array.md). + +**Примеры** + +Запрос: + +```sql +CREATE TABLE test (a Map(String,String)) ENGINE = Memory; + +INSERT INTO test VALUES ({'name':'eleven','age':'11'}), ({'number':'twelve','position':'6.0'}); + +SELECT mapValues(a) FROM test; +``` + +Результат: + +```text +┌─mapValues(a)─────┐ +│ ['eleven','11'] │ +│ ['twelve','6.0'] │ +└──────────────────┘ +``` + +[Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/functions/tuple-map-functions/) diff --git a/docs/ru/sql-reference/functions/type-conversion-functions.md b/docs/ru/sql-reference/functions/type-conversion-functions.md index 4a314bd22d8..f312f9f5847 100644 --- a/docs/ru/sql-reference/functions/type-conversion-functions.md +++ b/docs/ru/sql-reference/functions/type-conversion-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 38 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f\u0020\u0442\u0438\u043f\u043e\u0432" +toc_title: "Функции преобразования типов" --- # Функции преобразования типов {#funktsii-preobrazovaniia-tipov} @@ -36,10 +36,14 @@ toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u043f\u0440\u0435\u **Пример** +Запрос: + ``` sql -SELECT toInt64(nan), toInt32(32), toInt16('16'), toInt8(8.8) +SELECT toInt64(nan), toInt32(32), toInt16('16'), toInt8(8.8); ``` +Результат: + ``` text ┌─────────toInt64(nan)─┬─toInt32(32)─┬─toInt16('16')─┬─toInt8(8.8)─┐ │ -9223372036854775808 │ 32 │ 16 │ 8 │ @@ -52,10 +56,14 @@ SELECT toInt64(nan), toInt32(32), toInt16('16'), toInt8(8.8) **Пример** +Запрос: + ``` sql -select toInt64OrZero('123123'), toInt8OrZero('123qwe123') +SELECT toInt64OrZero('123123'), toInt8OrZero('123qwe123'); ``` +Результат: + ``` text ┌─toInt64OrZero('123123')─┬─toInt8OrZero('123qwe123')─┐ │ 123123 │ 0 │ @@ -68,10 +76,14 @@ select toInt64OrZero('123123'), toInt8OrZero('123qwe123') **Пример** +Запрос: + ``` sql -select toInt64OrNull('123123'), toInt8OrNull('123qwe123') +SELECT toInt64OrNull('123123'), toInt8OrNull('123qwe123'); ``` +Результат: + ``` text ┌─toInt64OrNull('123123')─┬─toInt8OrNull('123qwe123')─┐ │ 123123 │ ᴺᵁᴸᴸ │ @@ -102,10 +114,14 @@ select toInt64OrNull('123123'), toInt8OrNull('123qwe123') **Пример** +Запрос: + ``` sql -SELECT toUInt64(nan), toUInt32(-32), toUInt16('16'), toUInt8(8.8) +SELECT toUInt64(nan), toUInt32(-32), toUInt16('16'), toUInt8(8.8); ``` +Результат: + ``` text ┌───────toUInt64(nan)─┬─toUInt32(-32)─┬─toUInt16('16')─┬─toUInt8(8.8)─┐ │ 9223372036854775808 │ 4294967264 │ 16 │ 8 │ @@ -124,6 +140,8 @@ SELECT toUInt64(nan), toUInt32(-32), toUInt16('16'), toUInt8(8.8) ## toDate {#todate} +Cиноним: `DATE`. + ## toDateOrZero {#todateorzero} ## toDateOrNull {#todateornull} @@ -168,20 +186,28 @@ SELECT toUInt64(nan), toUInt32(-32), toUInt16('16'), toUInt8(8.8) **Примеры** +Запрос: + ``` sql -SELECT toDecimal32OrNull(toString(-1.111), 5) AS val, toTypeName(val) +SELECT toDecimal32OrNull(toString(-1.111), 5) AS val, toTypeName(val); ``` +Результат: + ``` text ┌──────val─┬─toTypeName(toDecimal32OrNull(toString(-1.111), 5))─┐ │ -1.11100 │ Nullable(Decimal(9, 5)) │ └──────────┴────────────────────────────────────────────────────┘ ``` +Запрос: + ``` sql -SELECT toDecimal32OrNull(toString(-1.111), 2) AS val, toTypeName(val) +SELECT toDecimal32OrNull(toString(-1.111), 2) AS val, toTypeName(val); ``` +Результат: + ``` text ┌──val─┬─toTypeName(toDecimal32OrNull(toString(-1.111), 2))─┐ │ ᴺᵁᴸᴸ │ Nullable(Decimal(9, 2)) │ @@ -213,20 +239,28 @@ SELECT toDecimal32OrNull(toString(-1.111), 2) AS val, toTypeName(val) **Пример** +Запрос: + ``` sql -SELECT toDecimal32OrZero(toString(-1.111), 5) AS val, toTypeName(val) +SELECT toDecimal32OrZero(toString(-1.111), 5) AS val, toTypeName(val); ``` +Результат: + ``` text ┌──────val─┬─toTypeName(toDecimal32OrZero(toString(-1.111), 5))─┐ │ -1.11100 │ Decimal(9, 5) │ └──────────┴────────────────────────────────────────────────────┘ ``` +Запрос: + ``` sql -SELECT toDecimal32OrZero(toString(-1.111), 2) AS val, toTypeName(val) +SELECT toDecimal32OrZero(toString(-1.111), 2) AS val, toTypeName(val); ``` +Результат: + ``` text ┌──val─┬─toTypeName(toDecimal32OrZero(toString(-1.111), 2))─┐ │ 0.00 │ Decimal(9, 2) │ @@ -258,12 +292,18 @@ YYYY-MM-DD hh:mm:ss Дополнительно, функция toString от аргумента типа DateTime может принимать второй аргумент String - имя тайм-зоны. Пример: `Asia/Yekaterinburg` В этом случае, форматирование времени производится согласно указанной тайм-зоне. +**Пример** + +Запрос: + ``` sql SELECT now() AS now_local, - toString(now(), 'Asia/Yekaterinburg') AS now_yekat + toString(now(), 'Asia/Yekaterinburg') AS now_yekat; ``` +Результат: + ``` text ┌───────────now_local─┬─now_yekat───────────┐ │ 2016-06-15 00:11:21 │ 2016-06-15 02:11:21 │ @@ -281,22 +321,30 @@ SELECT Принимает аргумент типа String или FixedString. Возвращает String, вырезая содержимое строки до первого найденного нулевого байта. -Пример: +**Примеры** + +Запрос: ``` sql -SELECT toFixedString('foo', 8) AS s, toStringCutToZero(s) AS s_cut +SELECT toFixedString('foo', 8) AS s, toStringCutToZero(s) AS s_cut; ``` +Результат: + ``` text ┌─s─────────────┬─s_cut─┐ │ foo\0\0\0\0\0 │ foo │ └───────────────┴───────┘ ``` +Запрос: + ``` sql -SELECT toFixedString('foo\0bar', 8) AS s, toStringCutToZero(s) AS s_cut +SELECT toFixedString('foo\0bar', 8) AS s, toStringCutToZero(s) AS s_cut; ``` +Результат: + ``` text ┌─s──────────┬─s_cut─┐ │ foo\0bar\0 │ foo │ @@ -344,7 +392,7 @@ reinterpretAsUUID(fixed_string) Запрос: ``` sql -SELECT reinterpretAsUUID(reverse(unhex('000102030405060708090a0b0c0d0e0f'))) +SELECT reinterpretAsUUID(reverse(unhex('000102030405060708090a0b0c0d0e0f'))); ``` Результат: @@ -377,10 +425,15 @@ SELECT uuid = uuid2; ## CAST(x, T) {#type_conversion_function-cast} -Преобразует x в тип данных t. -Поддерживается также синтаксис CAST(x AS t). +Преобразует входное значение `x` в указанный тип данных `T`. -Пример: +Поддерживается также синтаксис `CAST(x AS t)`. + +Обратите внимание, что если значение `x` не может быть преобразовано к типу `T`, возникает переполнение. Например, `CAST(-1, 'UInt8')` возвращает 255. + +**Пример** + +Запрос: ``` sql SELECT @@ -388,9 +441,11 @@ SELECT CAST(timestamp AS DateTime) AS datetime, CAST(timestamp AS Date) AS date, CAST(timestamp, 'String') AS string, - CAST(timestamp, 'FixedString(22)') AS fixed_string + CAST(timestamp, 'FixedString(22)') AS fixed_string; ``` +Результат: + ``` text ┌─timestamp───────────┬────────────datetime─┬───────date─┬─string──────────────┬─fixed_string──────────────┐ │ 2016-06-15 23:00:00 │ 2016-06-15 23:00:00 │ 2016-06-15 │ 2016-06-15 23:00:00 │ 2016-06-15 23:00:00\0\0\0 │ @@ -399,12 +454,18 @@ SELECT Преобразование в FixedString(N) работает только для аргументов типа String или FixedString(N). -Поддержано преобразование к типу [Nullable](../../sql-reference/functions/type-conversion-functions.md) и обратно. Пример: +Поддержано преобразование к типу [Nullable](../../sql-reference/functions/type-conversion-functions.md) и обратно. + +**Примеры** + +Запрос: ``` sql -SELECT toTypeName(x) FROM t_null +SELECT toTypeName(x) FROM t_null; ``` +Результат: + ``` text ┌─toTypeName(x)─┐ │ Int8 │ @@ -412,10 +473,14 @@ SELECT toTypeName(x) FROM t_null └───────────────┘ ``` +Запрос: + ``` sql -SELECT toTypeName(CAST(x, 'Nullable(UInt16)')) FROM t_null +SELECT toTypeName(CAST(x, 'Nullable(UInt16)')) FROM t_null; ``` +Результат: + ``` text ┌─toTypeName(CAST(x, 'Nullable(UInt16)'))─┐ │ Nullable(UInt16) │ @@ -427,6 +492,93 @@ SELECT toTypeName(CAST(x, 'Nullable(UInt16)')) FROM t_null - Настройка [cast_keep_nullable](../../operations/settings/settings.md#cast_keep_nullable) +## accurateCast(x, T) {#type_conversion_function-accurate-cast} + +Преобразует входное значение `x` в указанный тип данных `T`. + +В отличие от функции [cast(x, T)](#type_conversion_function-cast), `accurateCast` не допускает переполнения при преобразовании числовых типов. Например, `accurateCast(-1, 'UInt8')` вызовет исключение. + +**Примеры** + +Запрос: + +``` sql +SELECT cast(-1, 'UInt8') as uint8; +``` + +Результат: + +``` text +┌─uint8─┐ +│ 255 │ +└───── + +Запрос: + +```sql +SELECT accurateCast(-1, 'UInt8') as uint8; +``` + +Результат: + +``` text +Code: 70. DB::Exception: Received from localhost:9000. DB::Exception: Value in column Int8 cannot be safely converted into type UInt8: While processing accurateCast(-1, 'UInt8') AS uint8. +``` + +## accurateCastOrNull(x, T) {#type_conversion_function-accurate-cast_or_null} + +Преобразует входное значение `x` в указанный тип данных `T`. + +Всегда возвращает тип [Nullable](../../sql-reference/data-types/nullable.md). Если исходное значение не может быть преобразовано к целевому типу, возвращает [NULL](../../sql-reference/syntax.md#null-literal). + +**Синтаксис** + +```sql +accurateCastOrNull(x, T) +``` + +**Параметры** + +- `x` — входное значение. +- `T` — имя возвращаемого типа данных. + +**Возвращаемое значение** + +- Значение, преобразованное в указанный тип `T`. + +**Примеры** + +Запрос: + +``` sql +SELECT toTypeName(accurateCastOrNull(5, 'UInt8')); +``` + +Результат: + +``` text +┌─toTypeName(accurateCastOrNull(5, 'UInt8'))─┐ +│ Nullable(UInt8) │ +└────────────────────────────────────────────┘ +``` + +Запрос: + +``` sql +SELECT + accurateCastOrNull(-1, 'UInt8') as uint8, + accurateCastOrNull(128, 'Int8') as int8, + accurateCastOrNull('Test', 'FixedString(2)') as fixed_string; +``` + +Результат: + +``` text +┌─uint8─┬─int8─┬─fixed_string─┐ +│ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ +└───────┴──────┴──────────────┘ +``` + ## toInterval(Year\|Quarter\|Month\|Week\|Day\|Hour\|Minute\|Second) {#function-tointerval} Приводит аргумент из числового типа данных к типу данных [IntervalType](../../sql-reference/data-types/special-data-types/interval.md). @@ -454,6 +606,8 @@ toIntervalYear(number) **Пример** +Запрос: + ``` sql WITH toDate('2019-01-01') AS date, @@ -461,9 +615,11 @@ WITH toIntervalWeek(1) AS interval_to_week SELECT date + interval_week, - date + interval_to_week + date + interval_to_week; ``` +Результат: + ``` text ┌─plus(date, interval_week)─┬─plus(date, interval_to_week)─┐ │ 2019-01-08 │ 2019-01-08 │ @@ -479,7 +635,7 @@ SELECT **Синтаксис** ``` sql -parseDateTimeBestEffort(time_string[, time_zone]); +parseDateTimeBestEffort(time_string[, time_zone]) ``` **Параметры** @@ -522,7 +678,7 @@ AS parseDateTimeBestEffort; ``` sql SELECT parseDateTimeBestEffort('Sat, 18 Aug 2018 07:22:16 GMT', 'Europe/Moscow') -AS parseDateTimeBestEffort +AS parseDateTimeBestEffort; ``` Результат: @@ -537,7 +693,7 @@ AS parseDateTimeBestEffort ``` sql SELECT parseDateTimeBestEffort('1284101485') -AS parseDateTimeBestEffort +AS parseDateTimeBestEffort; ``` Результат: @@ -552,7 +708,7 @@ AS parseDateTimeBestEffort ``` sql SELECT parseDateTimeBestEffort('2018-12-12 10:12:12') -AS parseDateTimeBestEffort +AS parseDateTimeBestEffort; ``` Результат: @@ -566,7 +722,7 @@ AS parseDateTimeBestEffort Запрос: ``` sql -SELECT parseDateTimeBestEffort('10 20:19') +SELECT parseDateTimeBestEffort('10 20:19'); ``` Результат: @@ -591,7 +747,7 @@ SELECT parseDateTimeBestEffort('10 20:19') **Синтаксис** ``` sql -parseDateTimeBestEffortUS(time_string [, time_zone]); +parseDateTimeBestEffortUS(time_string [, time_zone]) ``` **Параметры** @@ -620,7 +776,7 @@ SELECT parseDateTimeBestEffortUS('09/12/2020 12:12:57') AS parseDateTimeBestEffortUS; ``` -Ответ: +Результат: ``` text ┌─parseDateTimeBestEffortUS─┐ @@ -635,7 +791,7 @@ SELECT parseDateTimeBestEffortUS('09-12-2020 12:12:57') AS parseDateTimeBestEffortUS; ``` -Ответ: +Результат: ``` text ┌─parseDateTimeBestEffortUS─┐ @@ -650,7 +806,7 @@ SELECT parseDateTimeBestEffortUS('09.12.2020 12:12:57') AS parseDateTimeBestEffortUS; ``` -Ответ: +Результат: ``` text ┌─parseDateTimeBestEffortUS─┐ @@ -658,6 +814,178 @@ AS parseDateTimeBestEffortUS; └─────────────────────────——┘ ``` +## parseDateTimeBestEffortUSOrNull {#parsedatetimebesteffortusornull} + +Работает аналогично функции [parseDateTimeBestEffortUS](#parsedatetimebesteffortUS), но в отличие от нее возвращает `NULL`, если входная строка не может быть преобразована в тип данных [DateTime](../../sql-reference/data-types/datetime.md). + +**Синтаксис** + +``` sql +parseDateTimeBestEffortUSOrNull(time_string[, time_zone]) +``` + +**Параметры** + +- `time_string` — строка, содержащая дату или дату со временем для преобразования. Дата должна быть в американском формате (`MM/DD/YYYY` и т.д.). [String](../../sql-reference/data-types/string.md). +- `time_zone` — [часовой пояс](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone). Функция анализирует `time_string` в соответствии с заданным часовым поясом. Опциональный параметр. [String](../../sql-reference/data-types/string.md). + +**Поддерживаемые нестандартные форматы** + +- Строка в формате [unix timestamp](https://en.wikipedia.org/wiki/Unix_time), содержащая 9-10 цифр. +- Строка, содержащая дату и время: `YYYYMMDDhhmmss`, `MM/DD/YYYY hh:mm:ss`, `MM-DD-YY hh:mm`, `YYYY-MM-DD hh:mm:ss` и т.д. +- Строка, содержащая дату без времени: `YYYY`, `YYYYMM`, `YYYY*MM`, `MM/DD/YYYY`, `MM-DD-YY` и т.д. +- Строка, содержащая день и время: `DD`, `DD hh`, `DD hh:mm`. В этом случае `YYYY-MM` заменяется на `2000-01`. +- Строка, содержащая дату и время, а также информацию о часовом поясе: `YYYY-MM-DD hh:mm:ss ±h:mm` и т.д. Например, `2020-12-12 17:36:00 -5:00`. + +**Возвращаемые значения** + +- `time_string`, преобразованная в тип данных `DateTime`. +- `NULL`, если входная строка не может быть преобразована в тип данных `DateTime`. + +**Примеры** + +Запрос: + +``` sql +SELECT parseDateTimeBestEffortUSOrNull('02/10/2021 21:12:57') AS parseDateTimeBestEffortUSOrNull; +``` + +Результат: + +``` text +┌─parseDateTimeBestEffortUSOrNull─┐ +│ 2021-02-10 21:12:57 │ +└─────────────────────────────────┘ +``` + +Запрос: + +``` sql +SELECT parseDateTimeBestEffortUSOrNull('02-10-2021 21:12:57 GMT', 'Europe/Moscow') AS parseDateTimeBestEffortUSOrNull; +``` + +Результат: + +``` text +┌─parseDateTimeBestEffortUSOrNull─┐ +│ 2021-02-11 00:12:57 │ +└─────────────────────────────────┘ +``` + +Запрос: + +``` sql +SELECT parseDateTimeBestEffortUSOrNull('02.10.2021') AS parseDateTimeBestEffortUSOrNull; +``` + +Результат: + +``` text +┌─parseDateTimeBestEffortUSOrNull─┐ +│ 2021-02-10 00:00:00 │ +└─────────────────────────────────┘ +``` + +Запрос: + +``` sql +SELECT parseDateTimeBestEffortUSOrNull('10.2021') AS parseDateTimeBestEffortUSOrNull; +``` + +Результат: + +``` text +┌─parseDateTimeBestEffortUSOrNull─┐ +│ ᴺᵁᴸᴸ │ +└─────────────────────────────────┘ +``` + +## parseDateTimeBestEffortUSOrZero {#parsedatetimebesteffortusorzero} + +Работает аналогично функции [parseDateTimeBestEffortUS](#parsedatetimebesteffortUS), но в отличие от нее возвращает нулевую дату (`1970-01-01`) или нулевую дату со временем (`1970-01-01 00:00:00`), если входная строка не может быть преобразована в тип данных [DateTime](../../sql-reference/data-types/datetime.md). + +**Синтаксис** + +``` sql +parseDateTimeBestEffortUSOrZero(time_string[, time_zone]) +``` + +**Параметры** + +- `time_string` — строка, содержащая дату или дату со временем для преобразования. Дата должна быть в американском формате (`MM/DD/YYYY` и т.д.). [String](../../sql-reference/data-types/string.md). +- `time_zone` — [часовой пояс](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-timezone). Функция анализирует `time_string` в соответствии с заданным часовым поясом. Опциональный параметр. [String](../../sql-reference/data-types/string.md). + +**Поддерживаемые нестандартные форматы** + +- Строка в формате [unix timestamp](https://en.wikipedia.org/wiki/Unix_time), содержащая 9-10 цифр. +- Строка, содержащая дату и время: `YYYYMMDDhhmmss`, `MM/DD/YYYY hh:mm:ss`, `MM-DD-YY hh:mm`, `YYYY-MM-DD hh:mm:ss` и т.д. +- Строка, содержащая дату без времени: `YYYY`, `YYYYMM`, `YYYY*MM`, `MM/DD/YYYY`, `MM-DD-YY` и т.д. +- Строка, содержащая день и время: `DD`, `DD hh`, `DD hh:mm`. В этом случае `YYYY-MM` заменяется на `2000-01`. +- Строка, содержащая дату и время, а также информацию о часовом поясе: `YYYY-MM-DD hh:mm:ss ±h:mm` и т.д. Например, `2020-12-12 17:36:00 -5:00`. + +**Возвращаемые значения** + +- `time_string`, преобразованная в тип данных `DateTime`. +- Нулевая дата или нулевая дата со временем, если входная строка не может быть преобразована в тип данных `DateTime`. + +**Примеры** + +Запрос: + +``` sql +SELECT parseDateTimeBestEffortUSOrZero('02/10/2021 21:12:57') AS parseDateTimeBestEffortUSOrZero; +``` + +Результат: + +``` text +┌─parseDateTimeBestEffortUSOrZero─┐ +│ 2021-02-10 21:12:57 │ +└─────────────────────────────────┘ +``` + +Запрос: + +``` sql +SELECT parseDateTimeBestEffortUSOrZero('02-10-2021 21:12:57 GMT', 'Europe/Moscow') AS parseDateTimeBestEffortUSOrZero; +``` + +Результат: + +``` text +┌─parseDateTimeBestEffortUSOrZero─┐ +│ 2021-02-11 00:12:57 │ +└─────────────────────────────────┘ +``` + +Запрос: + +``` sql +SELECT parseDateTimeBestEffortUSOrZero('02.10.2021') AS parseDateTimeBestEffortUSOrZero; +``` + +Результат: + +``` text +┌─parseDateTimeBestEffortUSOrZero─┐ +│ 2021-02-10 00:00:00 │ +└─────────────────────────────────┘ +``` + +Запрос: + +``` sql +SELECT parseDateTimeBestEffortUSOrZero('02.2021') AS parseDateTimeBestEffortUSOrZero; +``` + +Результат: + +``` text +┌─parseDateTimeBestEffortUSOrZero─┐ +│ 1970-01-01 00:00:00 │ +└─────────────────────────────────┘ +``` + ## toUnixTimestamp64Milli ## toUnixTimestamp64Micro ## toUnixTimestamp64Nano @@ -685,10 +1013,10 @@ toUnixTimestamp64Milli(value) ``` sql WITH toDateTime64('2019-09-16 19:20:12.345678910', 6) AS dt64 -SELECT toUnixTimestamp64Milli(dt64) +SELECT toUnixTimestamp64Milli(dt64); ``` -Ответ: +Результат: ``` text ┌─toUnixTimestamp64Milli(dt64)─┐ @@ -700,10 +1028,10 @@ SELECT toUnixTimestamp64Milli(dt64) ``` sql WITH toDateTime64('2019-09-16 19:20:12.345678910', 6) AS dt64 -SELECT toUnixTimestamp64Nano(dt64) +SELECT toUnixTimestamp64Nano(dt64); ``` -Ответ: +Результат: ``` text ┌─toUnixTimestamp64Nano(dt64)─┐ @@ -738,10 +1066,10 @@ fromUnixTimestamp64Milli(value [, ti]) ``` sql WITH CAST(1234567891011, 'Int64') AS i64 -SELECT fromUnixTimestamp64Milli(i64, 'UTC') +SELECT fromUnixTimestamp64Milli(i64, 'UTC'); ``` -Ответ: +Результат: ``` text ┌─fromUnixTimestamp64Milli(i64, 'UTC')─┐ @@ -772,12 +1100,12 @@ toLowCardinality(expr) Тип: `LowCardinality(expr_result_type)` -**Example** +**Пример** Запрос: ```sql -SELECT toLowCardinality('1') +SELECT toLowCardinality('1'); ``` Результат: @@ -813,10 +1141,10 @@ formatRow(format, x, y, ...) ``` sql SELECT formatRow('CSV', number, 'good') -FROM numbers(3) +FROM numbers(3); ``` -Ответ: +Результат: ``` text ┌─formatRow('CSV', number, 'good')─┐ @@ -854,10 +1182,10 @@ formatRowNoNewline(format, x, y, ...) ``` sql SELECT formatRowNoNewline('CSV', number, 'good') -FROM numbers(3) +FROM numbers(3); ``` -Ответ: +Результат: ``` text ┌─formatRowNoNewline('CSV', number, 'good')─┐ diff --git a/docs/ru/sql-reference/functions/url-functions.md b/docs/ru/sql-reference/functions/url-functions.md index 1008e2a359c..83f7fd32f6c 100644 --- a/docs/ru/sql-reference/functions/url-functions.md +++ b/docs/ru/sql-reference/functions/url-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 54 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u0020\u0055\u0052\u004c" +toc_title: "Функции для работы с URL" --- # Функции для работы с URL {#funktsii-dlia-raboty-s-url} @@ -115,6 +115,168 @@ SELECT topLevelDomain('svn+ssh://www.some.svn-hosting.com:80/repo/trunk') Например, `cutToFirstSignificantSubdomain('https://news.yandex.com.tr/') = 'yandex.com.tr'`. +### cutToFirstSignificantSubdomainCustom {#cuttofirstsignificantsubdomaincustom} + +Возвращает часть домена, включающую поддомены верхнего уровня до первого существенного поддомена. Принимает имя пользовательского [списка доменов верхнего уровня](https://ru.wikipedia.org/wiki/Список_доменов_верхнего_уровня). + +Полезно, если требуется актуальный список доменов верхнего уровня или если есть пользовательский. + +Пример конфигурации: + +```xml + + + + public_suffix_list.dat + + +``` + +**Синтаксис** + +``` sql +cutToFirstSignificantSubdomain(URL, TLD) +``` + +**Parameters** + +- `URL` — URL. [String](../../sql-reference/data-types/string.md). +- `TLD` — имя пользовательского списка доменов верхнего уровня. [String](../../sql-reference/data-types/string.md). + +**Возвращаемое значение** + +- Часть домена, включающая поддомены верхнего уровня до первого существенного поддомена. + +Тип: [String](../../sql-reference/data-types/string.md). + +**Пример** + +Запрос: + +```sql +SELECT cutToFirstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list'); +``` + +Результат: + +```text +┌─cutToFirstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list')─┐ +│ foo.there-is-no-such-domain │ +└───────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +**Смотрите также** + +- [firstSignificantSubdomain](#firstsignificantsubdomain). + +### cutToFirstSignificantSubdomainCustomWithWWW {#cuttofirstsignificantsubdomaincustomwithwww} + +Возвращает часть домена, включающую поддомены верхнего уровня до первого существенного поддомена, не опуская "www". Принимает имя пользовательского списка доменов верхнего уровня. + +Полезно, если требуется актуальный список доменов верхнего уровня или если есть пользовательский. + +Пример конфигурации: + +```xml + + + + public_suffix_list.dat + + +``` + +**Синтаксис** + +```sql +cutToFirstSignificantSubdomainCustomWithWWW(URL, TLD) +``` + +**Параметры** + +- `URL` — URL. [String](../../sql-reference/data-types/string.md). +- `TLD` — имя пользовательского списка доменов верхнего уровня. [String](../../sql-reference/data-types/string.md). + +**Возвращаемое значение** + +- Часть домена, включающая поддомены верхнего уровня до первого существенного поддомена, без удаления `www`. + +Тип: [String](../../sql-reference/data-types/string.md). + +**Пример** + +Запрос: + +```sql +SELECT cutToFirstSignificantSubdomainCustomWithWWW('www.foo', 'public_suffix_list'); +``` + +Результат: + +```text +┌─cutToFirstSignificantSubdomainCustomWithWWW('www.foo', 'public_suffix_list')─┐ +│ www.foo │ +└──────────────────────────────────────────────────────────────────────────────┘ +``` + +**Смотрите также** + +- [firstSignificantSubdomain](#firstsignificantsubdomain). + +### firstSignificantSubdomainCustom {#firstsignificantsubdomaincustom} + +Возвращает первый существенный поддомен. Принимает имя пользовательского списка доменов верхнего уровня. + +Полезно, если требуется актуальный список доменов верхнего уровня или если есть пользовательский. + +Пример конфигурации: + +```xml + + + + public_suffix_list.dat + + +``` + +**Синтаксис** + +```sql +firstSignificantSubdomainCustom(URL, TLD) +``` + +**Параметры** + +- `URL` — URL. [String](../../sql-reference/data-types/string.md). +- `TLD` — имя пользовательского списка доменов верхнего уровня. [String](../../sql-reference/data-types/string.md). + +**Возвращаемое значение** + +- Первый существенный поддомен. + +Тип: [String](../../sql-reference/data-types/string.md). + +**Пример** + +Запрос: + +```sql +SELECT firstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list'); +``` + +Результат: + +```text +┌─firstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list')─┐ +│ foo │ +└──────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +**Смотрите также** + +- [firstSignificantSubdomain](#firstsignificantsubdomain). + ### port(URL[, default_port = 0]) {#port} Возвращает порт или значение `default_port`, если в URL-адресе нет порта (или передан невалидный URL) diff --git a/docs/ru/sql-reference/functions/uuid-functions.md b/docs/ru/sql-reference/functions/uuid-functions.md index 6082fcaa712..f0017adbc8b 100644 --- a/docs/ru/sql-reference/functions/uuid-functions.md +++ b/docs/ru/sql-reference/functions/uuid-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 53 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u0020\u0055\u0055\u0049\u0044" +toc_title: "Функции для работы с UUID" --- # Функции для работы с UUID {#funktsii-dlia-raboty-s-uuid} diff --git a/docs/ru/sql-reference/functions/ym-dict-functions.md b/docs/ru/sql-reference/functions/ym-dict-functions.md index c3b04e4ab66..f6d02e553a0 100644 --- a/docs/ru/sql-reference/functions/ym-dict-functions.md +++ b/docs/ru/sql-reference/functions/ym-dict-functions.md @@ -1,6 +1,6 @@ --- toc_priority: 59 -toc_title: "\u0424\u0443\u043d\u043a\u0446\u0438\u0438\u0020\u0434\u043b\u044f\u0020\u0440\u0430\u0431\u043e\u0442\u044b\u0020\u0441\u043e\u0020\u0441\u043b\u043e\u0432\u0430\u0440\u044f\u043c\u0438\u0020\u042f\u043d\u0434\u0435\u043a\u0441\u002e\u041c\u0435\u0442\u0440\u0438\u043a\u0438" +toc_title: "Функции для работы со словарями Яндекс.Метрики" --- # Функции для работы со словарями Яндекс.Метрики {#ym-dict-functions} diff --git a/docs/ru/sql-reference/index.md b/docs/ru/sql-reference/index.md index f59232ee047..7aea530c7ee 100644 --- a/docs/ru/sql-reference/index.md +++ b/docs/ru/sql-reference/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0421\u043F\u0440\u0430\u0432\u043A\u0430 \u043F\u043E SQL" +toc_folder_title: "Справка по SQL" toc_hidden: true toc_priority: 28 toc_title: hidden diff --git a/docs/ru/sql-reference/operators/in.md b/docs/ru/sql-reference/operators/in.md index 4c1290df166..e0412747898 100644 --- a/docs/ru/sql-reference/operators/in.md +++ b/docs/ru/sql-reference/operators/in.md @@ -13,10 +13,28 @@ SELECT (CounterID, UserID) IN ((34, 123), (101500, 456)) FROM ... Если слева стоит один столбец, входящий в индекс, а справа - множество констант, то при выполнении запроса, система воспользуется индексом. -Не перечисляйте слишком большое количество значений (миллионы) явно. Если множество большое - лучше загрузить его во временную таблицу (например, смотрите раздел «Внешние данные для обработки запроса»), и затем воспользоваться подзапросом. +Не перечисляйте слишком большое количество значений (миллионы) явно. Если множество большое - лучше загрузить его во временную таблицу (например, смотрите раздел [Внешние данные для обработки запроса](../../engines/table-engines/special/external-data.md)), и затем воспользоваться подзапросом. В качестве правой части оператора может быть множество константных выражений, множество кортежей с константными выражениями (показано в примерах выше), а также имя таблицы или подзапрос SELECT в скобках. +Если типы данных в левой и правой частях подзапроса `IN` различаются, ClickHouse преобразует значение в левой части к типу данных из правой части. Преобразование выполняется по аналогии с функцией [accurateCastOrNull](../functions/type-conversion-functions.md#type_conversion_function-accurate-cast_or_null), т.е. тип данных становится [Nullable](../../sql-reference/data-types/nullable.md), а если преобразование не может быть выполнено, возвращается значение [NULL](../../sql-reference/syntax.md#null-literal). + +**Пример** + +Запрос: + +``` sql +SELECT '1' IN (SELECT 1); +``` + +Результат: + +``` text +┌─in('1', _subquery49)─┐ +│ 1 │ +└──────────────────────┘ +``` + Если в качестве правой части оператора указано имя таблицы (например, `UserID IN users`), то это эквивалентно подзапросу `UserID IN (SELECT * FROM users)`. Это используется при работе с внешними данными, отправляемым вместе с запросом. Например, вместе с запросом может быть отправлено множество идентификаторов посетителей, загруженное во временную таблицу users, по которому следует выполнить фильтрацию. Если в качестве правой части оператора, указано имя таблицы, имеющий движок Set (подготовленное множество, постоянно находящееся в оперативке), то множество не будет создаваться заново при каждом запросе. diff --git a/docs/ru/sql-reference/operators/index.md b/docs/ru/sql-reference/operators/index.md index 1eddfc4dcaf..691c398ce4c 100644 --- a/docs/ru/sql-reference/operators/index.md +++ b/docs/ru/sql-reference/operators/index.md @@ -1,6 +1,6 @@ --- toc_priority: 38 -toc_title: "\u041e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b" +toc_title: "Операторы" --- # Операторы {#operatory} diff --git a/docs/ru/sql-reference/statements/alter/column.md b/docs/ru/sql-reference/statements/alter/column.md index 7a394e2f684..35a1952d842 100644 --- a/docs/ru/sql-reference/statements/alter/column.md +++ b/docs/ru/sql-reference/statements/alter/column.md @@ -1,6 +1,6 @@ --- toc_priority: 37 -toc_title: "\u041c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0438\u0020\u0441\u043e\u0020\u0441\u0442\u043e\u043b\u0431\u0446\u0430\u043c\u0438" +toc_title: "Манипуляции со столбцами" --- # Манипуляции со столбцами {#manipuliatsii-so-stolbtsami} diff --git a/docs/ru/sql-reference/statements/alter/constraint.md b/docs/ru/sql-reference/statements/alter/constraint.md index e26db208493..13396f33621 100644 --- a/docs/ru/sql-reference/statements/alter/constraint.md +++ b/docs/ru/sql-reference/statements/alter/constraint.md @@ -1,6 +1,6 @@ --- toc_priority: 43 -toc_title: "\u041c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0438\u0020\u0441\u0020\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u043c\u0438" +toc_title: "Манипуляции с ограничениями" --- # Манипуляции с ограничениями (constraints) {#manipuliatsii-s-ogranicheniiami-constraints} diff --git a/docs/ru/sql-reference/statements/alter/index/index.md b/docs/ru/sql-reference/statements/alter/index/index.md index 2cadbbe065e..a42bccd7b47 100644 --- a/docs/ru/sql-reference/statements/alter/index/index.md +++ b/docs/ru/sql-reference/statements/alter/index/index.md @@ -1,7 +1,7 @@ --- toc_hidden_folder: true toc_priority: 42 -toc_title: "\u041c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0438\u0020\u0441\u0020\u0438\u043d\u0434\u0435\u043a\u0441\u0430\u043c\u0438" +toc_title: "Манипуляции с индексами" --- # Манипуляции с индексами {#manipuliatsii-s-indeksami} diff --git a/docs/ru/sql-reference/statements/create/database.md b/docs/ru/sql-reference/statements/create/database.md index e6c561f8e0b..0e880517134 100644 --- a/docs/ru/sql-reference/statements/create/database.md +++ b/docs/ru/sql-reference/statements/create/database.md @@ -1,6 +1,6 @@ --- toc_priority: 35 -toc_title: "\u0411\u0430\u0437\u0430\u0020\u0434\u0430\u043d\u043d\u044b\u0445" +toc_title: "База данных" --- # CREATE DATABASE {#query-language-create-database} diff --git a/docs/ru/sql-reference/statements/create/dictionary.md b/docs/ru/sql-reference/statements/create/dictionary.md index 3134a89483b..dba2aa61ca1 100644 --- a/docs/ru/sql-reference/statements/create/dictionary.md +++ b/docs/ru/sql-reference/statements/create/dictionary.md @@ -1,6 +1,6 @@ --- toc_priority: 38 -toc_title: "\u0421\u043b\u043e\u0432\u0430\u0440\u044c" +toc_title: "Словарь" --- # CREATE DICTIONARY {#create-dictionary-query} diff --git a/docs/ru/sql-reference/statements/create/index.md b/docs/ru/sql-reference/statements/create/index.md index 28ddce2afe3..70961e4f404 100644 --- a/docs/ru/sql-reference/statements/create/index.md +++ b/docs/ru/sql-reference/statements/create/index.md @@ -1,7 +1,7 @@ --- toc_folder_title: CREATE toc_priority: 34 -toc_title: "\u041e\u0431\u0437\u043e\u0440" +toc_title: "Обзор" --- # Запросы CREATE {#create-queries} diff --git a/docs/ru/sql-reference/statements/create/quota.md b/docs/ru/sql-reference/statements/create/quota.md index 65762071ea2..f5ac0df010e 100644 --- a/docs/ru/sql-reference/statements/create/quota.md +++ b/docs/ru/sql-reference/statements/create/quota.md @@ -1,6 +1,6 @@ --- toc_priority: 42 -toc_title: "\u041a\u0432\u043e\u0442\u0430" +toc_title: "Квота" --- # CREATE QUOTA {#create-quota-statement} diff --git a/docs/ru/sql-reference/statements/create/role.md b/docs/ru/sql-reference/statements/create/role.md index 521117c0e89..8592f263156 100644 --- a/docs/ru/sql-reference/statements/create/role.md +++ b/docs/ru/sql-reference/statements/create/role.md @@ -1,6 +1,6 @@ --- toc_priority: 40 -toc_title: "\u0420\u043e\u043b\u044c" +toc_title: "Роль" --- # CREATE ROLE {#create-role-statement} diff --git a/docs/ru/sql-reference/statements/create/row-policy.md b/docs/ru/sql-reference/statements/create/row-policy.md index e79a19d4cbe..75f6fdfd2e1 100644 --- a/docs/ru/sql-reference/statements/create/row-policy.md +++ b/docs/ru/sql-reference/statements/create/row-policy.md @@ -1,6 +1,6 @@ --- toc_priority: 41 -toc_title: "\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430\u0020\u0434\u043e\u0441\u0442\u0443\u043f\u0430" +toc_title: "Политика доступа" --- # CREATE ROW POLICY {#create-row-policy-statement} diff --git a/docs/ru/sql-reference/statements/create/settings-profile.md b/docs/ru/sql-reference/statements/create/settings-profile.md index 643f9d92eac..5838ddc9153 100644 --- a/docs/ru/sql-reference/statements/create/settings-profile.md +++ b/docs/ru/sql-reference/statements/create/settings-profile.md @@ -1,6 +1,6 @@ --- toc_priority: 43 -toc_title: "\u041f\u0440\u043e\u0444\u0438\u043b\u044c\u0020\u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a" +toc_title: "Профиль настроек" --- # CREATE SETTINGS PROFILE {#create-settings-profile-statement} diff --git a/docs/ru/sql-reference/statements/create/table.md b/docs/ru/sql-reference/statements/create/table.md index 9f582042a36..8e2c471e548 100644 --- a/docs/ru/sql-reference/statements/create/table.md +++ b/docs/ru/sql-reference/statements/create/table.md @@ -1,6 +1,6 @@ --- toc_priority: 36 -toc_title: "\u0422\u0430\u0431\u043b\u0438\u0446\u0430" +toc_title: "Таблица" --- # CREATE TABLE {#create-table-query} diff --git a/docs/ru/sql-reference/statements/create/user.md b/docs/ru/sql-reference/statements/create/user.md index bcc9768eb43..ac9547691e6 100644 --- a/docs/ru/sql-reference/statements/create/user.md +++ b/docs/ru/sql-reference/statements/create/user.md @@ -1,6 +1,6 @@ --- toc_priority: 39 -toc_title: "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c" +toc_title: "Пользователь" --- # CREATE USER {#create-user-statement} diff --git a/docs/ru/sql-reference/statements/create/view.md b/docs/ru/sql-reference/statements/create/view.md index f4b91b5ae17..da021059a8e 100644 --- a/docs/ru/sql-reference/statements/create/view.md +++ b/docs/ru/sql-reference/statements/create/view.md @@ -1,6 +1,6 @@ --- toc_priority: 37 -toc_title: "\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435" +toc_title: "Представление" --- # CREATE VIEW {#create-view} diff --git a/docs/ru/sql-reference/statements/index.md b/docs/ru/sql-reference/statements/index.md index c7862015e64..5e72aa7cca0 100644 --- a/docs/ru/sql-reference/statements/index.md +++ b/docs/ru/sql-reference/statements/index.md @@ -1,5 +1,5 @@ --- -toc_folder_title: "\u0412\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u044F" +toc_folder_title: "Выражения" toc_priority: 31 --- diff --git a/docs/ru/sql-reference/statements/optimize.md b/docs/ru/sql-reference/statements/optimize.md index 9b94c31a8f7..8b1d72fed80 100644 --- a/docs/ru/sql-reference/statements/optimize.md +++ b/docs/ru/sql-reference/statements/optimize.md @@ -15,11 +15,10 @@ OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION I - Если `OPTIMIZE` не выполняет мёрж по любой причине, ClickHouse не оповещает об этом клиента. Чтобы включить оповещения, используйте настройку [optimize_throw_if_noop](../../operations/settings/settings.md#setting-optimize_throw_if_noop). - Если указать `PARTITION`, то оптимизация выполняется только для указанной партиции. [Как задавать имя партиции в запросах](alter/index.md#alter-how-to-specify-part-expr). -- Если указать `FINAL`, то оптимизация выполняется даже в том случае, если все данные уже лежат в одном куске. +- Если указать `FINAL`, то оптимизация выполняется даже в том случае, если все данные уже лежат в одном куске. Кроме того, слияние является принудительным, даже если выполняются параллельные слияния. - Если указать `DEDUPLICATE`, то произойдет схлопывание полностью одинаковых строк (сравниваются значения во всех колонках), имеет смысл только для движка MergeTree. !!! warning "Внимание" Запрос `OPTIMIZE` не может устранить причину появления ошибки «Too many parts». - -[Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/statements/optimize/) \ No newline at end of file +[Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/statements/optimize/) diff --git a/docs/ru/sql-reference/statements/select/all.md b/docs/ru/sql-reference/statements/select/all.md new file mode 100644 index 00000000000..4049d77a173 --- /dev/null +++ b/docs/ru/sql-reference/statements/select/all.md @@ -0,0 +1,22 @@ +--- +toc_title: ALL +--- + +# Секция ALL {#select-all} + +Если в таблице несколько совпадающих строк, то `ALL` возвращает все из них. Поведение запроса `SELECT ALL` точно такое же, как и `SELECT` без аргумента `DISTINCT`. Если указаны оба аргумента: `ALL` и `DISTINCT`, функция вернет исключение. + + +`ALL` может быть указан внутри агрегатной функции, например, результат выполнения запроса: + +```sql +SELECT sum(ALL number) FROM numbers(10); +``` + +равен результату выполнения запроса: + +```sql +SELECT sum(number) FROM numbers(10); +``` + +[Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/statements/select/all) diff --git a/docs/ru/sql-reference/statements/select/index.md b/docs/ru/sql-reference/statements/select/index.md index b0b6e80d7be..a548a988a89 100644 --- a/docs/ru/sql-reference/statements/select/index.md +++ b/docs/ru/sql-reference/statements/select/index.md @@ -1,8 +1,8 @@ --- -title: "\u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0020\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\u0020\u0053\u0045\u004c\u0045\u0043\u0054" +title: "Синтаксис запросов SELECT" toc_folder_title: SELECT toc_priority: 32 -toc_title: "\u041e\u0431\u0437\u043e\u0440" +toc_title: "Обзор" --- # Синтаксис запросов SELECT {#select-queries-syntax} diff --git a/docs/ru/sql-reference/statements/select/join.md b/docs/ru/sql-reference/statements/select/join.md index c5548d74156..4bd883c87ff 100644 --- a/docs/ru/sql-reference/statements/select/join.md +++ b/docs/ru/sql-reference/statements/select/join.md @@ -102,7 +102,7 @@ USING (equi_column1, ... equi_columnN, asof_column) - При использовании обычного `JOIN` , запрос отправляется на удалённые серверы. На каждом из них выполняются подзапросы для формирования «правой» таблицы, и с этой таблицей выполняется соединение. То есть, «правая» таблица формируется на каждом сервере отдельно. - При использовании `GLOBAL ... JOIN`, сначала сервер-инициатор запроса запускает подзапрос для вычисления правой таблицы. Эта временная таблица передаётся на каждый удалённый сервер, и на них выполняются запросы с использованием переданных временных данных. -Будьте аккуратны при использовании `GLOBAL`. За дополнительной информацией обращайтесь в раздел [Распределенные подзапросы](#select-distributed-subqueries). +Будьте аккуратны при использовании `GLOBAL`. За дополнительной информацией обращайтесь в раздел [Распределенные подзапросы](../../../sql-reference/operators/in.md#select-distributed-subqueries). ## Рекомендации по использованию {#usage-recommendations} diff --git a/docs/ru/sql-reference/statements/show.md b/docs/ru/sql-reference/statements/show.md index 56528f28c65..b214f0072e3 100644 --- a/docs/ru/sql-reference/statements/show.md +++ b/docs/ru/sql-reference/statements/show.md @@ -362,4 +362,69 @@ SHOW [CURRENT] QUOTA SHOW ACCESS ``` -[Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/show/) +## SHOW SETTINGS {#show-settings} + +Возвращает список системных настроек и их значений. Использует данные из таблицы [system.settings](../../operations/system-tables/settings.md). + +**Синтаксис** + +```sql +SHOW [CHANGED] SETTINGS LIKE|ILIKE +``` + +**Секции** + +При использовании `LIKE|ILIKE` можно задавать шаблон для имени настройки. Этот шаблон может содержать символы подстановки, такие как `%` или `_`. При использовании `LIKE` шаблон чувствителен к регистру, а при использовании `ILIKE` — не чувствителен. + +Если используется `CHANGED`, запрос вернет только те настройки, значения которых были изменены, т.е. отличны от значений по умолчанию. + +**Примеры** + +Запрос с использованием `LIKE`: + +```sql +SHOW SETTINGS LIKE 'send_timeout'; +``` +Результат: + +```text +┌─name─────────┬─type────┬─value─┐ +│ send_timeout │ Seconds │ 300 │ +└──────────────┴─────────┴───────┘ +``` + +Запрос с использованием `ILIKE`: + +```sql +SHOW SETTINGS ILIKE '%CONNECT_timeout%' +``` + +Результат: + +```text +┌─name────────────────────────────────────┬─type─────────┬─value─┐ +│ connect_timeout │ Seconds │ 10 │ +│ connect_timeout_with_failover_ms │ Milliseconds │ 50 │ +│ connect_timeout_with_failover_secure_ms │ Milliseconds │ 100 │ +└─────────────────────────────────────────┴──────────────┴───────┘ +``` + +Запрос с использованием `CHANGED`: + +```sql +SHOW CHANGED SETTINGS ILIKE '%MEMORY%' +``` + +Результат: + +```text +┌─name─────────────┬─type───┬─value───────┐ +│ max_memory_usage │ UInt64 │ 10000000000 │ +└──────────────────┴────────┴─────────────┘ +``` + +**См. также** + +- Таблица [system.settings](../../operations/system-tables/settings.md) + +[Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/statements/show/) diff --git a/docs/ru/sql-reference/syntax.md b/docs/ru/sql-reference/syntax.md index ca73d3a137e..d8eaa4f1731 100644 --- a/docs/ru/sql-reference/syntax.md +++ b/docs/ru/sql-reference/syntax.md @@ -1,6 +1,6 @@ --- toc_priority: 31 -toc_title: "\u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441" +toc_title: "Синтаксис" --- # Синтаксис {#sintaksis} diff --git a/docs/ru/sql-reference/table-functions/file.md b/docs/ru/sql-reference/table-functions/file.md index d3e6e106125..f9bdf902ad8 100644 --- a/docs/ru/sql-reference/table-functions/file.md +++ b/docs/ru/sql-reference/table-functions/file.md @@ -5,23 +5,27 @@ toc_title: file # file {#file} -Создаёт таблицу из файла. Данная табличная функция похожа на табличные функции [file](file.md) и [hdfs](hdfs.md). +Создаёт таблицу из файла. Данная табличная функция похожа на табличные функции [url](../../sql-reference/table-functions/url.md) и [hdfs](../../sql-reference/table-functions/hdfs.md). + +Функция `file` может использоваться в запросах `SELECT` и `INSERT` при работе с движком таблиц [File](../../engines/table-engines/special/file.md). + +**Синтаксис** ``` sql file(path, format, structure) ``` -**Входные параметры** +**Параметры** -- `path` — относительный путь до файла от [user_files_path](../../sql-reference/table-functions/file.md#server_configuration_parameters-user_files_path). Путь к файлу поддерживает следующие шаблоны в режиме доступа только для чтения `*`, `?`, `{abc,def}` и `{N..M}`, где `N`, `M` — числа, \``'abc', 'def'` — строки. +- `path` — относительный путь до файла от [user_files_path](../../sql-reference/table-functions/file.md#server_configuration_parameters-user_files_path). Путь к файлу поддерживает следующие шаблоны в режиме доступа только для чтения `*`, `?`, `{abc,def}` и `{N..M}`, где `N`, `M` — числа, `'abc', 'def'` — строки. - `format` — [формат](../../interfaces/formats.md#formats) файла. -- `structure` — структура таблицы. Формат `'colunmn1_name column1_ype, column2_name column2_type, ...'`. +- `structure` — структура таблицы. Формат: `'colunmn1_name column1_ype, column2_name column2_type, ...'`. **Возвращаемое значение** Таблица с указанной структурой, предназначенная для чтения или записи данных в указанном файле. -**Пример** +**Примеры** Настройка `user_files_path` и содержимое файла `test.csv`: @@ -35,12 +39,10 @@ $ cat /var/lib/clickhouse/user_files/test.csv 78,43,45 ``` -Таблица из `test.csv` и выборка первых двух строк из неё: +Получение данных из таблицы в файле `test.csv` и выборка первых двух строк из неё: ``` sql -SELECT * -FROM file('test.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32') -LIMIT 2 +SELECT * FROM file('test.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32') LIMIT 2; ``` ``` text @@ -50,45 +52,61 @@ LIMIT 2 └─────────┴─────────┴─────────┘ ``` -Шаблоны могут содержаться в нескольких компонентах пути. Обрабатываются только существующие файлы, название которых целиком удовлетворяет шаблону (не только суффиксом или префиксом). +Получение первых 10 строк таблицы, содержащей 3 столбца типа [UInt32](../../sql-reference/data-types/int-uint.md), из CSV-файла: -- `*` — Заменяет любое количество любых символов кроме `/`, включая отсутствие символов. -- `?` — Заменяет ровно один любой символ. -- `{some_string,another_string,yet_another_one}` — Заменяет любую из строк `'some_string', 'another_string', 'yet_another_one'`. -- `{N..M}` — Заменяет любое число в интервале от `N` до `M` включительно (может содержать ведущие нули). +``` sql +SELECT * FROM file('test.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32') LIMIT 10; +``` + +Вставка данных из файла в таблицу: + +``` sql +INSERT INTO FUNCTION file('test.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32') VALUES (1, 2, 3), (3, 2, 1); +SELECT * FROM file('test.csv', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32'); +``` + +``` text +┌─column1─┬─column2─┬─column3─┐ +│ 1 │ 2 │ 3 │ +│ 3 │ 2 │ 1 │ +└─────────┴─────────┴─────────┘ +``` + +## Шаблоны поиска в компонентах пути {#globs-in-path} + +При описании пути к файлу могут использоваться шаблоны поиска. Обрабатываются только те файлы, у которых путь и название соответствуют шаблону полностью (а не только префикс или суффикс). + +- `*` — заменяет любое количество любых символов кроме `/`, включая отсутствие символов. +- `?` — заменяет ровно один любой символ. +- `{some_string,another_string,yet_another_one}` — заменяет любую из строк `'some_string', 'another_string', 'yet_another_one'`. +- `{N..M}` — заменяет любое число в интервале от `N` до `M` включительно (может содержать ведущие нули). Конструкция с `{}` аналогична табличной функции [remote](remote.md). **Пример** -1. Предположим у нас есть несколько файлов со следующими относительными путями: +Предположим, у нас есть несколько файлов со следующими относительными путями: -- ‘some_dir/some_file_1’ -- ‘some_dir/some_file_2’ -- ‘some_dir/some_file_3’ -- ‘another_dir/some_file_1’ -- ‘another_dir/some_file_2’ -- ‘another_dir/some_file_3’ +- 'some_dir/some_file_1' +- 'some_dir/some_file_2' +- 'some_dir/some_file_3' +- 'another_dir/some_file_1' +- 'another_dir/some_file_2' +- 'another_dir/some_file_3' -1. Запросим количество строк в этих файлах: - - +Запросим количество строк в этих файлах: ``` sql -SELECT count(*) -FROM file('{some,another}_dir/some_file_{1..3}', 'TSV', 'name String, value UInt32') +SELECT count(*) FROM file('{some,another}_dir/some_file_{1..3}', 'TSV', 'name String, value UInt32'); ``` -1. Запросим количество строк во всех файлах этих двух директорий: - - +Запросим количество строк во всех файлах этих двух директорий: ``` sql -SELECT count(*) -FROM file('{some,another}_dir/*', 'TSV', 'name String, value UInt32') +SELECT count(*) FROM file('{some,another}_dir/*', 'TSV', 'name String, value UInt32'); ``` -!!! warning "Warning" +!!! warning "Предупреждение" Если ваш список файлов содержит интервал с ведущими нулями, используйте конструкцию с фигурными скобками для каждой цифры по отдельности или используйте `?`. **Пример** @@ -96,17 +114,16 @@ FROM file('{some,another}_dir/*', 'TSV', 'name String, value UInt32') Запрос данных из файлов с именами `file000`, `file001`, … , `file999`: ``` sql -SELECT count(*) -FROM file('big_dir/file{0..9}{0..9}{0..9}', 'CSV', 'name String, value UInt32') +SELECT count(*) FROM file('big_dir/file{0..9}{0..9}{0..9}', 'CSV', 'name String, value UInt32'); ``` ## Виртуальные столбцы {#virtualnye-stolbtsy} -- `_path` — Путь к файлу. -- `_file` — Имя файла. +- `_path` — путь к файлу. +- `_file` — имя файла. **Смотрите также** - [Виртуальные столбцы](index.md#table_engines-virtual_columns) -[Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/table_functions/file/) +[Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/table-functions/file/) diff --git a/docs/ru/sql-reference/table-functions/index.md b/docs/ru/sql-reference/table-functions/index.md index 83225d54e60..da04b2c7a10 100644 --- a/docs/ru/sql-reference/table-functions/index.md +++ b/docs/ru/sql-reference/table-functions/index.md @@ -1,8 +1,7 @@ --- -toc_folder_title: "\u0422\u0430\u0431\u043B\u0438\u0447\u043D\u044B\u0435 \u0444\u0443\ - \u043D\u043A\u0446\u0438\u0438" +toc_folder_title: "Табличные функции" toc_priority: 34 -toc_title: "\u0412\u0432\u0435\u0434\u0435\u043D\u0438\u0435" +toc_title: "Введение" --- # Табличные функции {#table-functions} diff --git a/docs/ru/sql-reference/table-functions/mysql.md b/docs/ru/sql-reference/table-functions/mysql.md index 21841eee67a..18b34d0bf6c 100644 --- a/docs/ru/sql-reference/table-functions/mysql.md +++ b/docs/ru/sql-reference/table-functions/mysql.md @@ -7,6 +7,8 @@ toc_title: mysql Позволяет выполнять запросы `SELECT` над данными, хранящимися на удалённом MySQL сервере. +**Синтаксис** + ``` sql mysql('host:port', 'database', 'table', 'user', 'password'[, replace_query, 'on_duplicate_clause']); ``` @@ -23,13 +25,13 @@ mysql('host:port', 'database', 'table', 'user', 'password'[, replace_query, 'on_ - `password` — пароль пользователя. -- `replace_query` — флаг, отвечающий за преобразование запросов `INSERT INTO` в `REPLACE INTO`. Если `replace_query=1`, то запрос заменяется. +- `replace_query` — флаг, отвечающий за преобразование запросов `INSERT INTO` в `REPLACE INTO`. Возможные значения: + - `0` - выполняется запрос `INSERT INTO`. + - `1` - выполняется запрос `REPLACE INTO`. -- `on_duplicate_clause` — выражение `ON DUPLICATE KEY on_duplicate_clause`, добавляемое в запрос `INSERT`. +- `on_duplicate_clause` — выражение `ON DUPLICATE KEY on_duplicate_clause`, добавляемое в запрос `INSERT`. Может быть передано только с помощью `replace_query = 0` (если вы одновременно передадите `replace_query = 1` и `on_duplicate_clause`, будет сгенерировано исключение). - Пример: `INSERT INTO t (c1,c2) VALUES ('a', 2) ON DUPLICATE KEY UPDATE c2 = c2 + 1`, где `on_duplicate_clause` это `UPDATE c2 = c2 + 1`. Чтобы узнать какие `on_duplicate_clause` можно использовать с секцией `ON DUPLICATE KEY` обратитесь к документации MySQL. - - Чтобы указать `'on_duplicate_clause'` необходимо передать `0` в параметр `replace_query`. Если одновременно передать `replace_query = 1` и `'on_duplicate_clause'`, то ClickHouse сгенерирует исключение. + Пример: `INSERT INTO t (c1,c2) VALUES ('a', 2) ON DUPLICATE KEY UPDATE c2 = c2 + 1`, где `on_duplicate_clause` это `UPDATE c2 = c2 + 1;` Простые условия `WHERE` такие как `=, !=, >, >=, <, =` выполняются на стороне сервера MySQL. @@ -39,46 +41,59 @@ mysql('host:port', 'database', 'table', 'user', 'password'[, replace_query, 'on_ Объект таблицы с теми же столбцами, что и в исходной таблице MySQL. -## Пример использования {#primer-ispolzovaniia} +!!! note "Примечание" + Чтобы отличить табличную функцию `mysql (...)` в запросе `INSERT` от имени таблицы со списком имен столбцов, используйте ключевые слова `FUNCTION` или `TABLE FUNCTION`. См. примеры ниже. + +**Примеры** Таблица в MySQL: ``` text mysql> CREATE TABLE `test`.`test` ( -> `int_id` INT NOT NULL AUTO_INCREMENT, - -> `int_nullable` INT NULL DEFAULT NULL, -> `float` FLOAT NOT NULL, - -> `float_nullable` FLOAT NULL DEFAULT NULL, -> PRIMARY KEY (`int_id`)); -Query OK, 0 rows affected (0,09 sec) -mysql> insert into test (`int_id`, `float`) VALUES (1,2); -Query OK, 1 row affected (0,00 sec) +mysql> INSERT INTO test (`int_id`, `float`) VALUES (1,2); -mysql> select * from test; -+--------+--------------+-------+----------------+ -| int_id | int_nullable | float | float_nullable | -+--------+--------------+-------+----------------+ -| 1 | NULL | 2 | NULL | -+--------+--------------+-------+----------------+ -1 row in set (0,00 sec) +mysql> SELECT * FROM test; ++--------+-------+ +| int_id | float | ++--------+-------+ +| 1 | 2 | ++--------+-------+ ``` Получение данных в ClickHouse: ``` sql -SELECT * FROM mysql('localhost:3306', 'test', 'test', 'bayonet', '123') +SELECT * FROM mysql('localhost:3306', 'test', 'test', 'bayonet', '123'); ``` ``` text -┌─int_id─┬─int_nullable─┬─float─┬─float_nullable─┐ -│ 1 │ ᴺᵁᴸᴸ │ 2 │ ᴺᵁᴸᴸ │ -└────────┴──────────────┴───────┴────────────────┘ +┌─int_id─┬─float─┐ +│ 1 │ 2 │ +└────────┴───────┘ ``` -## Смотрите также {#smotrite-takzhe} +Замена и вставка: + +```sql +INSERT INTO FUNCTION mysql('localhost:3306', 'test', 'test', 'bayonet', '123', 1) (int_id, float) VALUES (1, 3); +INSERT INTO TABLE FUNCTION mysql('localhost:3306', 'test', 'test', 'bayonet', '123', 0, 'UPDATE int_id = int_id + 1') (int_id, float) VALUES (1, 4); +SELECT * FROM mysql('localhost:3306', 'test', 'test', 'bayonet', '123'); +``` + +``` text +┌─int_id─┬─float─┐ +│ 1 │ 3 │ +│ 2 │ 4 │ +└────────┴───────┘ +``` + +**Смотрите также** - [Движок таблиц ‘MySQL’](../../sql-reference/table-functions/mysql.md) - [Использование MySQL как источника данных для внешнего словаря](../../sql-reference/table-functions/mysql.md#dicts-external_dicts_dict_sources-mysql) -[Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/table_functions/mysql/) +[Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/table_functions/mysql/) diff --git a/docs/ru/sql-reference/table-functions/remote.md b/docs/ru/sql-reference/table-functions/remote.md index 901317a805d..83b3687f61d 100644 --- a/docs/ru/sql-reference/table-functions/remote.md +++ b/docs/ru/sql-reference/table-functions/remote.md @@ -5,9 +5,11 @@ toc_title: remote # remote, remoteSecure {#remote-remotesecure} -Позволяет обратиться к удалённым серверам без создания таблицы типа `Distributed`. +Позволяет обратиться к удалённым серверам без создания таблицы типа [Distributed](../../engines/table-engines/special/distributed.md). Функция `remoteSecure` работает аналогично `remote`, но использует защищенное соединение. -Сигнатуры: +Обе функции могут использоваться в запросах `SELECT` и `INSERT`. + +**Синтаксис** ``` sql remote('addresses_expr', db, table[, 'user'[, 'password']]) @@ -16,12 +18,40 @@ remoteSecure('addresses_expr', db, table[, 'user'[, 'password']]) remoteSecure('addresses_expr', db.table[, 'user'[, 'password']]) ``` -`addresses_expr` - выражение, генерирующее адреса удалённых серверов. Это может быть просто один адрес сервера. Адрес сервера - это `хост:порт`, или только `хост`. Хост может быть указан в виде имени сервера, или в виде IPv4 или IPv6 адреса. IPv6 адрес указывается в квадратных скобках. Порт - TCP-порт удалённого сервера. Если порт не указан, используется `tcp_port` из конфигурационного файла сервера (по умолчанию - 9000). +**Параметры** + +- `addresses_expr` — выражение, генерирующее адреса удалённых серверов. Это может быть просто один адрес сервера. Адрес сервера — это `host:port` или только `host`. + + Вместо параметра `host` может быть указано имя сервера или его адрес в формате IPv4 или IPv6. IPv6 адрес указывается в квадратных скобках. + + `port` — TCP-порт удалённого сервера. Если порт не указан, используется [tcp_port](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-tcp_port) из конфигурационного файла сервера, к которому обратились через функцию `remote` (по умолчанию - 9000), и [tcp_port_secure](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-tcp_port_secure), к которому обратились через функцию `remoteSecure` (по умолчанию — 9440). -!!! important "Важно" С IPv6-адресом обязательно нужно указывать порт. -Примеры: + Тип: [String](../../sql-reference/data-types/string.md). + +- `db` — имя базы данных. Тип: [String](../../sql-reference/data-types/string.md). +- `table` — имя таблицы. Тип: [String](../../sql-reference/data-types/string.md). +- `user` — имя пользователя. Если пользователь не указан, то по умолчанию `default`. Тип: [String](../../sql-reference/data-types/string.md). +- `password` — пароль. Если пароль не указан, то используется пустой пароль. Тип: [String](../../sql-reference/data-types/string.md). +- `sharding_key` — ключ шардирования для поддержки распределения данных между узлами. Например: `insert into remote('127.0.0.1:9000,127.0.0.2', db, table, 'default', rand())`. Тип: [UInt32](../../sql-reference/data-types/int-uint.md). + +**Возвращаемое значение** + +Набор данных с удаленных серверов. + +**Использование** + +Использование табличной функции `remote` менее оптимально, чем создание таблицы типа `Distributed`, так как в этом случае соединения с серверами устанавливаются заново при каждом запросе. Если указываются имена серверов, то приходится также выполнять поиск сервера по имени. Кроме того, не ведётся сквозной подсчёт ошибок при работе с разными репликами. При обработке большого количества запросов всегда создавайте таблицу типа `Distributed`, использовать табличную функцию `remote` в таких случаях не рекомендуется. + +Табличная функция `remote` может быть полезна в следующих случаях: + +- Обращение на конкретный сервер для сравнения данных, отладки и тестирования. +- Запросы между разными кластерами ClickHouse для исследований. +- Нечастые распределённые запросы, задаваемые вручную. +- Распределённые запросы, где набор серверов определяется каждый раз заново. + +**Адреса** ``` text example01-01-1 @@ -32,9 +62,7 @@ localhost [2a02:6b8:0:1111::11]:9000 ``` -Адреса можно указать через запятую, в этом случае ClickHouse обработает запрос как распределённый, т.е. отправит его по всем указанным адресам как на шарды с разными данными. - -Пример: +Адреса можно указать через запятую. В этом случае ClickHouse обработает запрос как распределённый, т.е. отправит его по всем указанным адресам как на шарды с разными данными. Пример: ``` text example01-01-1,example01-02-1 @@ -46,38 +74,36 @@ example01-01-1,example01-02-1 example01-0{1,2}-1 ``` -В фигурных скобках может быть указан диапазон (неотрицательных целых) чисел через две точки. В этом случае, диапазон раскрывается в множество значений, генерирующих адреса шардов. Если запись первого числа начинается с нуля, то значения формируются с таким же выравниванием нулями. Предыдущий пример может быть записан следующим образом: +В фигурных скобках может быть указан диапазон (неотрицательных целых) чисел через две точки. В этом случае диапазон раскрывается в множество значений, генерирующих адреса шардов. Если запись первого числа начинается с нуля, то значения формируются с таким же выравниванием нулями. Предыдущий пример может быть записан следующим образом: ``` text example01-{01..02}-1 ``` -При наличии нескольких пар фигурных скобок, генерируется прямое произведение соответствующих множеств. +При наличии нескольких пар фигурных скобок генерируется прямое произведение соответствующих множеств. -Адреса или их фрагменты в фигурных скобках можно указать через символ \|. В этом случае, соответствующие множества адресов понимаются как реплики - запрос будет отправлен на первую живую реплику. При этом, реплики перебираются в порядке, согласно текущей настройке [load_balancing](../../operations/settings/settings.md). - -Пример: +Адреса или их фрагменты в фигурных скобках можно указать через символ \|. В этом случае соответствующие множества адресов понимаются как реплики — запрос будет отправлен на первую живую реплику. При этом реплики перебираются в порядке, согласно текущей настройке [load_balancing](../../operations/settings/settings.md#settings-load_balancing). В этом примере указаны два шарда, в каждом из которых имеются две реплики: ``` text example01-{01..02}-{1|2} ``` -В этом примере указано два шарда, в каждом из которых имеется две реплики. +Количество генерируемых адресов ограничено константой. Сейчас это 1000 адресов. -Количество генерируемых адресов ограничено константой - сейчас это 1000 штук. +**Примеры** -Использование табличной функции `remote` менее оптимально, чем создание таблицы типа `Distributed`, так как в этом случае, соединения с серверами устанавливаются заново при каждом запросе, в случае задания имён хостов, делается резолвинг имён, а также не ведётся подсчёт ошибок при работе с разными репликами. При обработке большого количества запросов, всегда создавайте `Distributed` таблицу заранее, не используйте табличную функцию `remote`. +Выборка данных с удаленного сервера: -Табличная функция `remote` может быть полезна для следующих случаях: +``` sql +SELECT * FROM remote('127.0.0.1', db.remote_engine_table) LIMIT 3; +``` -- обращение на конкретный сервер в целях сравнения данных, отладки и тестирования; -- запросы между разными кластерами ClickHouse в целях исследований; -- нечастых распределённых запросов, задаваемых вручную; -- распределённых запросов, где набор серверов определяется каждый раз заново. +Вставка данных с удаленного сервера в таблицу: -Если пользователь не задан,то используется `default`. -Если пароль не задан, то используется пустой пароль. +``` sql +CREATE TABLE remote_table (name String, value UInt32) ENGINE=Memory; +INSERT INTO FUNCTION remote('127.0.0.1', currentDatabase(), 'remote_table') VALUES ('test', 42); +SELECT * FROM remote_table; +``` -`remoteSecure` - аналогично функции `remote`, но с соединением по шифрованному каналу. Порт по умолчанию - `tcp_port_secure` из конфига или 9440. - -[Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/table_functions/remote/) +[Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/table-functions/remote/) diff --git a/docs/ru/sql-reference/table-functions/url.md b/docs/ru/sql-reference/table-functions/url.md index 0cd7c24c663..043a9231e75 100644 --- a/docs/ru/sql-reference/table-functions/url.md +++ b/docs/ru/sql-reference/table-functions/url.md @@ -5,21 +5,40 @@ toc_title: url # url {#url} -`url(URL, format, structure)` - возвращает таблицу со столбцами, указанными в -`structure`, созданную из данных находящихся по `URL` в формате `format`. +Функция `url` берет данные по указанному адресу `URL` и создает из них таблицу указанной структуры со столбцами указанного формата. -URL - адрес, по которому сервер принимает `GET` и/или `POST` запросы по -протоколу HTTP или HTTPS. +Функция `url` может быть использована в запросах `SELECT` и `INSERT` с таблицами на движке [URL](../../engines/table-engines/special/url.md). -format - [формат](../../interfaces/formats.md#formats) данных. - -structure - структура таблицы в форме `'UserID UInt64, Name String'`. Определяет имена и типы столбцов. - -**Пример** +**Синтаксис** ``` sql --- получение 3-х строк таблицы, состоящей из двух колонк типа String и UInt32 от сервера, отдающего данные в формате CSV -SELECT * FROM url('http://127.0.0.1:12345/', CSV, 'column1 String, column2 UInt32') LIMIT 3 +url(URL, format, structure) ``` -[Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/table_functions/url/) +**Параметры** + +- `URL` — HTTP или HTTPS-адрес сервера, который может принимать запросы `GET` или `POST` (для запросов `SELECT` или `INSERT` соответственно). Тип: [String](../../sql-reference/data-types/string.md). +- `format` — [формат](../../interfaces/formats.md#formats) данных. Тип: [String](../../sql-reference/data-types/string.md). +- `structure` — структура таблицы в формате `'UserID UInt64, Name String'`. Определяет имена и типы столбцов. Тип: [String](../../sql-reference/data-types/string.md). + +**Возвращаемое значение** + +Таблица с указанными форматом и структурой, а также с данными, полученными из указанного адреса `URL`. + +**Примеры** + +Получение с HTTP-сервера первых 3 строк таблицы с данными в формате [CSV](../../interfaces/formats.md/#csv), содержащей столбцы типа [String](../../sql-reference/data-types/string.md) и [UInt32](../../sql-reference/data-types/int-uint.md). + +``` sql +SELECT * FROM url('http://127.0.0.1:12345/', CSV, 'column1 String, column2 UInt32') LIMIT 3; +``` + +Вставка данных в таблицу: + +``` sql +CREATE TABLE test_table (column1 String, column2 UInt32) ENGINE=Memory; +INSERT INTO FUNCTION url('http://127.0.0.1:8123/?query=INSERT+INTO+test_table+FORMAT+CSV', 'CSV', 'column1 String, column2 UInt32') VALUES ('http interface', 42); +SELECT * FROM test_table; +``` + +[Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/table-functions/url/) diff --git a/docs/ru/whats-new/extended-roadmap.md b/docs/ru/whats-new/extended-roadmap.md deleted file mode 120000 index 471ca0aefaa..00000000000 --- a/docs/ru/whats-new/extended-roadmap.md +++ /dev/null @@ -1 +0,0 @@ -roadmap.md \ No newline at end of file diff --git a/docs/ru/whats-new/extended-roadmap.md b/docs/ru/whats-new/extended-roadmap.md new file mode 100644 index 00000000000..16c7709ec28 --- /dev/null +++ b/docs/ru/whats-new/extended-roadmap.md @@ -0,0 +1,10 @@ +--- +toc_priority: 74 +toc_title: Roadmap +--- + +# Планы развития {#roadmap} + +Планы развития на 2021 год опубликованы для обсуждения [здесь](https://github.com/ClickHouse/ClickHouse/issues/17623). + +[Оригинальная статья](https://clickhouse.tech/docs/ru/roadmap/) diff --git a/docs/ru/whats-new/index.md b/docs/ru/whats-new/index.md index b8ba6133454..d8a26423813 100644 --- a/docs/ru/whats-new/index.md +++ b/docs/ru/whats-new/index.md @@ -1,6 +1,8 @@ --- -toc_folder_title: "\u0427\u0442\u043E \u043D\u043E\u0432\u043E\u0433\u043E?" +toc_folder_title: "Что нового?" toc_priority: 82 --- +# Что нового в ClickHouse? +Планы развития вкратце изложены [здесь](extended-roadmap.md), а новости по предыдущим релизам подробно описаны в [журнале изменений](changelog/index.md). diff --git a/docs/ru/whats-new/roadmap.md b/docs/ru/whats-new/roadmap.md deleted file mode 120000 index 2c383b2ad5d..00000000000 --- a/docs/ru/whats-new/roadmap.md +++ /dev/null @@ -1 +0,0 @@ -../../en/whats-new/roadmap.md \ No newline at end of file diff --git a/docs/zh/commercial/cloud.md b/docs/zh/commercial/cloud.md index 9cca8776d14..c74ffa93e9a 100644 --- a/docs/zh/commercial/cloud.md +++ b/docs/zh/commercial/cloud.md @@ -29,6 +29,18 @@ toc_title: 云 - 跨可用区扩展以实现性能和高可用性 - 内置监控和SQL查询编辑器 +## 阿里云 {#alibaba-cloud} + +阿里云的 ClickHouse 托管服务 [中国站](https://www.aliyun.com/product/clickhouse) (国际站于2021年5月初开放) 提供以下主要功能: + +- 基于阿里飞天分布式系统的高可靠云盘存储引擎 +- 按需扩容,无需手动进行数据搬迁 +- 支持单节点、单副本、多节点、多副本多种架构,支持冷热数据分层 +- 支持访问白名单和一键恢复,多层网络安全防护,云盘加密 +- 与云上日志系统、数据库、数据应用工具无缝集成 +- 内置监控和数据库管理平台 +- 专业的数据库专家技术支持和服务 + ## 腾讯云 {#tencent-cloud} [腾讯云的 ClickHouse 托管服务](https://cloud.tencent.com/product/cdwch)提供以下主要功能: diff --git a/docs/zh/engines/table-engines/mergetree-family/replication.md b/docs/zh/engines/table-engines/mergetree-family/replication.md index 07ef255d6bb..a4d03e8da36 100644 --- a/docs/zh/engines/table-engines/mergetree-family/replication.md +++ b/docs/zh/engines/table-engines/mergetree-family/replication.md @@ -47,7 +47,7 @@ 如果配置文件中没有设置 ZooKeeper ,则无法创建复制表,并且任何现有的复制表都将变为只读。 -`SELECT` 查询并不需要借助 ZooKeeper ,复本并不影响 `SELECT` 的性能,查询复制表与非复制表速度是一样的。查询分布式表时,ClickHouse的处理方式可通过设置 [max_replica_delay_for_distributed_queries](../../../operations/settings/settings.md#settings-max_replica_delay_for_distributed_queries) 和 [fallback_to_stale_replicas_for_distributed_queries](../../../operations/settings/settings.md) 修改。 +`SELECT` 查询并不需要借助 ZooKeeper ,副本并不影响 `SELECT` 的性能,查询复制表与非复制表速度是一样的。查询分布式表时,ClickHouse的处理方式可通过设置 [max_replica_delay_for_distributed_queries](../../../operations/settings/settings.md#settings-max_replica_delay_for_distributed_queries) 和 [fallback_to_stale_replicas_for_distributed_queries](../../../operations/settings/settings.md) 修改。 对于每个 `INSERT` 语句,会通过几个事务将十来个记录添加到 ZooKeeper。(确切地说,这是针对每个插入的数据块; 每个 INSERT 语句的每 `max_insert_block_size = 1048576` 行和最后剩余的都各算作一个块。)相比非复制表,写 zk 会导致 `INSERT` 的延迟略长一些。但只要你按照建议每秒不超过一个 `INSERT` 地批量插入数据,不会有任何问题。一个 ZooKeeper 集群能给整个 ClickHouse 集群支撑协调每秒几百个 `INSERT`。数据插入的吞吐量(每秒的行数)可以跟不用复制的数据一样高。 diff --git a/docs/zh/operations/settings/query-complexity.md b/docs/zh/operations/settings/query-complexity.md index 1e7dc82f7e1..680d5e001e0 100644 --- a/docs/zh/operations/settings/query-complexity.md +++ b/docs/zh/operations/settings/query-complexity.md @@ -45,7 +45,7 @@ Restrictions on the «maximum amount of something» can take the value 0, which 用于在单个服务器上运行用户查询的最大RAM量。 -默认值定义在 [设置。h](https://github.com/ClickHouse/ClickHouse/blob/master/src/Interpreters/Settings.h#L244). 默认情况下,金额不受限制 (`max_memory_usage_for_user = 0`). +默认值定义在 [Settings.h](https://github.com/ClickHouse/ClickHouse/blob/master/src/Interpreters/Settings.h#L244). 默认情况下,数额不受限制 (`max_memory_usage_for_user = 0`). 另请参阅说明 [max_memory_usage](#settings_max_memory_usage). @@ -53,7 +53,7 @@ Restrictions on the «maximum amount of something» can take the value 0, which 用于在单个服务器上运行所有查询的最大RAM数量。 -默认值定义在 [设置。h](https://github.com/ClickHouse/ClickHouse/blob/master/src/Interpreters/Settings.h#L245). 默认情况下,金额不受限制 (`max_memory_usage_for_all_queries = 0`). +默认值定义在 [Settings.h](https://github.com/ClickHouse/ClickHouse/blob/master/src/Interpreters/Settings.h#L245). 默认情况下,数额不受限制 (`max_memory_usage_for_all_queries = 0`). 另请参阅说明 [max_memory_usage](#settings_max_memory_usage). diff --git a/docs/zh/sql-reference/operators/in.md b/docs/zh/sql-reference/operators/in.md index a16b75fe555..f39bd02c309 100644 --- a/docs/zh/sql-reference/operators/in.md +++ b/docs/zh/sql-reference/operators/in.md @@ -18,7 +18,7 @@ SELECT (CounterID, UserID) IN ((34, 123), (101500, 456)) FROM ... 如果左侧是索引中的单列,而右侧是一组常量,则系统将使用索引处理查询。 -Don't list too many values explicitly (i.e. millions). If a data set is large, put it in a temporary table (for example, see the section “External data for query processing”),然后使用子查询。 +请不要列举太多具体的常量 (比方说 几百万条)。如果数据集非常大,请把它放在一张临时表里(例如,参考章节[用于查询处理的外部数据](../../engines/table-engines/special/external-data.md)),然后使用子查询。 运算符的右侧可以是一组常量表达式、一组带有常量表达式的元组(如上面的示例所示),或括号中的数据库表或SELECT子查询的名称。 diff --git a/programs/client/Client.cpp b/programs/client/Client.cpp index 3c27908741c..da7c729a737 100644 --- a/programs/client/Client.cpp +++ b/programs/client/Client.cpp @@ -2472,7 +2472,7 @@ public: /** If "--password [value]" is used but the value is omitted, the bad argument exception will be thrown. * implicit_value is used to avoid this exception (to allow user to type just "--password") * Since currently boost provides no way to check if a value has been set implicitly for an option, - * the "\n" is used to distinguish this case because there is hardly a chance an user would use "\n" + * the "\n" is used to distinguish this case because there is hardly a chance a user would use "\n" * as the password. */ ("password", po::value()->implicit_value("\n", ""), "password") diff --git a/programs/format/Format.cpp b/programs/format/Format.cpp index 86a85d1d4a5..ba3d6e8557b 100644 --- a/programs/format/Format.cpp +++ b/programs/format/Format.cpp @@ -1,16 +1,18 @@ +#include #include #include -#include #include #include #include #include #include +#include #include -#include #include #include +#include +#include #include #include @@ -28,6 +30,14 @@ #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wmissing-declarations" +namespace DB +{ +namespace ErrorCodes +{ +extern const int INVALID_FORMAT_INSERT_QUERY_WITH_DATA; +} +} + int mainEntryClickHouseFormat(int argc, char ** argv) { using namespace DB; @@ -40,6 +50,7 @@ int mainEntryClickHouseFormat(int argc, char ** argv) ("quiet,q", "just check syntax, no output on success") ("multiquery,n", "allow multiple queries in the same file") ("obfuscate", "obfuscate instead of formatting") + ("backslash", "add a backslash at the end of each line of the formatted query") ("seed", po::value(), "seed (arbitrary string) that determines the result of obfuscation") ; @@ -60,6 +71,7 @@ int mainEntryClickHouseFormat(int argc, char ** argv) bool quiet = options.count("quiet"); bool multiple = options.count("multiquery"); bool obfuscate = options.count("obfuscate"); + bool backslash = options.count("backslash"); if (quiet && (hilite || oneline || obfuscate)) { @@ -128,15 +140,70 @@ int mainEntryClickHouseFormat(int argc, char ** argv) do { ASTPtr res = parseQueryAndMovePosition(parser, pos, end, "query", multiple, 0, DBMS_DEFAULT_MAX_PARSER_DEPTH); + /// For insert query with data(INSERT INTO ... VALUES ...), will lead to format fail, + /// should throw exception early and make exception message more readable. + if (const auto * insert_query = res->as(); insert_query && insert_query->data) + { + throw Exception( + "Can't format ASTInsertQuery with data, since data will be lost", + DB::ErrorCodes::INVALID_FORMAT_INSERT_QUERY_WITH_DATA); + } if (!quiet) { - WriteBufferFromOStream res_buf(std::cout, 4096); - formatAST(*res, res_buf, hilite, oneline); - res_buf.next(); - if (multiple) - std::cout << "\n;\n"; - std::cout << std::endl; + if (!backslash) + { + WriteBufferFromOStream res_buf(std::cout, 4096); + formatAST(*res, res_buf, hilite, oneline); + res_buf.next(); + if (multiple) + std::cout << "\n;\n"; + std::cout << std::endl; + } + /// add additional '\' at the end of each line; + else + { + WriteBufferFromOwnString str_buf; + formatAST(*res, str_buf, hilite, oneline); + + auto res_string = str_buf.str(); + WriteBufferFromOStream res_cout(std::cout, 4096); + + const char * s_pos= res_string.data(); + const char * s_end = s_pos + res_string.size(); + + while (s_pos != s_end) + { + if (*s_pos == '\n') + res_cout.write(" \\", 2); + res_cout.write(*s_pos++); + } + + res_cout.next(); + if (multiple) + std::cout << " \\\n;\n"; + std::cout << std::endl; + } } + + do + { + /// skip spaces to avoid throw exception after last query + while (pos != end && std::isspace(*pos)) + ++pos; + + /// for skip comment after the last query and to not throw exception + if (end - pos > 2 && *pos == '-' && *(pos + 1) == '-') + { + pos += 2; + /// skip until the end of the line + while (pos != end && *pos != '\n') + ++pos; + } + /// need to parse next sql + else + break; + } while (pos != end); + } while (multiple && pos != end); } } diff --git a/programs/install/Install.cpp b/programs/install/Install.cpp index 8404586d394..ef72624e7ab 100644 --- a/programs/install/Install.cpp +++ b/programs/install/Install.cpp @@ -66,6 +66,7 @@ namespace ErrorCodes extern const int CANNOT_OPEN_FILE; extern const int SYSTEM_ERROR; extern const int NOT_ENOUGH_SPACE; + extern const int CANNOT_KILL; } } @@ -886,6 +887,27 @@ namespace fmt::print("Sent kill signal.\n", pid); else throwFromErrno("Cannot send kill signal", ErrorCodes::SYSTEM_ERROR); + + /// Wait for the process (100 seconds). + constexpr size_t num_kill_check_tries = 1000; + constexpr size_t kill_check_delay_ms = 100; + for (size_t i = 0; i < num_kill_check_tries; ++i) + { + fmt::print("Waiting for server to be killed\n"); + if (!isRunning(pid_file)) + { + fmt::print("Server exited\n"); + break; + } + sleepForMilliseconds(kill_check_delay_ms); + } + + if (isRunning(pid_file)) + { + throw Exception(ErrorCodes::CANNOT_KILL, + "The server process still exists after %zu ms", + num_kill_check_tries, kill_check_delay_ms); + } } return 0; diff --git a/programs/local/LocalServer.cpp b/programs/local/LocalServer.cpp index 5a8d35e204d..7c6b60fbf8e 100644 --- a/programs/local/LocalServer.cpp +++ b/programs/local/LocalServer.cpp @@ -240,7 +240,7 @@ try /// Skip networking - /// Sets external authenticators config (LDAP). + /// Sets external authenticators config (LDAP, Kerberos). global_context->setExternalAuthenticatorsConfig(config()); setupUsers(); diff --git a/programs/odbc-bridge/ColumnInfoHandler.cpp b/programs/odbc-bridge/ColumnInfoHandler.cpp index ee4daa3e16d..14fa734f246 100644 --- a/programs/odbc-bridge/ColumnInfoHandler.cpp +++ b/programs/odbc-bridge/ColumnInfoHandler.cpp @@ -4,14 +4,14 @@ # include # include -# include +# include # include # include # include # include # include # include -# include +# include # include # include # include @@ -59,16 +59,16 @@ namespace } } -void ODBCColumnsInfoHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) +void ODBCColumnsInfoHandler::handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) { - Poco::Net::HTMLForm params(request, request.stream()); + HTMLForm params(request, request.getStream()); LOG_TRACE(log, "Request URI: {}", request.getURI()); auto process_error = [&response, this](const std::string & message) { response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); if (!response.sent()) - response.send() << message << std::endl; + *response.send() << message << std::endl; LOG_WARNING(log, message); }; @@ -159,8 +159,16 @@ void ODBCColumnsInfoHandler::handleRequest(Poco::Net::HTTPServerRequest & reques columns.emplace_back(reinterpret_cast(column_name), std::move(column_type)); } - WriteBufferFromHTTPServerResponse out(request, response, keep_alive_timeout); - writeStringBinary(columns.toString(), out); + WriteBufferFromHTTPServerResponse out(response, request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD, keep_alive_timeout); + try + { + writeStringBinary(columns.toString(), out); + out.finalize(); + } + catch (...) + { + out.finalize(); + } } catch (...) { diff --git a/programs/odbc-bridge/ColumnInfoHandler.h b/programs/odbc-bridge/ColumnInfoHandler.h index 04b4c06693b..9b5b470b31d 100644 --- a/programs/odbc-bridge/ColumnInfoHandler.h +++ b/programs/odbc-bridge/ColumnInfoHandler.h @@ -3,10 +3,11 @@ #if USE_ODBC # include -# include -# include +# include # include +# include + /** The structure of the table is taken from the query "SELECT * FROM table WHERE 1=0". * TODO: It would be much better to utilize ODBC methods dedicated for columns description. * If there is no such table, an exception is thrown. @@ -14,7 +15,7 @@ namespace DB { -class ODBCColumnsInfoHandler : public Poco::Net::HTTPRequestHandler +class ODBCColumnsInfoHandler : public HTTPRequestHandler { public: ODBCColumnsInfoHandler(size_t keep_alive_timeout_, Context & context_) @@ -22,7 +23,7 @@ public: { } - void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override; + void handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) override; private: Poco::Logger * log; diff --git a/programs/odbc-bridge/HandlerFactory.cpp b/programs/odbc-bridge/HandlerFactory.cpp index 0cc40480b87..9ac48af4ace 100644 --- a/programs/odbc-bridge/HandlerFactory.cpp +++ b/programs/odbc-bridge/HandlerFactory.cpp @@ -7,39 +7,40 @@ namespace DB { -Poco::Net::HTTPRequestHandler * HandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & request) + +std::unique_ptr HandlerFactory::createRequestHandler(const HTTPServerRequest & request) { Poco::URI uri{request.getURI()}; LOG_TRACE(log, "Request URI: {}", uri.toString()); if (uri.getPath() == "/ping" && request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) - return new PingHandler(keep_alive_timeout); + return std::make_unique(keep_alive_timeout); if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST) { if (uri.getPath() == "/columns_info") #if USE_ODBC - return new ODBCColumnsInfoHandler(keep_alive_timeout, context); + return std::make_unique(keep_alive_timeout, context); #else return nullptr; #endif else if (uri.getPath() == "/identifier_quote") #if USE_ODBC - return new IdentifierQuoteHandler(keep_alive_timeout, context); + return std::make_unique(keep_alive_timeout, context); #else return nullptr; #endif else if (uri.getPath() == "/schema_allowed") #if USE_ODBC - return new SchemaAllowedHandler(keep_alive_timeout, context); + return std::make_unique(keep_alive_timeout, context); #else return nullptr; #endif else if (uri.getPath() == "/write") - return new ODBCHandler(pool_map, keep_alive_timeout, context, "write"); + return std::make_unique(pool_map, keep_alive_timeout, context, "write"); else - return new ODBCHandler(pool_map, keep_alive_timeout, context, "read"); + return std::make_unique(pool_map, keep_alive_timeout, context, "read"); } return nullptr; } diff --git a/programs/odbc-bridge/HandlerFactory.h b/programs/odbc-bridge/HandlerFactory.h index 1d4edfc9dd1..5dce6f02ecd 100644 --- a/programs/odbc-bridge/HandlerFactory.h +++ b/programs/odbc-bridge/HandlerFactory.h @@ -1,16 +1,17 @@ #pragma once + #include -#include -#include -#include -#include "MainHandler.h" +#include #include "ColumnInfoHandler.h" #include "IdentifierQuoteHandler.h" +#include "MainHandler.h" #include "SchemaAllowedHandler.h" +#include + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" - #include +#include #pragma GCC diagnostic pop @@ -19,7 +20,7 @@ namespace DB /** Factory for '/ping', '/', '/columns_info', '/identifier_quote', '/schema_allowed' handlers. * Also stores Session pools for ODBC connections */ -class HandlerFactory : public Poco::Net::HTTPRequestHandlerFactory +class HandlerFactory : public HTTPRequestHandlerFactory { public: HandlerFactory(const std::string & name_, size_t keep_alive_timeout_, Context & context_) @@ -28,7 +29,7 @@ public: pool_map = std::make_shared(); } - Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override; + std::unique_ptr createRequestHandler(const HTTPServerRequest & request) override; private: Poco::Logger * log; diff --git a/programs/odbc-bridge/IdentifierQuoteHandler.cpp b/programs/odbc-bridge/IdentifierQuoteHandler.cpp index 2c3701cfff9..5060d37c479 100644 --- a/programs/odbc-bridge/IdentifierQuoteHandler.cpp +++ b/programs/odbc-bridge/IdentifierQuoteHandler.cpp @@ -3,14 +3,14 @@ #if USE_ODBC # include -# include +# include +# include # include # include # include # include # include # include -# include # include # include # include @@ -22,16 +22,16 @@ namespace DB { -void IdentifierQuoteHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) +void IdentifierQuoteHandler::handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) { - Poco::Net::HTMLForm params(request, request.stream()); + HTMLForm params(request, request.getStream()); LOG_TRACE(log, "Request URI: {}", request.getURI()); auto process_error = [&response, this](const std::string & message) { response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); if (!response.sent()) - response.send() << message << std::endl; + *response.send() << message << std::endl; LOG_WARNING(log, message); }; @@ -49,8 +49,16 @@ void IdentifierQuoteHandler::handleRequest(Poco::Net::HTTPServerRequest & reques auto identifier = getIdentifierQuote(hdbc); - WriteBufferFromHTTPServerResponse out(request, response, keep_alive_timeout); - writeStringBinary(identifier, out); + WriteBufferFromHTTPServerResponse out(response, request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD, keep_alive_timeout); + try + { + writeStringBinary(identifier, out); + out.finalize(); + } + catch (...) + { + out.finalize(); + } } catch (...) { diff --git a/programs/odbc-bridge/IdentifierQuoteHandler.h b/programs/odbc-bridge/IdentifierQuoteHandler.h index fd357e32786..dad88c72ad8 100644 --- a/programs/odbc-bridge/IdentifierQuoteHandler.h +++ b/programs/odbc-bridge/IdentifierQuoteHandler.h @@ -1,8 +1,9 @@ #pragma once #include +#include + #include -#include #if USE_ODBC @@ -10,7 +11,7 @@ namespace DB { -class IdentifierQuoteHandler : public Poco::Net::HTTPRequestHandler +class IdentifierQuoteHandler : public HTTPRequestHandler { public: IdentifierQuoteHandler(size_t keep_alive_timeout_, Context &) @@ -18,7 +19,7 @@ public: { } - void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override; + void handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) override; private: Poco::Logger * log; diff --git a/programs/odbc-bridge/MainHandler.cpp b/programs/odbc-bridge/MainHandler.cpp index 64cb7bc0b46..4fcc9deea6a 100644 --- a/programs/odbc-bridge/MainHandler.cpp +++ b/programs/odbc-bridge/MainHandler.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -73,19 +74,19 @@ ODBCHandler::PoolPtr ODBCHandler::getPool(const std::string & connection_str) return pool_map->at(connection_str); } -void ODBCHandler::processError(Poco::Net::HTTPServerResponse & response, const std::string & message) +void ODBCHandler::processError(HTTPServerResponse & response, const std::string & message) { - response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); + response.setStatusAndReason(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); if (!response.sent()) - response.send() << message << std::endl; + *response.send() << message << std::endl; LOG_WARNING(log, message); } -void ODBCHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) +void ODBCHandler::handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) { - Poco::Net::HTMLForm params(request); + HTMLForm params(request); if (mode == "read") - params.read(request.stream()); + params.read(request.getStream()); LOG_TRACE(log, "Request URI: {}", request.getURI()); if (mode == "read" && !params.has("query")) @@ -136,7 +137,7 @@ void ODBCHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Ne std::string connection_string = params.get("connection_string"); LOG_TRACE(log, "Connection string: '{}'", connection_string); - WriteBufferFromHTTPServerResponse out(request, response, keep_alive_timeout); + WriteBufferFromHTTPServerResponse out(response, request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD, keep_alive_timeout); try { @@ -163,9 +164,8 @@ void ODBCHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Ne #endif auto pool = getPool(connection_string); - ReadBufferFromIStream read_buf(request.stream()); - auto input_format = FormatFactory::instance().getInput(format, read_buf, *sample_block, - context, max_block_size); + auto & read_buf = request.getStream(); + auto input_format = FormatFactory::instance().getInput(format, read_buf, *sample_block, context, max_block_size); auto input_stream = std::make_shared(input_format); ODBCBlockOutputStream output_stream(pool->get(), db_name, table_name, *sample_block, quoting_style); copyData(*input_stream, output_stream); @@ -187,9 +187,27 @@ void ODBCHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Ne auto message = getCurrentExceptionMessage(true); response.setStatusAndReason( Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); // can't call process_error, because of too soon response sending - writeStringBinary(message, out); - tryLogCurrentException(log); + try + { + writeStringBinary(message, out); + out.finalize(); + } + catch (...) + { + tryLogCurrentException(log); + } + + tryLogCurrentException(log); + } + + try + { + out.finalize(); + } + catch (...) + { + tryLogCurrentException(log); } } diff --git a/programs/odbc-bridge/MainHandler.h b/programs/odbc-bridge/MainHandler.h index ec5e6693a60..e237ede5814 100644 --- a/programs/odbc-bridge/MainHandler.h +++ b/programs/odbc-bridge/MainHandler.h @@ -1,12 +1,13 @@ #pragma once #include +#include + #include -#include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" - #include +#include #pragma GCC diagnostic pop namespace DB @@ -16,7 +17,7 @@ namespace DB * and also query in request body * response in RowBinary format */ -class ODBCHandler : public Poco::Net::HTTPRequestHandler +class ODBCHandler : public HTTPRequestHandler { public: using PoolPtr = std::shared_ptr; @@ -34,7 +35,7 @@ public: { } - void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override; + void handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) override; private: Poco::Logger * log; @@ -47,7 +48,7 @@ private: static inline std::mutex mutex; PoolPtr getPool(const std::string & connection_str); - void processError(Poco::Net::HTTPServerResponse & response, const std::string & message); + void processError(HTTPServerResponse & response, const std::string & message); }; } diff --git a/programs/odbc-bridge/ODBCBridge.cpp b/programs/odbc-bridge/ODBCBridge.cpp index 9deefaf7895..8869a2639c1 100644 --- a/programs/odbc-bridge/ODBCBridge.cpp +++ b/programs/odbc-bridge/ODBCBridge.cpp @@ -11,7 +11,6 @@ # include #endif -#include #include #include #include @@ -23,6 +22,7 @@ #include #include #include +#include namespace DB @@ -212,8 +212,12 @@ int ODBCBridge::main(const std::vector & /*args*/) SensitiveDataMasker::setInstance(std::make_unique(config(), "query_masking_rules")); } - auto server = Poco::Net::HTTPServer( - new HandlerFactory("ODBCRequestHandlerFactory-factory", keep_alive_timeout, context), server_pool, socket, http_params); + auto server = HTTPServer( + context, + std::make_shared("ODBCRequestHandlerFactory-factory", keep_alive_timeout, context), + server_pool, + socket, + http_params); server.start(); LOG_INFO(log, "Listening http://{}", address.toString()); diff --git a/programs/odbc-bridge/PingHandler.cpp b/programs/odbc-bridge/PingHandler.cpp index b0313e46bf3..e3ab5e5cd00 100644 --- a/programs/odbc-bridge/PingHandler.cpp +++ b/programs/odbc-bridge/PingHandler.cpp @@ -6,7 +6,7 @@ namespace DB { -void PingHandler::handleRequest(Poco::Net::HTTPServerRequest & /*request*/, Poco::Net::HTTPServerResponse & response) +void PingHandler::handleRequest(HTTPServerRequest & /* request */, HTTPServerResponse & response) { try { diff --git a/programs/odbc-bridge/PingHandler.h b/programs/odbc-bridge/PingHandler.h index d8109a50bb6..c969ec55af7 100644 --- a/programs/odbc-bridge/PingHandler.h +++ b/programs/odbc-bridge/PingHandler.h @@ -1,17 +1,19 @@ #pragma once -#include + +#include namespace DB { -/** Simple ping handler, answers "Ok." to GET request - */ -class PingHandler : public Poco::Net::HTTPRequestHandler + +/// Simple ping handler, answers "Ok." to GET request +class PingHandler : public HTTPRequestHandler { public: - PingHandler(size_t keep_alive_timeout_) : keep_alive_timeout(keep_alive_timeout_) {} - void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override; + explicit PingHandler(size_t keep_alive_timeout_) : keep_alive_timeout(keep_alive_timeout_) {} + void handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) override; private: size_t keep_alive_timeout; }; + } diff --git a/programs/odbc-bridge/SchemaAllowedHandler.cpp b/programs/odbc-bridge/SchemaAllowedHandler.cpp index fa08a27da59..d4a70db61f4 100644 --- a/programs/odbc-bridge/SchemaAllowedHandler.cpp +++ b/programs/odbc-bridge/SchemaAllowedHandler.cpp @@ -2,12 +2,12 @@ #if USE_ODBC -# include +# include +# include # include # include # include # include -# include # include # include # include @@ -33,16 +33,16 @@ namespace } -void SchemaAllowedHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) +void SchemaAllowedHandler::handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) { - Poco::Net::HTMLForm params(request, request.stream()); + HTMLForm params(request, request.getStream()); LOG_TRACE(log, "Request URI: {}", request.getURI()); auto process_error = [&response, this](const std::string & message) { response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); if (!response.sent()) - response.send() << message << std::endl; + *response.send() << message << std::endl; LOG_WARNING(log, message); }; @@ -60,8 +60,16 @@ void SchemaAllowedHandler::handleRequest(Poco::Net::HTTPServerRequest & request, bool result = isSchemaAllowed(hdbc); - WriteBufferFromHTTPServerResponse out(request, response, keep_alive_timeout); - writeBoolText(result, out); + WriteBufferFromHTTPServerResponse out(response, request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD, keep_alive_timeout); + try + { + writeBoolText(result, out); + out.finalize(); + } + catch (...) + { + out.finalize(); + } } catch (...) { diff --git a/programs/odbc-bridge/SchemaAllowedHandler.h b/programs/odbc-bridge/SchemaAllowedHandler.h index 76aa23b903c..91eddf67803 100644 --- a/programs/odbc-bridge/SchemaAllowedHandler.h +++ b/programs/odbc-bridge/SchemaAllowedHandler.h @@ -1,17 +1,18 @@ #pragma once +#include + #include -#include #if USE_ODBC namespace DB { + class Context; - -/// This handler establishes connection to database, and retrieve whether schema is allowed. -class SchemaAllowedHandler : public Poco::Net::HTTPRequestHandler +/// This handler establishes connection to database, and retrieves whether schema is allowed. +class SchemaAllowedHandler : public HTTPRequestHandler { public: SchemaAllowedHandler(size_t keep_alive_timeout_, Context &) @@ -19,7 +20,7 @@ public: { } - void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override; + void handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) override; private: Poco::Logger * log; diff --git a/programs/server/Server.cpp b/programs/server/Server.cpp index 2bb5181d348..9889b08828b 100644 --- a/programs/server/Server.cpp +++ b/programs/server/Server.cpp @@ -59,7 +59,6 @@ #include #include #include -#include #include "MetricsTransmitter.h" #include #include @@ -70,6 +69,7 @@ #include #include #include +#include #if !defined(ARCADIA_BUILD) @@ -82,6 +82,7 @@ #if defined(OS_LINUX) # include +# include # include #endif @@ -94,12 +95,16 @@ # include #endif +#if USE_NURAFT +# include +#endif namespace CurrentMetrics { extern const Metric Revision; extern const Metric VersionInteger; extern const Metric MemoryTracking; + extern const Metric MaxDDLEntryID; } @@ -476,16 +481,26 @@ int Server::main(const std::vector & /*args*/) } else { - throw Exception(ErrorCodes::CORRUPTED_DATA, - "Calculated checksum of the ClickHouse binary ({0}) does not correspond" - " to the reference checksum stored in the binary ({1})." - " It may indicate one of the following:" - " - the file {2} was changed just after startup;" - " - the file {2} is damaged on disk due to faulty hardware;" - " - the loaded executable is damaged in memory due to faulty hardware;" - " - the file {2} was intentionally modified;" - " - logical error in code." - , calculated_binary_hash, stored_binary_hash, executable_path); + /// If program is run under debugger, ptrace will fail. + if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1) + { + /// Program is run under debugger. Modification of it's binary image is ok for breakpoints. + LOG_WARNING(log, "Server is run under debugger and its binary image is modified (most likely with breakpoints).", + calculated_binary_hash); + } + else + { + throw Exception(ErrorCodes::CORRUPTED_DATA, + "Calculated checksum of the ClickHouse binary ({0}) does not correspond" + " to the reference checksum stored in the binary ({1})." + " It may indicate one of the following:" + " - the file {2} was changed just after startup;" + " - the file {2} is damaged on disk due to faulty hardware;" + " - the loaded executable is damaged in memory due to faulty hardware;" + " - the file {2} was intentionally modified;" + " - logical error in code." + , calculated_binary_hash, stored_binary_hash, executable_path); + } } } else @@ -700,7 +715,7 @@ int Server::main(const std::vector & /*args*/) config().getString("path", ""), std::move(main_config_zk_node_cache), main_config_zk_changed_event, - [&](ConfigurationPtr config) + [&](ConfigurationPtr config, bool initial_loading) { Settings::checkNoSettingNamesAtTopLevel(*config, config_path); @@ -750,14 +765,19 @@ int Server::main(const std::vector & /*args*/) if (config->has("max_partition_size_to_drop")) global_context->setMaxPartitionSizeToDrop(config->getUInt64("max_partition_size_to_drop")); - if (config->has("zookeeper")) - global_context->reloadZooKeeperIfChanged(config); + if (!initial_loading) + { + /// We do not load ZooKeeper configuration on the first config loading + /// because TestKeeper server is not started yet. + if (config->has("zookeeper")) + global_context->reloadZooKeeperIfChanged(config); - global_context->reloadAuxiliaryZooKeepersConfigIfChanged(config); + global_context->reloadAuxiliaryZooKeepersConfigIfChanged(config); + } global_context->updateStorageConfiguration(*config); }, - /* already_loaded = */ true); + /* already_loaded = */ false); /// Reload it right now (initial loading) auto & access_control = global_context->getAccessControlManager(); if (config().has("custom_settings_prefixes")) @@ -842,23 +862,33 @@ int Server::main(const std::vector & /*args*/) listen_try = true; } - for (const auto & listen_host : listen_hosts) + if (config().has("test_keeper_server")) { - /// TCP TestKeeper - const char * port_name = "test_keeper_server.tcp_port"; - createServer(listen_host, port_name, listen_try, [&](UInt16 port) +#if USE_NURAFT + /// Initialize test keeper RAFT. Do nothing if no nu_keeper_server in config. + global_context->initializeNuKeeperStorageDispatcher(); + for (const auto & listen_host : listen_hosts) { - Poco::Net::ServerSocket socket; - auto address = socketBindListen(socket, listen_host, port); - socket.setReceiveTimeout(settings.receive_timeout); - socket.setSendTimeout(settings.send_timeout); - servers_to_start_before_tables->emplace_back( - port_name, - std::make_unique( - new TestKeeperTCPHandlerFactory(*this), server_pool, socket, new Poco::Net::TCPServerParams)); + /// TCP NuKeeper + const char * port_name = "test_keeper_server.tcp_port"; + createServer(listen_host, port_name, listen_try, [&](UInt16 port) + { + Poco::Net::ServerSocket socket; + auto address = socketBindListen(socket, listen_host, port); + socket.setReceiveTimeout(settings.receive_timeout); + socket.setSendTimeout(settings.send_timeout); + servers_to_start_before_tables->emplace_back( + port_name, + std::make_unique( + new NuKeeperTCPHandlerFactory(*this), server_pool, socket, new Poco::Net::TCPServerParams)); + + LOG_INFO(log, "Listening for connections to NuKeeper (tcp): {}", address.toString()); + }); + } +#else + throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "ClickHouse server built without NuRaft library. Cannot use internal coordination."); +#endif - LOG_INFO(log, "Listening for connections to fake zookeeper (tcp): {}", address.toString()); - }); } for (auto & server : *servers_to_start_before_tables) @@ -898,6 +928,8 @@ int Server::main(const std::vector & /*args*/) LOG_INFO(log, "Closed connections to servers for tables. But {} remain. Probably some tables of other users cannot finish their connections after context shutdown.", current_connections); else LOG_INFO(log, "Closed connections to servers for tables."); + + global_context->shutdownNuKeeperStorageDispatcher(); } /** Explicitly destroy Context. It is more convenient than in destructor of Server, because logger is still available. @@ -990,16 +1022,6 @@ int Server::main(const std::vector & /*args*/) LOG_INFO(log, "Query Profiler and TraceCollector are disabled because they require PHDR cache to be created" " (otherwise the function 'dl_iterate_phdr' is not lock free and not async-signal safe)."); - if (has_zookeeper && config().has("distributed_ddl")) - { - /// DDL worker should be started after all tables were loaded - String ddl_zookeeper_path = config().getString("distributed_ddl.path", "/clickhouse/task_queue/ddl/"); - int pool_size = config().getInt("distributed_ddl.pool_size", 1); - if (pool_size < 1) - throw Exception("distributed_ddl.pool_size should be greater then 0", ErrorCodes::ARGUMENT_OUT_OF_BOUND); - global_context->setDDLWorker(std::make_unique(pool_size, ddl_zookeeper_path, *global_context, &config(), "distributed_ddl")); - } - std::unique_ptr dns_cache_updater; if (config().has("disable_internal_dns_cache") && config().getInt("disable_internal_dns_cache")) { @@ -1056,8 +1078,10 @@ int Server::main(const std::vector & /*args*/) socket.setReceiveTimeout(settings.http_receive_timeout); socket.setSendTimeout(settings.http_send_timeout); - servers->emplace_back(port_name, std::make_unique( - createHandlerFactory(*this, async_metrics, "HTTPHandler-factory"), server_pool, socket, http_params)); + servers->emplace_back( + port_name, + std::make_unique( + context(), createHandlerFactory(*this, async_metrics, "HTTPHandler-factory"), server_pool, socket, http_params)); LOG_INFO(log, "Listening for http://{}", address.toString()); }); @@ -1071,8 +1095,10 @@ int Server::main(const std::vector & /*args*/) auto address = socketBindListen(socket, listen_host, port, /* secure = */ true); socket.setReceiveTimeout(settings.http_receive_timeout); socket.setSendTimeout(settings.http_send_timeout); - servers->emplace_back(port_name, std::make_unique( - createHandlerFactory(*this, async_metrics, "HTTPSHandler-factory"), server_pool, socket, http_params)); + servers->emplace_back( + port_name, + std::make_unique( + context(), createHandlerFactory(*this, async_metrics, "HTTPSHandler-factory"), server_pool, socket, http_params)); LOG_INFO(log, "Listening for https://{}", address.toString()); #else @@ -1146,8 +1172,14 @@ int Server::main(const std::vector & /*args*/) auto address = socketBindListen(socket, listen_host, port); socket.setReceiveTimeout(settings.http_receive_timeout); socket.setSendTimeout(settings.http_send_timeout); - servers->emplace_back(port_name, std::make_unique( - createHandlerFactory(*this, async_metrics, "InterserverIOHTTPHandler-factory"), server_pool, socket, http_params)); + servers->emplace_back( + port_name, + std::make_unique( + context(), + createHandlerFactory(*this, async_metrics, "InterserverIOHTTPHandler-factory"), + server_pool, + socket, + http_params)); LOG_INFO(log, "Listening for replica communication (interserver): http://{}", address.toString()); }); @@ -1160,8 +1192,14 @@ int Server::main(const std::vector & /*args*/) auto address = socketBindListen(socket, listen_host, port, /* secure = */ true); socket.setReceiveTimeout(settings.http_receive_timeout); socket.setSendTimeout(settings.http_send_timeout); - servers->emplace_back(port_name, std::make_unique( - createHandlerFactory(*this, async_metrics, "InterserverIOHTTPSHandler-factory"), server_pool, socket, http_params)); + servers->emplace_back( + port_name, + std::make_unique( + context(), + createHandlerFactory(*this, async_metrics, "InterserverIOHTTPSHandler-factory"), + server_pool, + socket, + http_params)); LOG_INFO(log, "Listening for secure replica communication (interserver): https://{}", address.toString()); #else @@ -1221,8 +1259,14 @@ int Server::main(const std::vector & /*args*/) auto address = socketBindListen(socket, listen_host, port); socket.setReceiveTimeout(settings.http_receive_timeout); socket.setSendTimeout(settings.http_send_timeout); - servers->emplace_back(port_name, std::make_unique( - createHandlerFactory(*this, async_metrics, "PrometheusHandler-factory"), server_pool, socket, http_params)); + servers->emplace_back( + port_name, + std::make_unique( + context(), + createHandlerFactory(*this, async_metrics, "PrometheusHandler-factory"), + server_pool, + socket, + http_params)); LOG_INFO(log, "Listening for Prometheus: http://{}", address.toString()); }); @@ -1259,6 +1303,37 @@ int Server::main(const std::vector & /*args*/) std::thread::hardware_concurrency()); } + /// try to load dictionaries immediately, throw on error and die + ext::scope_guard dictionaries_xmls, models_xmls; + try + { + if (!config().getBool("dictionaries_lazy_load", true)) + { + global_context->tryCreateEmbeddedDictionaries(); + global_context->getExternalDictionariesLoader().enableAlwaysLoadEverything(true); + } + dictionaries_xmls = global_context->getExternalDictionariesLoader().addConfigRepository( + std::make_unique(config(), "dictionaries_config")); + models_xmls = global_context->getExternalModelsLoader().addConfigRepository( + std::make_unique(config(), "models_config")); + } + catch (...) + { + LOG_ERROR(log, "Caught exception while loading dictionaries."); + throw; + } + + if (has_zookeeper && config().has("distributed_ddl")) + { + /// DDL worker should be started after all tables were loaded + String ddl_zookeeper_path = config().getString("distributed_ddl.path", "/clickhouse/task_queue/ddl/"); + int pool_size = config().getInt("distributed_ddl.pool_size", 1); + if (pool_size < 1) + throw Exception("distributed_ddl.pool_size should be greater then 0", ErrorCodes::ARGUMENT_OUT_OF_BOUND); + global_context->setDDLWorker(std::make_unique(pool_size, ddl_zookeeper_path, *global_context, &config(), + "distributed_ddl", "DDLWorker", &CurrentMetrics::MaxDDLEntryID)); + } + LOG_INFO(log, "Ready for connections."); SCOPE_EXIT({ @@ -1308,26 +1383,6 @@ int Server::main(const std::vector & /*args*/) } }); - /// try to load dictionaries immediately, throw on error and die - ext::scope_guard dictionaries_xmls, models_xmls; - try - { - if (!config().getBool("dictionaries_lazy_load", true)) - { - global_context->tryCreateEmbeddedDictionaries(); - global_context->getExternalDictionariesLoader().enableAlwaysLoadEverything(true); - } - dictionaries_xmls = global_context->getExternalDictionariesLoader().addConfigRepository( - std::make_unique(config(), "dictionaries_config")); - models_xmls = global_context->getExternalModelsLoader().addConfigRepository( - std::make_unique(config(), "models_config")); - } - catch (...) - { - LOG_ERROR(log, "Caught exception while loading dictionaries."); - throw; - } - std::vector> metrics_transmitters; for (const auto & graphite_key : DB::getMultipleKeysFromConfig(config(), "", "graphite")) { diff --git a/programs/server/Server.h b/programs/server/Server.h index c582e475308..fbfc26f6ee5 100644 --- a/programs/server/Server.h +++ b/programs/server/Server.h @@ -51,6 +51,7 @@ public: } void defineOptions(Poco::Util::OptionSet & _options) override; + protected: int run() override; @@ -65,8 +66,6 @@ protected: private: Context * global_context_ptr = nullptr; -private: - Poco::Net::SocketAddress socketBindListen(Poco::Net::ServerSocket & socket, const std::string & host, UInt16 port, [[maybe_unused]] bool secure = false) const; using CreateServerFunc = std::function; diff --git a/programs/server/config.xml b/programs/server/config.xml index 849d3dc32ba..4220ecbcacd 100644 --- a/programs/server/config.xml +++ b/programs/server/config.xml @@ -284,6 +284,10 @@ In bytes. Cache is single for server. Memory is allocated only on demand. Cache is used when 'use_uncompressed_cache' user setting turned on (off by default). Uncompressed cache is advantageous only for very short queries and in rare cases. + + Note: uncompressed cache can be pointless for lz4, because memory bandwidth + is slower than multi-core decompression on some server configurations. + Enabling it can sometimes paradoxically make queries slower. --> 8589934592 @@ -358,6 +362,27 @@ --> + + @@ -421,9 +446,15 @@ - + + + + default @@ -568,7 +599,7 @@ - + - + + + + + + + + + + + + diff --git a/programs/server/users.xml b/programs/server/users.xml index 3223d855651..b33dc0628d1 100644 --- a/programs/server/users.xml +++ b/programs/server/users.xml @@ -7,9 +7,6 @@ 10000000000 - - 0 - + * Comment must end with -->. Nested comments are not possible. + * Note: constructions like are not valid comments in HTML but will be skipped by other rules. + * + * 2. CDATA is pasted verbatim. + * Note: CDATA is XML/XHTML specific. But we still process it for "best-effort" approach. + * + * 3. 'script' and 'style' elements are removed with all their content. + * Note: it's assumed that closing tag cannot appear inside content. + * For example, in JS string literal is has to be escaped as "<\/script>". + * Note: comments and CDATA is possible inside script or style - then closing tags are not searched inside CDATA. + * Example: ]]> + * But still searched inside comments. Sometimes it becomes complicated: + * var y = "-->"; alert(x + y); + * Note: script and style can be the names of XML namespaces - then they are not treat like usual script or style. + * Example: Hello. + * Note: whitespaces are possible after closing tag name: but not before: < / script>. + * + * 4. Other tags or tag-like elements are skipped without inner content. + * Example: . + * Note: it's expected that this HTML is illegal: + * Note: it will also skip something like tags: <>, , etc. + * Note: tag without end will be skipped to the end of input: + * 5. HTML and XML entities are not decoded. + * It should be processed by separate function. + * + * 6. Whitespaces in text are collapsed or inserted by specific rules. + * Whitespaces at beginning and at the end are removed. + * Consecutive whitespaces are collapsed. + * But if text is separated by other elements and there is no whitespace, it is inserted. + * It may be unnatural, examples: Helloworld, Helloworld + * - in HTML there will be no whitespace, but the function will insert it. + * But also consider: Hello

world

, Hello
world. + * This behaviour is reasonable for data analysis, e.g. convert HTML to a bag of words. + * + * 7. Also note that correct handling of whitespaces would require + * support of
 and CSS display and white-space properties.
+  *
+  * Usage example:
+  *
+  * SELECT extractTextFromHTML(html) FROM url('https://yandex.ru/', RawBLOB, 'html String')
+  *
+  * - ClickHouse has embedded web browser.
+  */
+
+namespace DB
+{
+
+namespace ErrorCodes
+{
+    extern const int ILLEGAL_COLUMN;
+    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
+}
+
+namespace
+{
+
+inline bool startsWith(const char * s, const char * end, const char * prefix)
+{
+    return s + strlen(prefix) < end && 0 == memcmp(s, prefix, strlen(prefix));
+}
+
+inline bool checkAndSkip(const char * __restrict & s, const char * end, const char * prefix)
+{
+    if (startsWith(s, end, prefix))
+    {
+        s += strlen(prefix);
+        return true;
+    }
+    return false;
+}
+
+bool processComment(const char * __restrict & src, const char * end)
+{
+    if (!checkAndSkip(src, end, "
+            2000
+            3000
+            
+            36000
+            
+        
+    
+
diff --git a/tests/integration/ci-runner.py b/tests/integration/ci-runner.py new file mode 100755 index 00000000000..f758457ada0 --- /dev/null +++ b/tests/integration/ci-runner.py @@ -0,0 +1,524 @@ +#!/usr/bin/env python3 + +import logging +import subprocess +import os +import time +import shutil +from collections import defaultdict +import random +import json +import csv + + +MAX_RETRY = 2 +SLEEP_BETWEEN_RETRIES = 5 +CLICKHOUSE_BINARY_PATH = "/usr/bin/clickhouse" +CLICKHOUSE_ODBC_BRIDGE_BINARY_PATH = "/usr/bin/clickhouse-odbc-bridge" + +TRIES_COUNT = 10 +MAX_TIME_SECONDS = 3600 + + +def get_tests_to_run(pr_info): + result = set([]) + changed_files = pr_info['changed_files'] + + if changed_files is None: + return [] + + for fpath in changed_files: + if 'tests/integration/test_' in fpath: + logging.info('File %s changed and seems like integration test', fpath) + result.add(fpath.split('/')[2]) + return list(result) + + +def filter_existing_tests(tests_to_run, repo_path): + result = [] + for relative_test_path in tests_to_run: + if os.path.exists(os.path.join(repo_path, 'tests/integration', relative_test_path)): + result.append(relative_test_path) + else: + logging.info("Skipping test %s, seems like it was removed", relative_test_path) + return result + + +def _get_deselect_option(tests): + return ' '.join(['--deselect {}'.format(t) for t in tests]) + + +def parse_test_results_output(fname): + read = False + description_output = [] + with open(fname, 'r') as out: + for line in out: + if read and line.strip() and not line.startswith('=='): + description_output.append(line.strip()) + if 'short test summary info' in line: + read = True + return description_output + + +def get_counters(output): + counters = { + "ERROR": set([]), + "PASSED": set([]), + "FAILED": set([]), + } + + for line in output: + if '.py' in line: + line_arr = line.strip().split(' ') + state = line_arr[0] + test_name = ' '.join(line_arr[1:]) + if ' - ' in test_name: + test_name = test_name[:test_name.find(' - ')] + if state in counters: + counters[state].add(test_name) + else: + logging.info("Strange line %s", line) + else: + logging.info("Strange line %s") + return {k: list(v) for k, v in counters.items()} + + +def parse_test_times(fname): + read = False + description_output = [] + with open(fname, 'r') as out: + for line in out: + if read and '==' in line: + break + if read and line.strip(): + description_output.append(line.strip()) + if 'slowest durations' in line: + read = True + return description_output + + +def get_test_times(output): + result = defaultdict(float) + for line in output: + if '.py' in line: + line_arr = line.strip().split(' ') + test_time = line_arr[0] + test_name = ' '.join([elem for elem in line_arr[2:] if elem]) + if test_name not in result: + result[test_name] = 0.0 + result[test_name] += float(test_time[:-1]) + return result + + +def clear_ip_tables_and_restart_daemons(): + logging.info("Dump iptables after run %s", subprocess.check_output("iptables -L", shell=True)) + try: + logging.info("Killing all alive docker containers") + subprocess.check_output("docker kill $(docker ps -q)", shell=True) + except subprocess.CalledProcessError as err: + logging.info("docker kill excepted: " + str(err)) + + try: + logging.info("Removing all docker containers") + subprocess.check_output("docker rm $(docker ps -a -q) --force", shell=True) + except subprocess.CalledProcessError as err: + logging.info("docker rm excepted: " + str(err)) + + try: + logging.info("Stopping docker daemon") + subprocess.check_output("service docker stop", shell=True) + except subprocess.CalledProcessError as err: + logging.info("docker stop excepted: " + str(err)) + + try: + for i in range(200): + try: + logging.info("Restarting docker %s", i) + subprocess.check_output("service docker start", shell=True) + subprocess.check_output("docker ps", shell=True) + break + except subprocess.CalledProcessError as err: + time.sleep(0.5) + logging.info("Waiting docker to start, current %s", str(err)) + else: + raise Exception("Docker daemon doesn't responding") + except subprocess.CalledProcessError as err: + logging.info("Can't reload docker: " + str(err)) + + try: + for i in xrange(1000): + # when rules will be empty, it will raise exception + subprocess.check_call("iptables -D DOCKER-USER 1", shell=True) # STYLE_CHECK_ALLOW_SUBPROCESS_CHECK_CALL + except: + logging.info("All iptables rules cleared") + + +class ClickhouseIntegrationTestsRunner: + + def __init__(self, result_path, params): + self.result_path = result_path + self.params = params + + self.image_versions = self.params['docker_images_with_versions'] + self.shuffle_groups = self.params['shuffle_test_groups'] + self.flaky_check = 'flaky check' in self.params['context_name'] + + def path(self): + return self.result_path + + def base_path(self): + return os.path.join(str(self.result_path), '../') + + def should_skip_tests(self): + return [] + + def get_image_with_version(self, name): + if name in self.image_versions: + return name + ":" + self.image_versions[name] + logging.warn("Cannot find image %s in params list %s", name, self.image_versions) + if ':' not in name: + return name + ":latest" + return name + + def get_single_image_version(self): + name = self.get_images_names()[0] + if name in self.image_versions: + return self.image_versions[name] + logging.warn("Cannot find image %s in params list %s", name, self.image_versions) + return 'latest' + + def shuffle_test_groups(self): + return self.shuffle_groups != 0 + + @staticmethod + def get_images_names(): + return ["yandex/clickhouse-integration-tests-runner", "yandex/clickhouse-mysql-golang-client", + "yandex/clickhouse-mysql-java-client", "yandex/clickhouse-mysql-js-client", + "yandex/clickhouse-mysql-php-client", "yandex/clickhouse-postgresql-java-client", + "yandex/clickhouse-integration-test", "yandex/clickhouse-kerberos-kdc", + "yandex/clickhouse-integration-helper", ] + + + def _can_run_with(self, path, opt): + with open(path, 'r') as script: + for line in script: + if opt in line: + return True + return False + + def _install_clickhouse(self, debs_path): + for package in ('clickhouse-common-static_', 'clickhouse-server_', 'clickhouse-client', 'clickhouse-common-static-dbg_'): # order matters + logging.info("Installing package %s", package) + for f in os.listdir(debs_path): + if package in f: + full_path = os.path.join(debs_path, f) + logging.info("Package found in %s", full_path) + log_name = "install_" + f + ".log" + log_path = os.path.join(str(self.path()), log_name) + with open(log_path, 'w') as log: + cmd = "dpkg -i {}".format(full_path) + logging.info("Executing installation cmd %s", cmd) + retcode = subprocess.Popen(cmd, shell=True, stderr=log, stdout=log).wait() + if retcode == 0: + logging.info("Instsallation of %s successfull", full_path) + else: + raise Exception("Installation of %s failed", full_path) + break + else: + raise Exception("Package with {} not found".format(package)) + logging.info("Unstripping binary") + # logging.info("Unstring %s", subprocess.check_output("eu-unstrip /usr/bin/clickhouse {}".format(CLICKHOUSE_BINARY_PATH), shell=True)) + + logging.info("All packages installed") + os.chmod(CLICKHOUSE_BINARY_PATH, 0o777) + os.chmod(CLICKHOUSE_ODBC_BRIDGE_BINARY_PATH, 0o777) + result_path_bin = os.path.join(str(self.base_path()), "clickhouse") + result_path_bridge = os.path.join(str(self.base_path()), "clickhouse-odbc-bridge") + shutil.copy(CLICKHOUSE_BINARY_PATH, result_path_bin) + shutil.copy(CLICKHOUSE_ODBC_BRIDGE_BINARY_PATH, result_path_bridge) + return None, None + + def _compress_logs(self, path, result_path): + subprocess.check_call("tar czf {} -C {} .".format(result_path, path), shell=True) # STYLE_CHECK_ALLOW_SUBPROCESS_CHECK_CALL + + def _get_all_tests(self, repo_path): + image_cmd = self._get_runner_image_cmd(repo_path) + cmd = "cd {}/tests/integration && ./runner {} ' --setup-plan' | grep '::' | sed 's/ (fixtures used:.*//g' | sed 's/^ *//g' > all_tests.txt".format(repo_path, image_cmd) + logging.info("Getting all tests with cmd '%s'", cmd) + subprocess.check_call(cmd, shell=True) # STYLE_CHECK_ALLOW_SUBPROCESS_CHECK_CALL + + all_tests_file_path = "{}/tests/integration/all_tests.txt".format(repo_path) + if not os.path.isfile(all_tests_file_path) or os.path.getsize(all_tests_file_path) == 0: + raise Exception("There is something wrong with getting all tests list: file '{}' is empty or does not exist.".format(all_tests_file_path)) + + all_tests = [] + with open(all_tests_file_path, "r") as all_tests_file: + for line in all_tests_file: + all_tests.append(line.strip()) + return list(sorted(all_tests)) + + def group_test_by_file(self, tests): + result = {} + for test in tests: + test_file = test.split('::')[0] + if test_file not in result: + result[test_file] = [] + result[test_file].append(test) + return result + + def _update_counters(self, main_counters, current_counters): + for test in current_counters["PASSED"]: + if test not in main_counters["PASSED"]: + if test in main_counters["FAILED"]: + main_counters["FAILED"].remove(test) + if test in main_counters["ERROR"]: + main_counters["ERROR"].remove(test) + main_counters["PASSED"].append(test) + + for state in ("ERROR", "FAILED"): + for test in current_counters[state]: + if test in main_counters["PASSED"]: + continue + if test not in main_counters[state]: + main_counters[state].append(test) + + def _get_runner_image_cmd(self, repo_path): + image_cmd = '' + if self._can_run_with(os.path.join(repo_path, "tests/integration", "runner"), '--docker-image-version'): + for img in self.get_images_names(): + if img == "yandex/clickhouse-integration-tests-runner": + runner_version = self.get_single_image_version() + logging.info("Can run with custom docker image version %s", runner_version) + image_cmd += ' --docker-image-version={} '.format(runner_version) + else: + if self._can_run_with(os.path.join(repo_path, "tests/integration", "runner"), '--docker-compose-images-tags'): + image_cmd += '--docker-compose-images-tags={} '.format(self.get_image_with_version(img)) + else: + image_cmd = '' + logging.info("Cannot run with custom docker image version :(") + return image_cmd + + def run_test_group(self, repo_path, test_group, tests_in_group, num_tries): + image_cmd = self._get_runner_image_cmd(repo_path) + counters = { + "ERROR": [], + "PASSED": [], + "FAILED": [], + } + tests_times = defaultdict(float) + test_group_str = test_group.replace('/', '_').replace('.', '_') + + for i in range(num_tries): + logging.info("Running test group %s for the %s retry", test_group, i) + clear_ip_tables_and_restart_daemons() + + output_path = os.path.join(str(self.path()), "test_output_" + test_group_str + "_" + str(i) + ".log") + log_name = "integration_run_" + test_group_str + "_" + str(i) + ".txt" + log_path = os.path.join(str(self.path()), log_name) + logging.info("Will wait output inside %s", output_path) + + test_names = set([]) + for test_name in tests_in_group: + if test_name not in counters["PASSED"]: + if '[' in test_name: + test_names.add(test_name[:test_name.find('[')]) + else: + test_names.add(test_name) + + test_cmd = ' '.join([test for test in sorted(test_names)]) + cmd = "cd {}/tests/integration && ./runner {} '-ss {} -rfEp --color=no --durations=0 {}' | tee {}".format( + repo_path, image_cmd, test_cmd, _get_deselect_option(self.should_skip_tests()), output_path) + + with open(log_path, 'w') as log: + logging.info("Executing cmd: %s", cmd) + retcode = subprocess.Popen(cmd, shell=True, stderr=log, stdout=log).wait() + if retcode == 0: + logging.info("Run %s group successfully", test_group) + else: + logging.info("Some tests failed") + + if os.path.exists(output_path): + lines = parse_test_results_output(output_path) + new_counters = get_counters(lines) + times_lines = parse_test_times(output_path) + new_tests_times = get_test_times(times_lines) + self._update_counters(counters, new_counters) + for test_name, test_time in new_tests_times.items(): + tests_times[test_name] = test_time + os.remove(output_path) + if len(counters["PASSED"]) == len(tests_in_group): + logging.info("All tests from group %s passed", test_group) + break + if len(counters["PASSED"]) >= 0 and len(counters["FAILED"]) == 0 and len(counters["ERROR"]) == 0: + logging.info("Seems like all tests passed but some of them are skipped or deselected. Ignoring them and finishing group.") + break + else: + for test in tests_in_group: + if test not in counters["PASSED"] and test not in counters["ERROR"] and test not in counters["FAILED"]: + counters["ERROR"].append(test) + + return counters, tests_times, log_name, log_path + + def run_flaky_check(self, repo_path, build_path): + pr_info = self.params['pr_info'] + + # pytest swears, if we require to run some tests which was renamed or deleted + tests_to_run = filter_existing_tests(get_tests_to_run(pr_info), repo_path) + if not tests_to_run: + logging.info("No tests to run found") + return 'success', 'Nothing to run', [('Nothing to run', 'OK')], '' + + self._install_clickhouse(build_path) + logging.info("Found '%s' tests to run", ' '.join(tests_to_run)) + result_state = "success" + description_prefix = "No flaky tests: " + start = time.time() + logging.info("Starting check with retries") + final_retry = 0 + log_paths = [] + for i in range(TRIES_COUNT): + final_retry += 1 + logging.info("Running tests for the %s time", i) + counters, tests_times, log_name, log_path = self.run_test_group(repo_path, "flaky", tests_to_run, 1) + log_paths.append(log_path) + if counters["FAILED"]: + logging.info("Found failed tests: %s", ' '.join(counters["FAILED"])) + description_prefix = "Flaky tests found: " + result_state = "failure" + break + if counters["ERROR"]: + description_prefix = "Flaky tests found: " + logging.info("Found error tests: %s", ' '.join(counters["ERROR"])) + result_state = "error" + break + logging.info("Try is OK, all tests passed, going to clear env") + clear_ip_tables_and_restart_daemons() + logging.info("And going to sleep for some time") + if time.time() - start > MAX_TIME_SECONDS: + logging.info("Timeout reached, going to finish flaky check") + break + time.sleep(5) + + logging.info("Finally all tests done, going to compress test dir") + test_logs = os.path.join(str(self.path()), "./test_dir.tar") + self._compress_logs("{}/tests/integration".format(repo_path), test_logs) + logging.info("Compression finished") + + test_result = [] + for state in ("ERROR", "FAILED", "PASSED"): + if state == "PASSED": + text_state = "OK" + elif state == "FAILED": + text_state = "FAIL" + else: + text_state = state + test_result += [(c + ' (✕' + str(final_retry) + ')', text_state, str(tests_times[c])) for c in counters[state]] + status_text = description_prefix + ', '.join([str(n).lower().replace('failed', 'fail') + ': ' + str(len(c)) for n, c in counters.items()]) + + return result_state, status_text, test_result, [test_logs] + log_paths + + def run_impl(self, repo_path, build_path): + if self.flaky_check: + return self.run_flaky_check(repo_path, build_path) + + self._install_clickhouse(build_path) + logging.info("Dump iptables before run %s", subprocess.check_output("iptables -L", shell=True)) + all_tests = self._get_all_tests(repo_path) + logging.info("Found %s tests first 3 %s", len(all_tests), ' '.join(all_tests[:3])) + grouped_tests = self.group_test_by_file(all_tests) + logging.info("Found %s tests groups", len(grouped_tests)) + + counters = { + "ERROR": [], + "PASSED": [], + "FAILED": [], + } + tests_times = defaultdict(float) + + logs = [] + items_to_run = list(grouped_tests.items()) + + logging.info("Total test groups %s", len(items_to_run)) + if self.shuffle_test_groups(): + logging.info("Shuffling test groups") + random.shuffle(items_to_run) + + for group, tests in items_to_run: + logging.info("Running test group %s countaining %s tests", group, len(tests)) + group_counters, group_test_times, log_name, log_path = self.run_test_group(repo_path, group, tests, MAX_RETRY) + total_tests = 0 + for counter, value in group_counters.items(): + logging.info("Tests from group %s stats, %s count %s", group, counter, len(value)) + counters[counter] += value + logging.info("Totally have %s with status %s", len(counters[counter]), counter) + total_tests += len(counters[counter]) + logging.info("Totally finished tests %s/%s", total_tests, len(all_tests)) + + for test_name, test_time in group_test_times.items(): + tests_times[test_name] = test_time + logs.append(log_path) + if len(counters["FAILED"]) + len(counters["ERROR"]) >= 20: + logging.info("Collected more than 20 failed/error tests, stopping") + break + + logging.info("Finally all tests done, going to compress test dir") + test_logs = os.path.join(str(self.path()), "./test_dir.tar") + self._compress_logs("{}/tests/integration".format(repo_path), test_logs) + logging.info("Compression finished") + + if counters["FAILED"] or counters["ERROR"]: + logging.info("Overall status failure, because we have tests in FAILED or ERROR state") + result_state = "failure" + else: + logging.info("Overall success!") + result_state = "success" + + test_result = [] + for state in ("ERROR", "FAILED", "PASSED"): + if state == "PASSED": + text_state = "OK" + elif state == "FAILED": + text_state = "FAIL" + else: + text_state = state + test_result += [(c, text_state, str(tests_times[c])) for c in counters[state]] + + status_text = "fail: {}, passed: {}, error: {}".format(len(counters['FAILED']), len(counters['PASSED']), len(counters['ERROR'])) + + if not counters or sum(len(counter) for counter in counters.values()) == 0: + status_text = "No tests found for some reason! It's a bug" + result_state = "failure" + + if '(memory)' in self.params['context_name']: + result_state = "success" + + return result_state, status_text, test_result, [test_logs] + logs + +def write_results(results_file, status_file, results, status): + with open(results_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerows(results) + with open(status_file, 'w') as f: + out = csv.writer(f, delimiter='\t') + out.writerow(status) + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') + + repo_path = os.environ.get("CLICKHOUSE_TESTS_REPO_PATH") + build_path = os.environ.get("CLICKHOUSE_TESTS_BUILD_PATH") + result_path = os.environ.get("CLICKHOUSE_TESTS_RESULT_PATH") + params_path = os.environ.get("CLICKHOUSE_TESTS_JSON_PARAMS_PATH") + + params = json.loads(open(params_path, 'r').read()) + runner = ClickhouseIntegrationTestsRunner(result_path, params) + + logging.info("Running tests") + state, description, test_results, logs = runner.run_impl(repo_path, build_path) + logging.info("Tests finished") + + status = (state, description) + out_results_file = os.path.join(str(runner.path()), "test_results.tsv") + out_status_file = os.path.join(str(runner.path()), "check_status.tsv") + write_results(out_results_file, out_status_file, test_results, status) + logging.info("Result written") diff --git a/tests/integration/helpers/cluster.py b/tests/integration/helpers/cluster.py index 14aa2f252c5..3872234d36c 100644 --- a/tests/integration/helpers/cluster.py +++ b/tests/integration/helpers/cluster.py @@ -13,6 +13,7 @@ import subprocess import time import traceback import urllib.parse +import shlex import cassandra.cluster import docker @@ -44,8 +45,8 @@ def _create_env_file(path, variables, fname=DEFAULT_ENV_NAME): f.write("=".join([var, value]) + "\n") return full_path -def run_and_check(args, env=None, shell=False): - res = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, shell=shell) +def run_and_check(args, env=None, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE): + res = subprocess.run(args, stdout=stdout, stderr=stderr, env=env, shell=shell) if res.returncode != 0: # check_call(...) from subprocess does not print stderr, so we do it manually print('Stderr:\n{}\n'.format(res.stderr.decode('utf-8'))) @@ -573,7 +574,7 @@ class ClickHouseCluster: raise Exception("Can't wait Minio to start") def wait_schema_registry_to_start(self, timeout=10): - sr_client = CachedSchemaRegistryClient('http://localhost:8081') + sr_client = CachedSchemaRegistryClient({"url":'http://localhost:8081'}) start = time.time() while time.time() - start < timeout: try: @@ -730,7 +731,7 @@ class ClickHouseCluster: clickhouse_start_cmd = self.base_cmd + ['up', '-d', '--no-recreate'] print(("Trying to create ClickHouse instance by command %s", ' '.join(map(str, clickhouse_start_cmd)))) - subprocess.check_output(clickhouse_start_cmd) + subprocess_check_call(clickhouse_start_cmd) print("ClickHouse instance created") start_deadline = time.time() + 20.0 # seconds @@ -868,6 +869,8 @@ services: cap_add: - SYS_PTRACE - NET_ADMIN + - IPC_LOCK + - SYS_NICE depends_on: {depends_on} user: '{user}' env_file: @@ -1079,6 +1082,23 @@ class ClickHouseInstance: ["bash", "-c", 'grep "{}" /var/log/clickhouse-server/clickhouse-server.log || true'.format(substring)]) return len(result) > 0 + def wait_for_log_line(self, regexp, filename='/var/log/clickhouse-server/clickhouse-server.log', timeout=30, repetitions=1, look_behind_lines=100): + start_time = time.time() + result = self.exec_in_container( + ["bash", "-c", 'timeout {} tail -Fn{} "{}" | grep -Em {} {}'.format(timeout, look_behind_lines, filename, repetitions, shlex.quote(regexp))]) + + # if repetitions>1 grep will return success even if not enough lines were collected, + if repetitions>1 and len(result.splitlines()) < repetitions: + print("wait_for_log_line: those lines were found during {} seconds:".format(timeout)) + print(result) + raise Exception("wait_for_log_line: Not enough repetitions: {} found, while {} expected".format(len(result.splitlines()), repetitions)) + + wait_duration = time.time() - start_time + + print('{} log line matching "{}" appeared in a {} seconds'.format(repetitions, regexp, wait_duration)) + return wait_duration + + def file_exists(self, path): return self.exec_in_container( ["bash", "-c", "echo $(if [ -e '{}' ]; then echo 'yes'; else echo 'no'; fi)".format(path)]) == 'yes\n' diff --git a/tests/integration/helpers/test_tools.py b/tests/integration/helpers/test_tools.py index bbab12e55d4..5fedadd3380 100644 --- a/tests/integration/helpers/test_tools.py +++ b/tests/integration/helpers/test_tools.py @@ -47,20 +47,20 @@ class TSV: def assert_eq_with_retry(instance, query, expectation, retry_count=20, sleep_time=0.5, stdin=None, timeout=None, - settings=None, user=None, ignore_error=False): + settings=None, user=None, ignore_error=False, get_result=lambda x: x): expectation_tsv = TSV(expectation) for i in range(retry_count): try: - if TSV(instance.query(query, user=user, stdin=stdin, timeout=timeout, settings=settings, - ignore_error=ignore_error)) == expectation_tsv: + if TSV(get_result(instance.query(query, user=user, stdin=stdin, timeout=timeout, settings=settings, + ignore_error=ignore_error))) == expectation_tsv: break time.sleep(sleep_time) except Exception as ex: print(("assert_eq_with_retry retry {} exception {}".format(i + 1, ex))) time.sleep(sleep_time) else: - val = TSV(instance.query(query, user=user, stdin=stdin, timeout=timeout, settings=settings, - ignore_error=ignore_error)) + val = TSV(get_result(instance.query(query, user=user, stdin=stdin, timeout=timeout, settings=settings, + ignore_error=ignore_error))) if expectation_tsv != val: raise AssertionError("'{}' != '{}'\n{}".format(expectation_tsv, val, '\n'.join( expectation_tsv.diff(val, n1="expectation", n2="query")))) diff --git a/tests/integration/test_allowed_url_from_config/test.py b/tests/integration/test_allowed_url_from_config/test.py index 6442937c8f4..8001af35913 100644 --- a/tests/integration/test_allowed_url_from_config/test.py +++ b/tests/integration/test_allowed_url_from_config/test.py @@ -5,7 +5,8 @@ cluster = ClickHouseCluster(__file__) node1 = cluster.add_instance('node1', main_configs=['configs/config_with_hosts.xml']) node2 = cluster.add_instance('node2', main_configs=['configs/config_with_only_primary_hosts.xml']) node3 = cluster.add_instance('node3', main_configs=['configs/config_with_only_regexp_hosts.xml']) -node4 = cluster.add_instance('node4', main_configs=['configs/config_without_allowed_hosts.xml']) +node4 = cluster.add_instance('node4', main_configs=[]) # No `remote_url_allow_hosts` at all. +node5 = cluster.add_instance('node5', main_configs=['configs/config_without_allowed_hosts.xml']) node6 = cluster.add_instance('node6', main_configs=['configs/config_for_remote.xml']) node7 = cluster.add_instance('node7', main_configs=['configs/config_for_redirect.xml'], with_hdfs=True) @@ -50,11 +51,25 @@ def test_config_with_only_regexp_hosts(start_cluster): "CREATE TABLE table_test_3_4 (word String) Engine=URL('https://yandex2.ru', S3)") -def test_config_without_allowed_hosts(start_cluster): +def test_config_without_allowed_hosts_section(start_cluster): assert node4.query("CREATE TABLE table_test_4_1 (word String) Engine=URL('https://host:80', CSV)") == "" - assert node4.query("CREATE TABLE table_test_4_2 (word String) Engine=URL('https://host', HDFS)") == "" - assert node4.query("CREATE TABLE table_test_4_3 (word String) Engine=URL('https://yandex.ru', CSV)") == "" - assert node4.query("CREATE TABLE table_test_4_4 (word String) Engine=URL('ftp://something.com', S3)") == "" + assert node4.query("CREATE TABLE table_test_4_2 (word String) Engine=S3('https://host:80/bucket/key', CSV)") == "" + assert node4.query("CREATE TABLE table_test_4_3 (word String) Engine=URL('https://host', HDFS)") == "" + assert node4.query("CREATE TABLE table_test_4_4 (word String) Engine=URL('https://yandex.ru', CSV)") == "" + assert node4.query("CREATE TABLE table_test_4_5 (word String) Engine=URL('ftp://something.com', S3)") == "" + + +def test_config_without_allowed_hosts(start_cluster): + assert "not allowed" in node5.query_and_get_error( + "CREATE TABLE table_test_5_1 (word String) Engine=URL('https://host:80', CSV)") + assert "not allowed" in node5.query_and_get_error( + "CREATE TABLE table_test_5_2 (word String) Engine=S3('https://host:80/bucket/key', CSV)") + assert "not allowed" in node5.query_and_get_error( + "CREATE TABLE table_test_5_3 (word String) Engine=URL('https://host', HDFS)") + assert "not allowed" in node5.query_and_get_error( + "CREATE TABLE table_test_5_4 (word String) Engine=URL('https://yandex.ru', CSV)") + assert "not allowed" in node5.query_and_get_error( + "CREATE TABLE table_test_5_5 (word String) Engine=URL('ftp://something.com', S3)") def test_table_function_remote(start_cluster): diff --git a/tests/integration/test_buffer_profile/__init__.py b/tests/integration/test_buffer_profile/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_buffer_profile/configs/buffer_profile.xml b/tests/integration/test_buffer_profile/configs/buffer_profile.xml new file mode 100644 index 00000000000..6ce6de70e63 --- /dev/null +++ b/tests/integration/test_buffer_profile/configs/buffer_profile.xml @@ -0,0 +1,3 @@ + + buffer_profile + diff --git a/tests/integration/test_buffer_profile/configs/users.d/buffer_profile.xml b/tests/integration/test_buffer_profile/configs/users.d/buffer_profile.xml new file mode 100644 index 00000000000..2edd2b63dc6 --- /dev/null +++ b/tests/integration/test_buffer_profile/configs/users.d/buffer_profile.xml @@ -0,0 +1,8 @@ + + + + 1 + + + + diff --git a/tests/integration/test_buffer_profile/test.py b/tests/integration/test_buffer_profile/test.py new file mode 100644 index 00000000000..ae9220898ab --- /dev/null +++ b/tests/integration/test_buffer_profile/test.py @@ -0,0 +1,54 @@ +# pylint: disable=unused-argument +# pylint: disable=redefined-outer-name +# pylint: disable=line-too-long + +import pytest + +from helpers.cluster import ClickHouseCluster +from helpers.client import QueryRuntimeException + +cluster = ClickHouseCluster(__file__) + +node_default = cluster.add_instance('node_default') +node_buffer_profile = cluster.add_instance('node_buffer_profile', + main_configs=['configs/buffer_profile.xml'], + user_configs=['configs/users.d/buffer_profile.xml']) + +@pytest.fixture(scope='module', autouse=True) +def start_cluster(): + try: + cluster.start() + yield cluster + finally: + cluster.shutdown() + +def bootstrap(node): + node.query(""" + CREATE TABLE data (key Int) Engine=MergeTree() + ORDER BY key + PARTITION BY key % 2; + + CREATE TABLE buffer AS data Engine=Buffer(currentDatabase(), data, + /* settings for manual flush only */ + 1, /* num_layers */ + 10e6, /* min_time, placeholder */ + 10e6, /* max_time, placeholder */ + 0, /* min_rows */ + 10e6, /* max_rows */ + 0, /* min_bytes */ + 80e6 /* max_bytes */ + ); + + INSERT INTO buffer SELECT * FROM numbers(100); + """) + +def test_default_profile(): + bootstrap(node_default) + # flush the buffer + node_default.query('OPTIMIZE TABLE buffer') + +def test_buffer_profile(): + bootstrap(node_buffer_profile) + with pytest.raises(QueryRuntimeException, match='Too many partitions for single INSERT block'): + # flush the buffer + node_buffer_profile.query('OPTIMIZE TABLE buffer') diff --git a/tests/integration/test_distributed_ddl/cluster.py b/tests/integration/test_distributed_ddl/cluster.py index 811eb94bad4..24f11fec547 100644 --- a/tests/integration/test_distributed_ddl/cluster.py +++ b/tests/integration/test_distributed_ddl/cluster.py @@ -10,8 +10,8 @@ from helpers.test_tools import TSV class ClickHouseClusterWithDDLHelpers(ClickHouseCluster): - def __init__(self, base_path, config_dir): - ClickHouseCluster.__init__(self, base_path) + def __init__(self, base_path, config_dir, testcase_name): + ClickHouseCluster.__init__(self, base_path, name=testcase_name) self.test_config_dir = config_dir @@ -104,8 +104,8 @@ class ClickHouseClusterWithDDLHelpers(ClickHouseCluster): def ddl_check_there_are_no_dublicates(instance): query = "SELECT max(c), argMax(q, c) FROM (SELECT lower(query) AS q, count() AS c FROM system.query_log WHERE type=2 AND q LIKE '/* ddl_entry=query-%' GROUP BY query)" rows = instance.query(query) - assert len(rows) > 0 and rows[0][0] == "1", "dublicates on {} {}, query {}".format(instance.name, - instance.ip_address, query) + assert len(rows) > 0 and rows[0][0] == "1", "dublicates on {} {}: {}".format(instance.name, + instance.ip_address, rows) @staticmethod def insert_reliable(instance, query_insert): diff --git a/tests/integration/test_distributed_ddl/test.py b/tests/integration/test_distributed_ddl/test.py index f0e78dfec41..9af27738eed 100755 --- a/tests/integration/test_distributed_ddl/test.py +++ b/tests/integration/test_distributed_ddl/test.py @@ -14,7 +14,7 @@ from .cluster import ClickHouseClusterWithDDLHelpers @pytest.fixture(scope="module", params=["configs", "configs_secure"]) def test_cluster(request): - cluster = ClickHouseClusterWithDDLHelpers(__file__, request.param) + cluster = ClickHouseClusterWithDDLHelpers(__file__, request.param, request.param) try: cluster.prepare() @@ -343,6 +343,12 @@ def test_replicated_without_arguments(test_cluster): "EXCHANGE TABLES test_atomic.rmt AND test_atomic.rmt_renamed ON CLUSTER cluster") assert instance.query("SELECT countDistinct(uuid) from clusterAllReplicas('cluster', 'system', 'databases') WHERE uuid != 0 AND name='test_atomic'") == "1\n" assert instance.query("SELECT countDistinct(uuid) from clusterAllReplicas('cluster', 'system', 'tables') WHERE uuid != 0 AND name='rmt'") == "1\n" + test_cluster.ddl_check_query(instance, + "CREATE TABLE test_atomic.rrmt ON CLUSTER cluster (n UInt64, m UInt64) ENGINE=ReplicatedReplacingMergeTree(m) ORDER BY n") + test_cluster.ddl_check_query(instance, + "CREATE TABLE test_atomic.rsmt ON CLUSTER cluster (n UInt64, m UInt64, k UInt64) ENGINE=ReplicatedSummingMergeTree((m, k)) ORDER BY n") + test_cluster.ddl_check_query(instance, + "CREATE TABLE test_atomic.rvcmt ON CLUSTER cluster (n UInt64, m Int8, k UInt64) ENGINE=ReplicatedVersionedCollapsingMergeTree(m, k) ORDER BY n") test_cluster.ddl_check_query(instance, "DROP DATABASE test_atomic ON CLUSTER cluster") test_cluster.ddl_check_query(instance, "CREATE DATABASE test_ordinary ON CLUSTER cluster ENGINE=Ordinary") diff --git a/tests/integration/test_distributed_ddl/test_replicated_alter.py b/tests/integration/test_distributed_ddl/test_replicated_alter.py index bd95f5660b7..148ad5fca5e 100644 --- a/tests/integration/test_distributed_ddl/test_replicated_alter.py +++ b/tests/integration/test_distributed_ddl/test_replicated_alter.py @@ -12,7 +12,7 @@ from .cluster import ClickHouseClusterWithDDLHelpers @pytest.fixture(scope="module", params=["configs", "configs_secure"]) def test_cluster(request): - cluster = ClickHouseClusterWithDDLHelpers(__file__, request.param) + cluster = ClickHouseClusterWithDDLHelpers(__file__, request.param, "alters_" + request.param) try: # TODO: Fix ON CLUSTER alters when nodes have different configs. Need to canonicalize node identity. diff --git a/tests/integration/test_distributed_ddl_parallel/configs/ddl_a.xml b/tests/integration/test_distributed_ddl_parallel/configs/ddl_a.xml new file mode 100644 index 00000000000..b926f99c687 --- /dev/null +++ b/tests/integration/test_distributed_ddl_parallel/configs/ddl_a.xml @@ -0,0 +1,5 @@ + + + 2 + + diff --git a/tests/integration/test_distributed_ddl_parallel/configs/ddl_b.xml b/tests/integration/test_distributed_ddl_parallel/configs/ddl_b.xml new file mode 100644 index 00000000000..2f038919032 --- /dev/null +++ b/tests/integration/test_distributed_ddl_parallel/configs/ddl_b.xml @@ -0,0 +1,5 @@ + + + 20 + + diff --git a/tests/integration/test_distributed_ddl_parallel/configs/dict.xml b/tests/integration/test_distributed_ddl_parallel/configs/dict.xml index 610d55841a0..d94b3f61dd9 100644 --- a/tests/integration/test_distributed_ddl_parallel/configs/dict.xml +++ b/tests/integration/test_distributed_ddl_parallel/configs/dict.xml @@ -1,26 +1,50 @@ - - slow_dict - - - sleep 7 - TabSeparated - - - - - - - - id - - - value - String - - - - 0 - + + slow_dict_7 + + + sleep 7 + TabSeparated + + + + + + + + id + + + value + String + + + + 0 + + + + slow_dict_3 + + + sleep 3 + TabSeparated + + + + + + + + id + + + value + String + + + + 0 + diff --git a/tests/integration/test_distributed_ddl_parallel/configs/remote_servers.xml b/tests/integration/test_distributed_ddl_parallel/configs/remote_servers.xml index 8ffa9f024d7..eb0ee60186b 100644 --- a/tests/integration/test_distributed_ddl_parallel/configs/remote_servers.xml +++ b/tests/integration/test_distributed_ddl_parallel/configs/remote_servers.xml @@ -1,6 +1,6 @@ - + n1 @@ -13,6 +13,20 @@ 9000 - + + + + + n3 + 9000 + + + + + n4 + 9000 + + + diff --git a/tests/integration/test_distributed_ddl_parallel/test.py b/tests/integration/test_distributed_ddl_parallel/test.py index 96530b111cb..44971ca3d9e 100644 --- a/tests/integration/test_distributed_ddl_parallel/test.py +++ b/tests/integration/test_distributed_ddl_parallel/test.py @@ -10,11 +10,31 @@ from helpers.cluster import ClickHouseCluster cluster = ClickHouseCluster(__file__) -def add_instance(name): +# By default the exceptions that was throwed in threads will be ignored +# (they will not mark the test as failed, only printed to stderr). +# +# Wrap thrading.Thread and re-throw exception on join() +class SafeThread(threading.Thread): + def __init__(self, target): + super().__init__() + self.target = target + self.exception = None + def run(self): + try: + self.target() + except Exception as e: # pylint: disable=broad-except + self.exception = e + def join(self, timeout=None): + super().join(timeout) + if self.exception: + raise self.exception + +def add_instance(name, ddl_config=None): main_configs=[ - 'configs/ddl.xml', 'configs/remote_servers.xml', ] + if ddl_config: + main_configs.append(ddl_config) dictionaries=[ 'configs/dict.xml', ] @@ -24,8 +44,12 @@ def add_instance(name): with_zookeeper=True) initiator = add_instance('initiator') -n1 = add_instance('n1') -n2 = add_instance('n2') +# distributed_ddl.pool_size = 2 +n1 = add_instance('n1', 'configs/ddl_a.xml') +n2 = add_instance('n2', 'configs/ddl_a.xml') +# distributed_ddl.pool_size = 20 +n3 = add_instance('n3', 'configs/ddl_b.xml') +n4 = add_instance('n4', 'configs/ddl_b.xml') @pytest.fixture(scope='module', autouse=True) def start_cluster(): @@ -49,17 +73,32 @@ def longer_then(sec): return inner return wrapper -# It takes 7 seconds to load slow_dict. -def thread_reload_dictionary(): - initiator.query('SYSTEM RELOAD DICTIONARY ON CLUSTER cluster slow_dict') +# It takes 7 seconds to load slow_dict_7. +def execute_reload_dictionary_slow_dict_7(): + initiator.query('SYSTEM RELOAD DICTIONARY ON CLUSTER cluster_a slow_dict_7', settings={ + 'distributed_ddl_task_timeout': 60, + }) +def execute_reload_dictionary_slow_dict_3(): + initiator.query('SYSTEM RELOAD DICTIONARY ON CLUSTER cluster_b slow_dict_3', settings={ + 'distributed_ddl_task_timeout': 60, + }) +def execute_smoke_query(): + initiator.query('DROP DATABASE IF EXISTS foo ON CLUSTER cluster_b', settings={ + 'distributed_ddl_task_timeout': 60, + }) + +def check_log(): + # ensure that none of tasks processed multiple times + for _, instance in list(cluster.instances.items()): + assert not instance.contains_in_log('Coordination::Exception: Node exists') # NOTE: uses inner function to exclude slow start_cluster() from timeout. -def test_dict_load(): +def test_slow_dict_load_7(): @pytest.mark.timeout(10) @longer_then(7) def inner_test(): - initiator.query('SYSTEM RELOAD DICTIONARY slow_dict') + initiator.query('SYSTEM RELOAD DICTIONARY slow_dict_7') inner_test() def test_all_in_parallel(): @@ -68,12 +107,13 @@ def test_all_in_parallel(): def inner_test(): threads = [] for _ in range(2): - threads.append(threading.Thread(target=thread_reload_dictionary)) + threads.append(SafeThread(target=execute_reload_dictionary_slow_dict_7)) for thread in threads: thread.start() for thread in threads: - thread.join() + thread.join(70) inner_test() + check_log() def test_two_in_parallel_two_queued(): @pytest.mark.timeout(19) @@ -81,9 +121,35 @@ def test_two_in_parallel_two_queued(): def inner_test(): threads = [] for _ in range(4): - threads.append(threading.Thread(target=thread_reload_dictionary)) + threads.append(SafeThread(target=execute_reload_dictionary_slow_dict_7)) for thread in threads: thread.start() for thread in threads: - thread.join() + thread.join(70) inner_test() + check_log() + +def test_smoke(): + for _ in range(100): + execute_smoke_query() + check_log() + +def test_smoke_parallel(): + threads = [] + for _ in range(100): + threads.append(SafeThread(target=execute_smoke_query)) + for thread in threads: + thread.start() + for thread in threads: + thread.join(70) + check_log() + +def test_smoke_parallel_dict_reload(): + threads = [] + for _ in range(100): + threads.append(SafeThread(target=execute_reload_dictionary_slow_dict_3)) + for thread in threads: + thread.start() + for thread in threads: + thread.join(70) + check_log() diff --git a/tests/integration/test_distributed_load_balancing/configs/users.xml b/tests/integration/test_distributed_load_balancing/configs/users.xml new file mode 100644 index 00000000000..b2dcdbcd8f3 --- /dev/null +++ b/tests/integration/test_distributed_load_balancing/configs/users.xml @@ -0,0 +1,8 @@ + + + + + 0 + + + diff --git a/tests/integration/test_distributed_load_balancing/test.py b/tests/integration/test_distributed_load_balancing/test.py index df7b74fcae1..d3ac5c132cd 100644 --- a/tests/integration/test_distributed_load_balancing/test.py +++ b/tests/integration/test_distributed_load_balancing/test.py @@ -166,6 +166,7 @@ def test_load_balancing_priority_round_robin(dist_table): def test_distributed_replica_max_ignored_errors(): settings = { + 'use_hedged_requests' : 0, 'load_balancing': 'in_order', 'prefer_localhost_replica': 0, 'connect_timeout': 2, diff --git a/tests/integration/test_distributed_respect_user_timeouts/test.py b/tests/integration/test_distributed_respect_user_timeouts/test.py index c19323b2049..662bf7fa6de 100644 --- a/tests/integration/test_distributed_respect_user_timeouts/test.py +++ b/tests/integration/test_distributed_respect_user_timeouts/test.py @@ -78,6 +78,7 @@ def _check_exception(exception, expected_tries=3): expected_lines = ( 'Code: 209, ' + EXCEPTION_NETWORK + EXCEPTION_TIMEOUT, 'Code: 209, ' + EXCEPTION_NETWORK + EXCEPTION_CONNECT, + EXCEPTION_TIMEOUT, ) assert any(line.startswith(expected) for expected in expected_lines), \ diff --git a/tests/integration/test_drop_replica/test.py b/tests/integration/test_drop_replica/test.py index f3af9dcb980..7d7ad784166 100644 --- a/tests/integration/test_drop_replica/test.py +++ b/tests/integration/test_drop_replica/test.py @@ -49,7 +49,6 @@ def fill_nodes(nodes, shard): cluster = ClickHouseCluster(__file__) - node_1_1 = cluster.add_instance('node_1_1', with_zookeeper=True, main_configs=['configs/remote_servers.xml']) node_1_2 = cluster.add_instance('node_1_2', with_zookeeper=True, main_configs=['configs/remote_servers.xml']) node_1_3 = cluster.add_instance('node_1_3', with_zookeeper=True, main_configs=['configs/remote_servers.xml']) diff --git a/tests/integration/test_force_drop_table/__init__.py b/tests/integration/test_force_drop_table/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_force_drop_table/configs/config.xml b/tests/integration/test_force_drop_table/configs/config.xml new file mode 100644 index 00000000000..e5f133953a6 --- /dev/null +++ b/tests/integration/test_force_drop_table/configs/config.xml @@ -0,0 +1,4 @@ + + 1 + 1 + diff --git a/tests/integration/test_force_drop_table/test.py b/tests/integration/test_force_drop_table/test.py new file mode 100644 index 00000000000..ad8316493e4 --- /dev/null +++ b/tests/integration/test_force_drop_table/test.py @@ -0,0 +1,49 @@ +import pytest + +from helpers.cluster import ClickHouseCluster + +cluster = ClickHouseCluster(__file__) +node = cluster.add_instance('node', main_configs=["configs/config.xml"], with_zookeeper=True) + + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + yield cluster + finally: + cluster.shutdown() + +def create_force_drop_flag(node): + force_drop_flag_path = "/var/lib/clickhouse/flags/force_drop_table" + node.exec_in_container(["bash", "-c", "touch {} && chmod a=rw {}".format(force_drop_flag_path, force_drop_flag_path)], user="root") + +@pytest.mark.parametrize("engine", ['Ordinary', 'Atomic']) +def test_drop_materialized_view(started_cluster, engine): + node.query("CREATE DATABASE d ENGINE={}".format(engine)) + node.query("CREATE TABLE d.rmt (n UInt64) ENGINE=ReplicatedMergeTree('/test/rmt', 'r1') ORDER BY n PARTITION BY n % 2") + node.query("CREATE MATERIALIZED VIEW d.mv (n UInt64, s String) ENGINE=MergeTree ORDER BY n PARTITION BY n % 2 AS SELECT n, toString(n) AS s FROM d.rmt") + node.query("INSERT INTO d.rmt VALUES (1), (2)") + assert "is greater than max" in node.query_and_get_error("DROP TABLE d.rmt") + assert "is greater than max" in node.query_and_get_error("DROP TABLE d.mv") + assert "is greater than max" in node.query_and_get_error("TRUNCATE TABLE d.rmt") + assert "is greater than max" in node.query_and_get_error("TRUNCATE TABLE d.mv") + assert "is greater than max" in node.query_and_get_error("ALTER TABLE d.rmt DROP PARTITION '0'") + assert node.query("SELECT * FROM d.rmt ORDER BY n") == "1\n2\n" + assert node.query("SELECT * FROM d.mv ORDER BY n") == "1\t1\n2\t2\n" + + create_force_drop_flag(node) + node.query("ALTER TABLE d.rmt DROP PARTITION '0'") + assert node.query("SELECT * FROM d.rmt ORDER BY n") == "1\n" + assert "is greater than max" in node.query_and_get_error("ALTER TABLE d.mv DROP PARTITION '0'") + create_force_drop_flag(node) + node.query("ALTER TABLE d.mv DROP PARTITION '0'") + assert node.query("SELECT * FROM d.mv ORDER BY n") == "1\t1\n" + assert "is greater than max" in node.query_and_get_error("DROP TABLE d.rmt SYNC") + create_force_drop_flag(node) + node.query("DROP TABLE d.rmt SYNC") + assert "is greater than max" in node.query_and_get_error("DROP TABLE d.mv SYNC") + create_force_drop_flag(node) + node.query("DROP TABLE d.mv SYNC") + node.query("DROP DATABASE d") + diff --git a/tests/integration/test_graphite_merge_tree/configs/graphite_rollup.xml b/tests/integration/test_graphite_merge_tree/configs/graphite_rollup.xml index 6d1907f3da7..f5206c8827a 100644 --- a/tests/integration/test_graphite_merge_tree/configs/graphite_rollup.xml +++ b/tests/integration/test_graphite_merge_tree/configs/graphite_rollup.xml @@ -94,4 +94,25 @@ + + metric + timestamp + value + updated + + avg + + 0 + 60 + + + 36000 + 600 + + + 72000 + 300 + + + diff --git a/tests/integration/test_graphite_merge_tree/test.py b/tests/integration/test_graphite_merge_tree/test.py index ee8a18f1ca5..7628211551d 100644 --- a/tests/integration/test_graphite_merge_tree/test.py +++ b/tests/integration/test_graphite_merge_tree/test.py @@ -3,6 +3,7 @@ import os.path as p import time import pytest +from helpers.client import QueryRuntimeException from helpers.cluster import ClickHouseCluster from helpers.test_tools import TSV @@ -442,3 +443,20 @@ SELECT * FROM test.graphite; ''') assert TSV(result) == TSV(expected) + + +def test_wrong_rollup_config(graphite_table): + with pytest.raises(QueryRuntimeException) as exc: + q(''' +CREATE TABLE test.graphite_not_created + (metric String, value Float64, timestamp UInt32, date Date, updated UInt32) + ENGINE = GraphiteMergeTree('graphite_rollup_wrong_age_precision') + PARTITION BY toYYYYMM(date) + ORDER BY (metric, timestamp) + SETTINGS index_granularity=1; + ''') + + # The order of retentions is not guaranteed + assert ("age and precision should only grow up: " in str(exc.value)) + assert ("36000:600" in str(exc.value)) + assert ("72000:300" in str(exc.value)) diff --git a/tests/integration/test_hedged_requests/__init__.py b/tests/integration/test_hedged_requests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_hedged_requests/configs/remote_servers.xml b/tests/integration/test_hedged_requests/configs/remote_servers.xml new file mode 100644 index 00000000000..9d753ca2b6a --- /dev/null +++ b/tests/integration/test_hedged_requests/configs/remote_servers.xml @@ -0,0 +1,22 @@ + + + + + true + + node_1 + 9000 + + + node_2 + 9000 + + + node_3 + 9000 + + + + + + diff --git a/tests/integration/test_hedged_requests/configs/users.xml b/tests/integration/test_hedged_requests/configs/users.xml new file mode 100644 index 00000000000..509d3d12508 --- /dev/null +++ b/tests/integration/test_hedged_requests/configs/users.xml @@ -0,0 +1,10 @@ + + + + + in_order + 100 + 2 + + + diff --git a/tests/integration/test_hedged_requests/configs/users1.xml b/tests/integration/test_hedged_requests/configs/users1.xml new file mode 100644 index 00000000000..2a54396feca --- /dev/null +++ b/tests/integration/test_hedged_requests/configs/users1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/integration/test_hedged_requests/test.py b/tests/integration/test_hedged_requests/test.py new file mode 100644 index 00000000000..0c0155ff9a2 --- /dev/null +++ b/tests/integration/test_hedged_requests/test.py @@ -0,0 +1,320 @@ +import os +import sys +import time + +import pytest + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from helpers.cluster import ClickHouseCluster +from helpers.network import PartitionManager +from helpers.test_tools import TSV + +cluster = ClickHouseCluster(__file__) +NODES = {'node_' + str(i): None for i in (1, 2, 3)} + +NODES['node'] = None + +sleep_time = 30 + +@pytest.fixture(scope="module") +def started_cluster(): + NODES['node'] = cluster.add_instance( + 'node', with_zookeeper=True, stay_alive=True, main_configs=['configs/remote_servers.xml'], user_configs=['configs/users.xml']) + + for name in NODES: + if name != 'node': + NODES[name] = cluster.add_instance(name, with_zookeeper=True, user_configs=['configs/users1.xml']) + + try: + cluster.start() + + for node_id, node in list(NODES.items()): + node.query('''CREATE TABLE replicated (id UInt32, date Date) ENGINE = + ReplicatedMergeTree('/clickhouse/tables/replicated', '{}') ORDER BY id PARTITION BY toYYYYMM(date)'''.format(node_id)) + + NODES['node'].query('''CREATE TABLE distributed (id UInt32, date Date) ENGINE = + Distributed('test_cluster', 'default', 'replicated')''') + + NODES['node'].query("INSERT INTO distributed select number, toDate(number) from numbers(100);") + + yield cluster + + finally: + cluster.shutdown() + + +config = ''' + + + {sleep_in_send_tables_status} + {sleep_in_send_data} + + +''' + + +def check_query(expected_replica, receive_timeout=300): + NODES['node'].restart_clickhouse() + + # Without hedged requests select query will last more than 30 seconds, + # with hedged requests it will last just around 1-2 second + + start = time.time() + result = NODES['node'].query("SELECT hostName(), id FROM distributed ORDER BY id LIMIT 1 SETTINGS receive_timeout={}".format(receive_timeout)); + query_time = time.time() - start + + assert TSV(result) == TSV(expected_replica + "\t0") + + print("Query time:", query_time) + assert query_time < 10 + + +def check_settings(node_name, sleep_in_send_tables_status, sleep_in_send_data): + attempts = 0 + while attempts < 1000: + setting1 = NODES[node_name].http_query("SELECT value FROM system.settings WHERE name='sleep_in_send_tables_status'") + setting2 = NODES[node_name].http_query("SELECT value FROM system.settings WHERE name='sleep_in_send_data'") + if int(setting1) == sleep_in_send_tables_status and int(setting2) == sleep_in_send_data: + return + time.sleep(0.1) + attempts += 1 + + assert attempts < 1000 + + +def test_stuck_replica(started_cluster): + cluster.pause_container("node_1") + + check_query(expected_replica="node_2") + + result = NODES['node'].query("SELECT slowdowns_count FROM system.clusters WHERE cluster='test_cluster' and host_name='node_1'") + + assert TSV(result) == TSV("1") + + result = NODES['node'].query("SELECT hostName(), id FROM distributed ORDER BY id LIMIT 1"); + + assert TSV(result) == TSV("node_2\t0") + + # Check that we didn't choose node_1 first again and slowdowns_count didn't increase. + result = NODES['node'].query("SELECT slowdowns_count FROM system.clusters WHERE cluster='test_cluster' and host_name='node_1'") + + assert TSV(result) == TSV("1") + + cluster.unpause_container("node_1") + + +def test_long_query(started_cluster): + # Restart to reset pool states. + NODES['node'].restart_clickhouse() + + result = NODES['node'].query("select hostName(), max(id + sleep(1.5)) from distributed settings max_block_size = 1, max_threads = 1;") + assert TSV(result) == TSV("node_1\t99") + + NODES['node'].query("INSERT INTO distributed select number, toDate(number) from numbers(100);") + + +def test_send_table_status_sleep(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=sleep_time, sleep_in_send_data=0)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=0)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=0)) + + check_settings('node_1', sleep_time, 0) + check_settings('node_2', 0, 0) + check_settings('node_3', 0, 0) + + check_query(expected_replica="node_2") + + +def test_send_table_status_sleep2(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=sleep_time, sleep_in_send_data=0)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=sleep_time, sleep_in_send_data=0)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=0)) + + check_settings('node_1', sleep_time, 0) + check_settings('node_2', sleep_time, 0) + check_settings('node_3', 0, 0) + + check_query(expected_replica="node_3") + + +def test_send_data(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=0)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=0)) + + check_settings('node_1', 0, sleep_time) + check_settings('node_2', 0, 0) + check_settings('node_3', 0, 0) + + check_query(expected_replica="node_2") + + +def test_send_data2(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=0)) + + check_settings('node_1', 0, sleep_time) + check_settings('node_2', 0, sleep_time) + check_settings('node_3', 0, 0) + + check_query(expected_replica="node_3") + + +def test_combination1(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=sleep_time, sleep_in_send_data=0)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=0)) + + check_settings('node_1', sleep_time, 0) + check_settings('node_2', 0, sleep_time) + check_settings('node_3', 0, 0) + + check_query(expected_replica="node_3") + + +def test_combination2(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=sleep_time, sleep_in_send_data=0)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=0)) + + check_settings('node_1', 0, sleep_time) + check_settings('node_2', sleep_time, 0) + check_settings('node_3', 0, 0) + + check_query(expected_replica="node_3") + + +def test_combination3(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=1, sleep_in_send_data=0)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + check_settings('node_1', 0, sleep_time) + check_settings('node_2', 1, 0) + check_settings('node_3', 0, sleep_time) + + check_query(expected_replica="node_2") + + +def test_combination4(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=1, sleep_in_send_data=sleep_time)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=1, sleep_in_send_data=0)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=2, sleep_in_send_data=0)) + + check_settings('node_1', 1, sleep_time) + check_settings('node_2', 1, 0) + check_settings('node_3', 2, 0) + + check_query(expected_replica="node_2") + + +def test_receive_timeout1(started_cluster): + # Check the situation when first two replicas get receive timeout + # in establishing connection, but the third replica is ok. + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=3, sleep_in_send_data=0)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=3, sleep_in_send_data=0)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=1)) + + check_settings('node_1', 3, 0) + check_settings('node_2', 3, 0) + check_settings('node_3', 0, 1) + + check_query(expected_replica="node_3", receive_timeout=2) + + +def test_receive_timeout2(started_cluster): + # Check the situation when first replica get receive timeout + # in packet receiving but there are replicas in process of + # connection establishing. + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=4)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=2, sleep_in_send_data=0)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=2, sleep_in_send_data=0)) + + check_settings('node_1', 0, 4) + check_settings('node_2', 2, 0) + check_settings('node_3', 2, 0) + + check_query(expected_replica="node_2", receive_timeout=3) + diff --git a/tests/integration/test_hedged_requests_parallel/__init__.py b/tests/integration/test_hedged_requests_parallel/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_hedged_requests_parallel/configs/remote_servers.xml b/tests/integration/test_hedged_requests_parallel/configs/remote_servers.xml new file mode 100644 index 00000000000..63767185b34 --- /dev/null +++ b/tests/integration/test_hedged_requests_parallel/configs/remote_servers.xml @@ -0,0 +1,26 @@ + + + + + true + + node_1 + 9000 + + + node_2 + 9000 + + + node_3 + 9000 + + + node_4 + 9000 + + + + + + diff --git a/tests/integration/test_hedged_requests_parallel/configs/users.xml b/tests/integration/test_hedged_requests_parallel/configs/users.xml new file mode 100644 index 00000000000..af9d6d96e60 --- /dev/null +++ b/tests/integration/test_hedged_requests_parallel/configs/users.xml @@ -0,0 +1,11 @@ + + + + + in_order + 2 + 100 + 2 + + + diff --git a/tests/integration/test_hedged_requests_parallel/configs/users1.xml b/tests/integration/test_hedged_requests_parallel/configs/users1.xml new file mode 100644 index 00000000000..2a54396feca --- /dev/null +++ b/tests/integration/test_hedged_requests_parallel/configs/users1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/integration/test_hedged_requests_parallel/test.py b/tests/integration/test_hedged_requests_parallel/test.py new file mode 100644 index 00000000000..17db4af5d41 --- /dev/null +++ b/tests/integration/test_hedged_requests_parallel/test.py @@ -0,0 +1,158 @@ +import os +import sys +import time + +import pytest + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from helpers.cluster import ClickHouseCluster +from helpers.network import PartitionManager + +cluster = ClickHouseCluster(__file__) + +NODES = {'node_' + str(i): None for i in (1, 2, 3, 4)} +NODES['node'] = None + +sleep_time = 30 + +@pytest.fixture(scope="module") +def started_cluster(): + cluster = ClickHouseCluster(__file__) + NODES['node'] = cluster.add_instance( + 'node', with_zookeeper=True, stay_alive=True, main_configs=['configs/remote_servers.xml'], user_configs=['configs/users.xml']) + + for name in NODES: + if name != 'node': + NODES[name] = cluster.add_instance(name, with_zookeeper=True, user_configs=['configs/users1.xml']) + + try: + cluster.start() + + for node_id, node in list(NODES.items()): + node.query('''CREATE TABLE replicated (id UInt32, date Date) ENGINE = + ReplicatedMergeTree('/clickhouse/tables/replicated', '{}') ORDER BY id PARTITION BY toYYYYMM(date)'''.format(node_id)) + + NODES['node'].query('''CREATE TABLE distributed (id UInt32, date Date) ENGINE = + Distributed('test_cluster', 'default', 'replicated')''') + + NODES['node'].query("INSERT INTO distributed VALUES (1, '2020-01-01'), (2, '2020-01-02')") + + yield cluster + + finally: + cluster.shutdown() + + +config = ''' + + + {sleep_in_send_tables_status} + {sleep_in_send_data} + + +''' + + +def check_query(): + NODES['node'].restart_clickhouse() + + # Without hedged requests select query will last more than 30 seconds, + # with hedged requests it will last just around 1-2 second + + start = time.time() + NODES['node'].query("SELECT * FROM distributed"); + query_time = time.time() - start + print("Query time:", query_time) + + assert query_time < 5 + + +def check_settings(node_name, sleep_in_send_tables_status, sleep_in_send_data): + attempts = 0 + while attempts < 1000: + setting1 = NODES[node_name].http_query("SELECT value FROM system.settings WHERE name='sleep_in_send_tables_status'") + setting2 = NODES[node_name].http_query("SELECT value FROM system.settings WHERE name='sleep_in_send_data'") + if int(setting1) == sleep_in_send_tables_status and int(setting2) == sleep_in_send_data: + return + time.sleep(0.1) + attempts += 1 + + assert attempts < 1000 + + +def test_send_table_status_sleep(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=sleep_time, sleep_in_send_data=0)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=sleep_time, sleep_in_send_data=0)) + + check_settings('node_1', sleep_time, 0) + check_settings('node_2', sleep_time, 0) + + check_query() + + +def test_send_data(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + check_settings('node_1', 0, sleep_time) + check_settings('node_2', 0, sleep_time) + + check_query() + + +def test_combination1(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=1, sleep_in_send_data=0)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=1, sleep_in_send_data=0)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + check_settings('node_1', 1, 0) + check_settings('node_2', 1, 0) + check_settings('node_3', 0, sleep_time) + + check_query() + + +def test_combination2(started_cluster): + NODES['node_1'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + NODES['node_2'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=1, sleep_in_send_data=0)) + + NODES['node_3'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=0, sleep_in_send_data=sleep_time)) + + NODES['node_4'].replace_config( + '/etc/clickhouse-server/users.d/users1.xml', + config.format(sleep_in_send_tables_status=1, sleep_in_send_data=0)) + + + check_settings('node_1', 0, sleep_time) + check_settings('node_2', 1, 0) + check_settings('node_3', 0, sleep_time) + check_settings('node_4', 1, 0) + + check_query() + diff --git a/tests/integration/test_insert_distributed_async_extra_dirs/__init__.py b/tests/integration/test_insert_distributed_async_extra_dirs/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_insert_distributed_async_extra_dirs/configs/remote_servers.xml b/tests/integration/test_insert_distributed_async_extra_dirs/configs/remote_servers.xml new file mode 100644 index 00000000000..1df72377ce6 --- /dev/null +++ b/tests/integration/test_insert_distributed_async_extra_dirs/configs/remote_servers.xml @@ -0,0 +1,13 @@ + + + + + + node + 9000 + + + + + + diff --git a/tests/integration/test_insert_distributed_async_extra_dirs/test.py b/tests/integration/test_insert_distributed_async_extra_dirs/test.py new file mode 100644 index 00000000000..8365fce298d --- /dev/null +++ b/tests/integration/test_insert_distributed_async_extra_dirs/test.py @@ -0,0 +1,43 @@ +# pylint: disable=unused-argument +# pylint: disable=redefined-outer-name +# pylint: disable=line-too-long + +import pytest + +from helpers.cluster import ClickHouseCluster + +cluster = ClickHouseCluster(__file__) + +node = cluster.add_instance('node', main_configs=['configs/remote_servers.xml'], stay_alive=True) + +@pytest.fixture(scope='module', autouse=True) +def start_cluster(): + try: + cluster.start() + yield cluster + finally: + cluster.shutdown() + +def test_insert_distributed_async_send_success(): + node.query('CREATE TABLE data (key Int, value String) Engine=Null()') + node.query(""" + CREATE TABLE dist AS data + Engine=Distributed( + test_cluster, + currentDatabase(), + data, + key + ) + """) + + node.exec_in_container(['bash', '-c', 'mkdir /var/lib/clickhouse/data/default/dist/shard10000_replica10000']) + node.exec_in_container(['bash', '-c', 'touch /var/lib/clickhouse/data/default/dist/shard10000_replica10000/1.bin']) + + node.exec_in_container(['bash', '-c', 'mkdir /var/lib/clickhouse/data/default/dist/shard1_replica10000']) + node.exec_in_container(['bash', '-c', 'touch /var/lib/clickhouse/data/default/dist/shard1_replica10000/1.bin']) + + node.exec_in_container(['bash', '-c', 'mkdir /var/lib/clickhouse/data/default/dist/shard10000_replica1']) + node.exec_in_container(['bash', '-c', 'touch /var/lib/clickhouse/data/default/dist/shard10000_replica1/1.bin']) + + # will check that clickhouse-server is alive + node.restart_clickhouse() diff --git a/tests/integration/test_jbod_balancer/__init__.py b/tests/integration/test_jbod_balancer/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_jbod_balancer/configs/config.d/storage_configuration.xml b/tests/integration/test_jbod_balancer/configs/config.d/storage_configuration.xml new file mode 100644 index 00000000000..62b0ffacaf0 --- /dev/null +++ b/tests/integration/test_jbod_balancer/configs/config.d/storage_configuration.xml @@ -0,0 +1,29 @@ + + + + + 1024 + + + /jbod1/ + + + /jbod2/ + + + /jbod3/ + + + + + + + jbod1 + jbod2 + jbod3 + + + + + + diff --git a/tests/integration/test_jbod_balancer/test.py b/tests/integration/test_jbod_balancer/test.py new file mode 100644 index 00000000000..abc6a0bff11 --- /dev/null +++ b/tests/integration/test_jbod_balancer/test.py @@ -0,0 +1,182 @@ +import json +import random +import re +import string +import threading +import time +from multiprocessing.dummy import Pool + +import pytest +from helpers.client import QueryRuntimeException +from helpers.cluster import ClickHouseCluster + +cluster = ClickHouseCluster(__file__) + +node1 = cluster.add_instance( + "node1", + main_configs=["configs/config.d/storage_configuration.xml",], + with_zookeeper=True, + stay_alive=True, + tmpfs=["/jbod1:size=100M", "/jbod2:size=100M", "/jbod3:size=100M"], + macros={"shard": 0, "replica": 1}, +) + + +node2 = cluster.add_instance( + "node2", + main_configs=["configs/config.d/storage_configuration.xml"], + with_zookeeper=True, + stay_alive=True, + tmpfs=["/jbod1:size=100M", "/jbod2:size=100M", "/jbod3:size=100M"], + macros={"shard": 0, "replica": 2}, +) + + +@pytest.fixture(scope="module") +def start_cluster(): + try: + cluster.start() + yield cluster + + finally: + cluster.shutdown() + + +def check_balance(node, table): + + partitions = node.query( + """ + WITH + arraySort(groupArray(c)) AS array_c, + arrayEnumerate(array_c) AS array_i, + sum(c) AS sum_c, + count() AS n, + if(sum_c = 0, 0, (((2. * arraySum(arrayMap((c, i) -> (c * i), array_c, array_i))) / n) / sum_c) - (((n + 1) * 1.) / n)) AS gini + SELECT + partition + FROM + ( + SELECT + partition, + disk_name, + sum(bytes_on_disk) AS c + FROM system.parts + WHERE active AND level > 0 AND disk_name like 'jbod%' AND table = '{}' + GROUP BY + partition, disk_name + ) + GROUP BY partition + HAVING gini < 0.1 + """.format( + table + ) + ).splitlines() + + assert set(partitions) == set(["0", "1"]) + + +def test_jbod_balanced_merge(start_cluster): + try: + node1.query( + """ + CREATE TABLE tbl (p UInt8, d String) + ENGINE = MergeTree + PARTITION BY p + ORDER BY tuple() + SETTINGS + storage_policy = 'jbod', + min_bytes_to_rebalance_partition_over_jbod = 1024, + max_bytes_to_merge_at_max_space_in_pool = 4096 + """ + ) + node1.query("create table tmp1 as tbl") + node1.query("create table tmp2 as tbl") + + for i in range(200): + # around 1k per block + node1.query( + "insert into tbl select randConstant() % 2, randomPrintableASCII(16) from numbers(50)" + ) + node1.query( + "insert into tmp1 select randConstant() % 2, randomPrintableASCII(16) from numbers(50)" + ) + node1.query( + "insert into tmp2 select randConstant() % 2, randomPrintableASCII(16) from numbers(50)" + ) + + time.sleep(1) + + check_balance(node1, "tbl") + + finally: + node1.query(f"DROP TABLE IF EXISTS tbl SYNC") + node1.query(f"DROP TABLE IF EXISTS tmp1 SYNC") + node1.query(f"DROP TABLE IF EXISTS tmp2 SYNC") + + +def test_replicated_balanced_merge_fetch(start_cluster): + try: + for i, node in enumerate([node1, node2]): + node.query( + """ + CREATE TABLE tbl (p UInt8, d String) + ENGINE = ReplicatedMergeTree('/clickhouse/tbl', '{}') + PARTITION BY p + ORDER BY tuple() + SETTINGS + storage_policy = 'jbod', + old_parts_lifetime = 1, + cleanup_delay_period = 1, + cleanup_delay_period_random_add = 2, + min_bytes_to_rebalance_partition_over_jbod = 1024, + max_bytes_to_merge_at_max_space_in_pool = 4096 + """.format( + i + ) + ) + + node.query( + """ + CREATE TABLE tmp1 (p UInt8, d String) + ENGINE = MergeTree + PARTITION BY p + ORDER BY tuple() + SETTINGS + storage_policy = 'jbod', + min_bytes_to_rebalance_partition_over_jbod = 1024, + max_bytes_to_merge_at_max_space_in_pool = 4096 + """ + ) + + node.query("create table tmp2 as tmp1") + + node2.query("alter table tbl modify setting always_fetch_merged_part = 1") + + for i in range(200): + # around 1k per block + node1.query( + "insert into tbl select randConstant() % 2, randomPrintableASCII(16) from numbers(50)" + ) + node1.query( + "insert into tmp1 select randConstant() % 2, randomPrintableASCII(16) from numbers(50)" + ) + node1.query( + "insert into tmp2 select randConstant() % 2, randomPrintableASCII(16) from numbers(50)" + ) + node2.query( + "insert into tmp1 select randConstant() % 2, randomPrintableASCII(16) from numbers(50)" + ) + node2.query( + "insert into tmp2 select randConstant() % 2, randomPrintableASCII(16) from numbers(50)" + ) + + node2.query("SYSTEM SYNC REPLICA tbl", timeout=10) + + check_balance(node1, "tbl") + check_balance(node2, "tbl") + + finally: + for node in [node1, node2]: + node.query("DROP TABLE IF EXISTS tbl SYNC") + node.query("DROP TABLE IF EXISTS tmp1 SYNC") + node.query("DROP TABLE IF EXISTS tmp2 SYNC") diff --git a/tests/integration/test_materialize_mysql_database/materialize_with_ddl.py b/tests/integration/test_materialize_mysql_database/materialize_with_ddl.py index c9be2387fc7..f906c309443 100644 --- a/tests/integration/test_materialize_mysql_database/materialize_with_ddl.py +++ b/tests/integration/test_materialize_mysql_database/materialize_with_ddl.py @@ -471,12 +471,14 @@ def select_without_columns(clickhouse_node, mysql_node, service_name): mysql_node.query("CREATE DATABASE db") mysql_node.query("CREATE TABLE db.t (a INT PRIMARY KEY, b INT)") clickhouse_node.query( - "CREATE DATABASE db ENGINE = MaterializeMySQL('{}:3306', 'db', 'root', 'clickhouse')".format(service_name)) + "CREATE DATABASE db ENGINE = MaterializeMySQL('{}:3306', 'db', 'root', 'clickhouse') SETTINGS max_flush_data_time = 100000".format(service_name)) check_query(clickhouse_node, "SHOW TABLES FROM db FORMAT TSV", "t\n") clickhouse_node.query("SYSTEM STOP MERGES db.t") clickhouse_node.query("CREATE VIEW v AS SELECT * FROM db.t") mysql_node.query("INSERT INTO db.t VALUES (1, 1), (2, 2)") - mysql_node.query("DELETE FROM db.t WHERE a=2;") + mysql_node.query("DELETE FROM db.t WHERE a = 2;") + # We need to execute a DDL for flush data buffer + mysql_node.query("CREATE TABLE db.temporary(a INT PRIMARY KEY, b INT)") optimize_on_insert = clickhouse_node.query("SELECT value FROM system.settings WHERE name='optimize_on_insert'").strip() if optimize_on_insert == "0": @@ -577,13 +579,13 @@ def err_sync_user_privs_with_materialize_mysql_database(clickhouse_node, mysql_n mysql_node.query("DROP USER 'test'@'%'") -def restore_instance_mysql_connections(clickhouse_node, pm, action='DROP'): +def restore_instance_mysql_connections(clickhouse_node, pm, action='REJECT'): pm._check_instance(clickhouse_node) pm._delete_rule({'source': clickhouse_node.ip_address, 'destination_port': 3306, 'action': action}) pm._delete_rule({'destination': clickhouse_node.ip_address, 'source_port': 3306, 'action': action}) time.sleep(5) -def drop_instance_mysql_connections(clickhouse_node, pm, action='DROP'): +def drop_instance_mysql_connections(clickhouse_node, pm, action='REJECT'): pm._check_instance(clickhouse_node) pm._add_rule({'source': clickhouse_node.ip_address, 'destination_port': 3306, 'action': action}) pm._add_rule({'destination': clickhouse_node.ip_address, 'source_port': 3306, 'action': action}) @@ -616,8 +618,6 @@ def network_partition_test(clickhouse_node, mysql_node, service_name): restore_instance_mysql_connections(clickhouse_node, pm) - clickhouse_node.query("DETACH DATABASE test_database") - clickhouse_node.query("ATTACH DATABASE test_database") check_query(clickhouse_node, "SELECT * FROM test_database.test_table FORMAT TSV", '1\n') clickhouse_node.query( @@ -635,16 +635,27 @@ def network_partition_test(clickhouse_node, mysql_node, service_name): def mysql_kill_sync_thread_restore_test(clickhouse_node, mysql_node, service_name): clickhouse_node.query("DROP DATABASE IF EXISTS test_database;") + clickhouse_node.query("DROP DATABASE IF EXISTS test_database_auto;") + mysql_node.query("DROP DATABASE IF EXISTS test_database;") mysql_node.query("CREATE DATABASE test_database;") mysql_node.query("CREATE TABLE test_database.test_table ( `id` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB;") mysql_node.query("INSERT INTO test_database.test_table VALUES (1)") - clickhouse_node.query("CREATE DATABASE test_database ENGINE = MaterializeMySQL('{}:3306', 'test_database', 'root', 'clickhouse')".format(service_name)) + mysql_node.query("DROP DATABASE IF EXISTS test_database_auto;") + mysql_node.query("CREATE DATABASE test_database_auto;") + mysql_node.query("CREATE TABLE test_database_auto.test_table ( `id` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB;") + mysql_node.query("INSERT INTO test_database_auto.test_table VALUES (11)") + + clickhouse_node.query("CREATE DATABASE test_database ENGINE = MaterializeMySQL('{}:3306', 'test_database', 'root', 'clickhouse') SETTINGS max_wait_time_when_mysql_unavailable=-1".format(service_name)) + clickhouse_node.query("CREATE DATABASE test_database_auto ENGINE = MaterializeMySQL('{}:3306', 'test_database_auto', 'root', 'clickhouse')".format(service_name)) + check_query(clickhouse_node, "SELECT * FROM test_database.test_table FORMAT TSV", '1\n') + check_query(clickhouse_node, "SELECT * FROM test_database_auto.test_table FORMAT TSV", '11\n') get_sync_id_query = "select id from information_schema.processlist where STATE='Master has sent all binlog to slave; waiting for more updates'" result = mysql_node.query_and_get_data(get_sync_id_query) + assert len(result) == 2 for row in result: row_result = {} @@ -656,7 +667,7 @@ def mysql_kill_sync_thread_restore_test(clickhouse_node, mysql_node, service_nam # When you use KILL, a thread-specific kill flag is set for the thread. In most cases, it might take some time for the thread to die because the kill flag is checked only at specific intervals: time.sleep(3) clickhouse_node.query("SELECT * FROM test_database.test_table") - assert "Cannot read all data" in str(exception.value) + assert "Cannot read all data" in str(exception.value) clickhouse_node.query("DETACH DATABASE test_database") clickhouse_node.query("ATTACH DATABASE test_database") @@ -665,8 +676,13 @@ def mysql_kill_sync_thread_restore_test(clickhouse_node, mysql_node, service_nam mysql_node.query("INSERT INTO test_database.test_table VALUES (2)") check_query(clickhouse_node, "SELECT * FROM test_database.test_table ORDER BY id FORMAT TSV", '1\n2\n') + mysql_node.query("INSERT INTO test_database_auto.test_table VALUES (12)") + check_query(clickhouse_node, "SELECT * FROM test_database_auto.test_table ORDER BY id FORMAT TSV", '11\n12\n') + clickhouse_node.query("DROP DATABASE test_database") + clickhouse_node.query("DROP DATABASE test_database_auto") mysql_node.query("DROP DATABASE test_database") + mysql_node.query("DROP DATABASE test_database_auto") def mysql_killed_while_insert(clickhouse_node, mysql_node, service_name): @@ -687,10 +703,9 @@ def mysql_killed_while_insert(clickhouse_node, mysql_node, service_name): run_and_check( ['docker-compose', '-p', mysql_node.project_name, '-f', mysql_node.docker_compose, 'stop']) finally: - with pytest.raises(QueryRuntimeException) as execption: + with pytest.raises(QueryRuntimeException) as exception: time.sleep(5) clickhouse_node.query("SELECT count() FROM kill_mysql_while_insert.test") - assert "Master maybe lost." in str(execption.value) run_and_check( ['docker-compose', '-p', mysql_node.project_name, '-f', mysql_node.docker_compose, 'start']) diff --git a/tests/integration/test_materialize_mysql_database/test.py b/tests/integration/test_materialize_mysql_database/test.py index e55772d9e1d..ced9a978d02 100644 --- a/tests/integration/test_materialize_mysql_database/test.py +++ b/tests/integration/test_materialize_mysql_database/test.py @@ -37,6 +37,12 @@ class MySQLNodeInstance: self.docker_compose = docker_compose self.project_name = project_name + self.base_dir = p.dirname(__file__) + self.instances_dir = p.join(self.base_dir, '_instances_mysql') + if not os.path.exists(self.instances_dir): + os.mkdir(self.instances_dir) + self.docker_logs_path = p.join(self.instances_dir, 'docker_mysql.log') + def alloc_connection(self): if self.mysql_connection is None: @@ -71,10 +77,28 @@ class MySQLNodeInstance: cursor.execute(executio_query) return cursor.fetchall() + def start_and_wait(self): + run_and_check(['docker-compose', + '-p', cluster.project_name, + '-f', self.docker_compose, + 'up', '--no-recreate', '-d', + ]) + self.wait_mysql_to_start(120) + def close(self): if self.mysql_connection is not None: self.mysql_connection.close() + with open(self.docker_logs_path, "w+") as f: + try: + run_and_check([ + 'docker-compose', + '-p', cluster.project_name, + '-f', self.docker_compose, 'logs', + ], stdout=f) + except Exception as e: + print("Unable to get logs from docker mysql.") + def wait_mysql_to_start(self, timeout=60): start = time.time() while time.time() - start < timeout: @@ -95,9 +119,7 @@ def started_mysql_5_7(): mysql_node = MySQLNodeInstance('root', 'clickhouse', '127.0.0.1', 3308, docker_compose) try: - run_and_check( - ['docker-compose', '-p', cluster.project_name, '-f', docker_compose, 'up', '--no-recreate', '-d']) - mysql_node.wait_mysql_to_start(120) + mysql_node.start_and_wait() yield mysql_node finally: mysql_node.close() @@ -111,9 +133,7 @@ def started_mysql_8_0(): mysql_node = MySQLNodeInstance('root', 'clickhouse', '127.0.0.1', 33308, docker_compose) try: - run_and_check( - ['docker-compose', '-p', cluster.project_name, '-f', docker_compose, 'up', '--no-recreate', '-d']) - mysql_node.wait_mysql_to_start(120) + mysql_node.start_and_wait() yield mysql_node finally: mysql_node.close() diff --git a/tests/integration/test_mysql_protocol/test.py b/tests/integration/test_mysql_protocol/test.py index 9532d4b8ba2..7f7d59674bc 100644 --- a/tests/integration/test_mysql_protocol/test.py +++ b/tests/integration/test_mysql_protocol/test.py @@ -217,7 +217,7 @@ def test_mysql_replacement_query(mysql_client, server_address): --password=123 -e "select database();" '''.format(host=server_address, port=server_port), demux=True) assert code == 0 - assert stdout.decode() == 'database()\ndefault\n' + assert stdout.decode() == 'DATABASE()\ndefault\n' code, (stdout, stderr) = mysql_client.exec_run(''' mysql --protocol tcp -h {host} -P {port} default -u default diff --git a/tests/integration/test_odbc_interaction/test.py b/tests/integration/test_odbc_interaction/test.py index 084fc407f39..6bb6a6ee777 100644 --- a/tests/integration/test_odbc_interaction/test.py +++ b/tests/integration/test_odbc_interaction/test.py @@ -342,3 +342,25 @@ def test_bridge_dies_with_parent(started_cluster): assert clickhouse_pid is None assert bridge_pid is None + + +def test_odbc_postgres_date_data_type(started_cluster): + conn = get_postgres_conn(); + cursor = conn.cursor() + cursor.execute("CREATE TABLE IF NOT EXISTS clickhouse.test_date (column1 integer, column2 date)") + + cursor.execute("INSERT INTO clickhouse.test_date VALUES (1, '2020-12-01')") + cursor.execute("INSERT INTO clickhouse.test_date VALUES (2, '2020-12-02')") + cursor.execute("INSERT INTO clickhouse.test_date VALUES (3, '2020-12-03')") + conn.commit() + + node1.query( + ''' + CREATE TABLE test_date (column1 UInt64, column2 Date) + ENGINE=ODBC('DSN=postgresql_odbc; Servername=postgre-sql.local', 'clickhouse', 'test_date')''') + + expected = '1\t2020-12-01\n2\t2020-12-02\n3\t2020-12-03\n' + result = node1.query('SELECT * FROM test_date'); + assert(result == expected) + + diff --git a/tests/integration/test_quota/configs/users.d/assign_myquota.xml b/tests/integration/test_quota/configs/users.d/assign_myquota_to_default_user.xml similarity index 100% rename from tests/integration/test_quota/configs/users.d/assign_myquota.xml rename to tests/integration/test_quota/configs/users.d/assign_myquota_to_default_user.xml diff --git a/tests/integration/test_quota/configs/users.d/quota.xml b/tests/integration/test_quota/configs/users.d/myquota.xml similarity index 100% rename from tests/integration/test_quota/configs/users.d/quota.xml rename to tests/integration/test_quota/configs/users.d/myquota.xml diff --git a/tests/integration/test_quota/configs/users.d/user_with_no_quota.xml b/tests/integration/test_quota/configs/users.d/user_with_no_quota.xml new file mode 100644 index 00000000000..70f51cfff43 --- /dev/null +++ b/tests/integration/test_quota/configs/users.d/user_with_no_quota.xml @@ -0,0 +1,10 @@ + + + + + + ::/0 + + + + diff --git a/tests/integration/test_quota/test.py b/tests/integration/test_quota/test.py index 84454159a58..4374f46a39f 100644 --- a/tests/integration/test_quota/test.py +++ b/tests/integration/test_quota/test.py @@ -7,9 +7,10 @@ from helpers.cluster import ClickHouseCluster from helpers.test_tools import assert_eq_with_retry, TSV cluster = ClickHouseCluster(__file__) -instance = cluster.add_instance('instance', user_configs=["configs/users.d/assign_myquota.xml", +instance = cluster.add_instance('instance', user_configs=["configs/users.d/assign_myquota_to_default_user.xml", "configs/users.d/drop_default_quota.xml", - "configs/users.d/quota.xml"]) + "configs/users.d/myquota.xml", + "configs/users.d/user_with_no_quota.xml"]) def check_system_quotas(canonical): @@ -49,9 +50,11 @@ def system_quotas_usage(canonical): def copy_quota_xml(local_file_name, reload_immediately=True): script_dir = os.path.dirname(os.path.realpath(__file__)) instance.copy_file_to_container(os.path.join(script_dir, local_file_name), - '/etc/clickhouse-server/users.d/quota.xml') + '/etc/clickhouse-server/users.d/myquota.xml') if reload_immediately: - instance.query("SYSTEM RELOAD CONFIG") + # We use the special user 'user_with_no_quota' here because + # we don't want SYSTEM RELOAD CONFIG to mess our quota consuming checks. + instance.query("SYSTEM RELOAD CONFIG", user='user_with_no_quota') @pytest.fixture(scope="module", autouse=True) @@ -71,12 +74,12 @@ def started_cluster(): @pytest.fixture(autouse=True) def reset_quotas_and_usage_info(): try: - yield - finally: - copy_quota_xml('simpliest.xml') # To reset usage info. instance.query("DROP QUOTA IF EXISTS qA, qB") copy_quota_xml('simpliest.xml') # To reset usage info. copy_quota_xml('normal_limits.xml') + yield + finally: + pass def test_quota_from_users_xml(): @@ -379,4 +382,34 @@ def test_query_inserts(): instance.query("INSERT INTO test_table values(1)") system_quota_usage( - [["myQuota", "default", 31556952, 1, 1000, 0, 500, 1, 500, 0, "\\N", 0, "\\N", 0, "\\N", 0, 1000, 0, "\\N", "\\N"]]) \ No newline at end of file + [["myQuota", "default", 31556952, 1, 1000, 0, 500, 1, 500, 0, "\\N", 0, "\\N", 0, "\\N", 0, 1000, 0, "\\N", "\\N"]]) + +def test_consumption_of_show_tables(): + assert instance.query("SHOW TABLES") == "test_table\n" + assert re.match( + "myQuota\\tdefault\\t.*\\t31556952\\t1\\t1000\\t1\\t500\\t0\\t500\\t0\\t\\\\N\\t1\\t\\\\N.*", + instance.query("SHOW QUOTA")) + +def test_consumption_of_show_databases(): + assert instance.query("SHOW DATABASES") == "default\nsystem\n" + assert re.match( + "myQuota\\tdefault\\t.*\\t31556952\\t1\\t1000\\t1\\t500\\t0\\t500\\t0\\t\\\\N\\t2\\t\\\\N.*", + instance.query("SHOW QUOTA")) + +def test_consumption_of_show_clusters(): + assert len(instance.query("SHOW CLUSTERS")) > 0 + assert re.match( + "myQuota\\tdefault\\t.*\\t31556952\\t1\\t1000\\t1\\t500\\t0\\t500\\t0\\t\\\\N.*", + instance.query("SHOW QUOTA")) + +def test_consumption_of_show_processlist(): + instance.query("SHOW PROCESSLIST") + assert re.match( + "myQuota\\tdefault\\t.*\\t31556952\\t1\\t1000\\t1\\t500\\t0\\t500\\t0\\t\\\\N\\t0\\t\\\\N.*", + instance.query("SHOW QUOTA")) + +def test_consumption_of_show_privileges(): + assert len(instance.query("SHOW PRIVILEGES")) > 0 + assert re.match( + "myQuota\\tdefault\\t.*\\t31556952\\t1\\t1000\\t1\\t500\\t0\\t500\\t0\\t\\\\N.*", + instance.query("SHOW QUOTA")) diff --git a/tests/integration/test_reload_auxiliary_zookeepers/test.py b/tests/integration/test_reload_auxiliary_zookeepers/test.py index 92c66c890fc..1b14408bc12 100644 --- a/tests/integration/test_reload_auxiliary_zookeepers/test.py +++ b/tests/integration/test_reload_auxiliary_zookeepers/test.py @@ -62,8 +62,7 @@ def test_reload_auxiliary_zookeepers(start_cluster): """ node.replace_config("/etc/clickhouse-server/conf.d/zookeeper.xml", new_config) - # Hopefully it has finished the configuration reload - time.sleep(2) + node.query("SYSTEM RELOAD CONFIG") node.query( "ALTER TABLE simple2 FETCH PARTITION '2020-08-27' FROM 'zookeeper2:/clickhouse/tables/0/simple';" @@ -81,7 +80,7 @@ def test_reload_auxiliary_zookeepers(start_cluster): """ node.replace_config("/etc/clickhouse-server/conf.d/zookeeper.xml", new_config) - time.sleep(2) + node.query("SYSTEM RELOAD CONFIG") with pytest.raises(QueryRuntimeException): node.query( "ALTER TABLE simple2 FETCH PARTITION '2020-08-27' FROM 'zookeeper2:/clickhouse/tables/0/simple';" diff --git a/tests/integration/test_reload_zookeeper/test.py b/tests/integration/test_reload_zookeeper/test.py index 82c47f4ec9e..1fe0ab13a7f 100644 --- a/tests/integration/test_reload_zookeeper/test.py +++ b/tests/integration/test_reload_zookeeper/test.py @@ -74,6 +74,9 @@ def test_reload_zookeeper(start_cluster): with pytest.raises(QueryRuntimeException): node.query("SELECT COUNT() FROM test_table", settings={"select_sequential_consistency" : 1}) + def get_active_zk_connections(): + return str(node.exec_in_container(['bash', '-c', 'lsof -a -i4 -i6 -itcp -w | grep 2181 | grep ESTABLISHED | wc -l'], privileged=True, user='root')).strip() + ## set config to zoo2, server will be normal new_config = """ @@ -89,5 +92,10 @@ def test_reload_zookeeper(start_cluster): node.replace_config("/etc/clickhouse-server/conf.d/zookeeper.xml", new_config) node.query("SYSTEM RELOAD CONFIG") + active_zk_connections = get_active_zk_connections() + assert active_zk_connections == '1', "Total connections to ZooKeeper not equal to 1, {}".format(active_zk_connections) + assert_eq_with_retry(node, "SELECT COUNT() FROM test_table", '1000', retry_count=120, sleep_time=0.5) + active_zk_connections = get_active_zk_connections() + assert active_zk_connections == '1', "Total connections to ZooKeeper not equal to 1, {}".format(active_zk_connections) diff --git a/tests/integration/test_replace_partition/test.py b/tests/integration/test_replace_partition/test.py index 06e7f4be82b..d30a038825f 100644 --- a/tests/integration/test_replace_partition/test.py +++ b/tests/integration/test_replace_partition/test.py @@ -1,3 +1,8 @@ +# pylint: disable=line-too-long +# pylint: disable=unused-argument +# pylint: disable=redefined-outer-name: + +import time import pytest from helpers.cluster import ClickHouseCluster @@ -13,13 +18,13 @@ def _fill_nodes(nodes, shard): node.query( ''' CREATE DATABASE test; - + CREATE TABLE real_table(date Date, id UInt32, dummy UInt32) ENGINE = MergeTree(date, id, 8192); - + CREATE TABLE other_table(date Date, id UInt32, dummy UInt32) ENGINE = MergeTree(date, id, 8192); - + CREATE TABLE test_table(date Date, id UInt32, dummy UInt32) ENGINE = ReplicatedMergeTree('/clickhouse/tables/test{shard}/replicated', '{replica}', date, id, 8192); '''.format(shard=shard, replica=node.name)) @@ -97,12 +102,13 @@ def test_drop_failover(drop_failover): # Drop partition on source node node3.query("ALTER TABLE test_table DROP PARTITION 201706") - # connection restored + # Wait few seconds for connection to zookeeper to be restored + time.sleep(5) - node4.query_with_retry("select last_exception from system.replication_queue where type = 'REPLACE_RANGE'", - check_callback=lambda x: 'Not found part' not in x, sleep_time=1) - assert 'Not found part' not in node4.query( - "select last_exception from system.replication_queue where type = 'REPLACE_RANGE'") + msg = node4.query_with_retry( + "select last_exception from system.replication_queue where type = 'REPLACE_RANGE'", + check_callback=lambda x: 'Not found part' not in x, sleep_time=1) + assert 'Not found part' not in msg assert_eq_with_retry(node4, "SELECT id FROM test_table order by id", '') @@ -151,8 +157,11 @@ def test_replace_after_replace_failover(replace_after_replace_failover): assert_eq_with_retry(node5, "SELECT id FROM test_table order by id", '333') - node6.query_with_retry("select last_exception from system.replication_queue where type = 'REPLACE_RANGE'", - check_callback=lambda x: 'Not found part' not in x, sleep_time=1) - assert 'Not found part' not in node6.query( - "select last_exception from system.replication_queue where type = 'REPLACE_RANGE'") + # Wait few seconds for connection to zookeeper to be restored + time.sleep(5) + + msg = node6.query_with_retry( + "select last_exception from system.replication_queue where type = 'REPLACE_RANGE'", + check_callback=lambda x: 'Not found part' not in x, sleep_time=1) + assert 'Not found part' not in msg assert_eq_with_retry(node6, "SELECT id FROM test_table order by id", '333') diff --git a/tests/integration/test_replicated_database/__init__.py b/tests/integration/test_replicated_database/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_replicated_database/configs/config.xml b/tests/integration/test_replicated_database/configs/config.xml new file mode 100644 index 00000000000..ebceee3aa5c --- /dev/null +++ b/tests/integration/test_replicated_database/configs/config.xml @@ -0,0 +1,34 @@ + + 10 + + + + + true + + main_node + 9000 + + + dummy_node + 9000 + + + competing_node + 9000 + + + + true + + snapshotting_node + 9000 + + + snapshot_recovering_node + 9000 + + + + + diff --git a/tests/integration/test_replicated_database/configs/settings.xml b/tests/integration/test_replicated_database/configs/settings.xml new file mode 100644 index 00000000000..e0f7e8691e6 --- /dev/null +++ b/tests/integration/test_replicated_database/configs/settings.xml @@ -0,0 +1,12 @@ + + + + 1 + + + + + default + + + diff --git a/tests/integration/test_replicated_database/test.py b/tests/integration/test_replicated_database/test.py new file mode 100644 index 00000000000..99e7d6077f8 --- /dev/null +++ b/tests/integration/test_replicated_database/test.py @@ -0,0 +1,278 @@ +import time +import re +import pytest + +from helpers.cluster import ClickHouseCluster +from helpers.test_tools import assert_eq_with_retry, assert_logs_contain +from helpers.network import PartitionManager + +cluster = ClickHouseCluster(__file__) + +main_node = cluster.add_instance('main_node', main_configs=['configs/config.xml'], user_configs=['configs/settings.xml'], with_zookeeper=True, stay_alive=True, macros={"shard": 1, "replica": 1}) +dummy_node = cluster.add_instance('dummy_node', main_configs=['configs/config.xml'], user_configs=['configs/settings.xml'], with_zookeeper=True, stay_alive=True, macros={"shard": 1, "replica": 2}) +competing_node = cluster.add_instance('competing_node', main_configs=['configs/config.xml'], user_configs=['configs/settings.xml'], with_zookeeper=True, macros={"shard": 1, "replica": 3}) +snapshotting_node = cluster.add_instance('snapshotting_node', main_configs=['configs/config.xml'], user_configs=['configs/settings.xml'], with_zookeeper=True, macros={"shard": 2, "replica": 1}) +snapshot_recovering_node = cluster.add_instance('snapshot_recovering_node', main_configs=['configs/config.xml'], user_configs=['configs/settings.xml'], with_zookeeper=True, macros={"shard": 2, "replica": 2}) + +all_nodes = [main_node, dummy_node, competing_node, snapshotting_node, snapshot_recovering_node] + +uuid_regex = re.compile("[0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12}") +def assert_create_query(nodes, table_name, expected): + replace_uuid = lambda x: re.sub(uuid_regex, "uuid", x) + query = "show create table {}".format(table_name) + for node in nodes: + assert_eq_with_retry(node, query, expected, get_result=replace_uuid) + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + main_node.query("CREATE DATABASE testdb ENGINE = Replicated('/clickhouse/databases/test1', 'shard1', 'replica1');") + dummy_node.query("CREATE DATABASE testdb ENGINE = Replicated('/clickhouse/databases/test1', 'shard1', 'replica2');") + yield cluster + + finally: + cluster.shutdown() + +def test_create_replicated_table(started_cluster): + assert "Old syntax is not allowed" in \ + main_node.query_and_get_error("CREATE TABLE testdb.replicated_table (d Date, k UInt64, i32 Int32) ENGINE=ReplicatedMergeTree('/test/tmp', 'r', d, k, 8192);") + + main_node.query("CREATE TABLE testdb.replicated_table (d Date, k UInt64, i32 Int32) ENGINE=ReplicatedMergeTree ORDER BY k PARTITION BY toYYYYMM(d);") + + expected = "CREATE TABLE testdb.replicated_table\\n(\\n `d` Date,\\n `k` UInt64,\\n `i32` Int32\\n)\\n" \ + "ENGINE = ReplicatedMergeTree(\\'/clickhouse/tables/uuid/{shard}\\', \\'{replica}\\')\\n" \ + "PARTITION BY toYYYYMM(d)\\nORDER BY k\\nSETTINGS index_granularity = 8192" + assert_create_query([main_node, dummy_node], "testdb.replicated_table", expected) + # assert without replacing uuid + assert main_node.query("show create testdb.replicated_table") == dummy_node.query("show create testdb.replicated_table") + +@pytest.mark.parametrize("engine", ['MergeTree', 'ReplicatedMergeTree']) +def test_simple_alter_table(started_cluster, engine): + # test_simple_alter_table + name = "testdb.alter_test_{}".format(engine) + main_node.query("CREATE TABLE {} " + "(CounterID UInt32, StartDate Date, UserID UInt32, VisitID UInt32, NestedColumn Nested(A UInt8, S String), ToDrop UInt32) " + "ENGINE = {} PARTITION BY StartDate ORDER BY (CounterID, StartDate, intHash32(UserID), VisitID);".format(name, engine)) + main_node.query("ALTER TABLE {} ADD COLUMN Added0 UInt32;".format(name)) + main_node.query("ALTER TABLE {} ADD COLUMN Added2 UInt32;".format(name)) + main_node.query("ALTER TABLE {} ADD COLUMN Added1 UInt32 AFTER Added0;".format(name)) + main_node.query("ALTER TABLE {} ADD COLUMN AddedNested1 Nested(A UInt32, B UInt64) AFTER Added2;".format(name)) + main_node.query("ALTER TABLE {} ADD COLUMN AddedNested1.C Array(String) AFTER AddedNested1.B;".format(name)) + main_node.query("ALTER TABLE {} ADD COLUMN AddedNested2 Nested(A UInt32, B UInt64) AFTER AddedNested1;".format(name)) + + full_engine = engine if not "Replicated" in engine else engine + "(\\'/clickhouse/tables/uuid/{shard}\\', \\'{replica}\\')" + expected = "CREATE TABLE {}\\n(\\n `CounterID` UInt32,\\n `StartDate` Date,\\n `UserID` UInt32,\\n" \ + " `VisitID` UInt32,\\n `NestedColumn.A` Array(UInt8),\\n `NestedColumn.S` Array(String),\\n" \ + " `ToDrop` UInt32,\\n `Added0` UInt32,\\n `Added1` UInt32,\\n `Added2` UInt32,\\n" \ + " `AddedNested1.A` Array(UInt32),\\n `AddedNested1.B` Array(UInt64),\\n `AddedNested1.C` Array(String),\\n" \ + " `AddedNested2.A` Array(UInt32),\\n `AddedNested2.B` Array(UInt64)\\n)\\n" \ + "ENGINE = {}\\nPARTITION BY StartDate\\nORDER BY (CounterID, StartDate, intHash32(UserID), VisitID)\\n" \ + "SETTINGS index_granularity = 8192".format(name, full_engine) + + assert_create_query([main_node, dummy_node], name, expected) + + # test_create_replica_after_delay + competing_node.query("CREATE DATABASE IF NOT EXISTS testdb ENGINE = Replicated('/clickhouse/databases/test1', 'shard1', 'replica3');") + + name = "testdb.alter_test_{}".format(engine) + main_node.query("ALTER TABLE {} ADD COLUMN Added3 UInt32;".format(name)) + main_node.query("ALTER TABLE {} DROP COLUMN AddedNested1;".format(name)) + main_node.query("ALTER TABLE {} RENAME COLUMN Added1 TO AddedNested1;".format(name)) + + full_engine = engine if not "Replicated" in engine else engine + "(\\'/clickhouse/tables/uuid/{shard}\\', \\'{replica}\\')" + expected = "CREATE TABLE {}\\n(\\n `CounterID` UInt32,\\n `StartDate` Date,\\n `UserID` UInt32,\\n" \ + " `VisitID` UInt32,\\n `NestedColumn.A` Array(UInt8),\\n `NestedColumn.S` Array(String),\\n" \ + " `ToDrop` UInt32,\\n `Added0` UInt32,\\n `AddedNested1` UInt32,\\n `Added2` UInt32,\\n" \ + " `AddedNested2.A` Array(UInt32),\\n `AddedNested2.B` Array(UInt64),\\n `Added3` UInt32\\n)\\n" \ + "ENGINE = {}\\nPARTITION BY StartDate\\nORDER BY (CounterID, StartDate, intHash32(UserID), VisitID)\\n" \ + "SETTINGS index_granularity = 8192".format(name, full_engine) + + assert_create_query([main_node, dummy_node, competing_node], name, expected) + + +def test_alters_from_different_replicas(started_cluster): + # test_alters_from_different_replicas + competing_node.query("CREATE DATABASE IF NOT EXISTS testdb ENGINE = Replicated('/clickhouse/databases/test1', 'shard1', 'replica3');") + + main_node.query("CREATE TABLE testdb.concurrent_test " + "(CounterID UInt32, StartDate Date, UserID UInt32, VisitID UInt32, NestedColumn Nested(A UInt8, S String), ToDrop UInt32) " + "ENGINE = MergeTree(StartDate, intHash32(UserID), (CounterID, StartDate, intHash32(UserID), VisitID), 8192);") + + main_node.query("CREATE TABLE testdb.dist AS testdb.concurrent_test ENGINE = Distributed(cluster, testdb, concurrent_test, CounterID)") + + dummy_node.stop_clickhouse(kill=True) + + settings = {"distributed_ddl_task_timeout": 10} + assert "There are 1 unfinished hosts (0 of them are currently active)" in \ + competing_node.query_and_get_error("ALTER TABLE testdb.concurrent_test ADD COLUMN Added0 UInt32;", settings=settings) + dummy_node.start_clickhouse() + main_node.query("ALTER TABLE testdb.concurrent_test ADD COLUMN Added2 UInt32;") + competing_node.query("ALTER TABLE testdb.concurrent_test ADD COLUMN Added1 UInt32 AFTER Added0;") + main_node.query("ALTER TABLE testdb.concurrent_test ADD COLUMN AddedNested1 Nested(A UInt32, B UInt64) AFTER Added2;") + competing_node.query("ALTER TABLE testdb.concurrent_test ADD COLUMN AddedNested1.C Array(String) AFTER AddedNested1.B;") + main_node.query("ALTER TABLE testdb.concurrent_test ADD COLUMN AddedNested2 Nested(A UInt32, B UInt64) AFTER AddedNested1;") + + expected = "CREATE TABLE testdb.concurrent_test\\n(\\n `CounterID` UInt32,\\n `StartDate` Date,\\n `UserID` UInt32,\\n" \ + " `VisitID` UInt32,\\n `NestedColumn.A` Array(UInt8),\\n `NestedColumn.S` Array(String),\\n `ToDrop` UInt32,\\n" \ + " `Added0` UInt32,\\n `Added1` UInt32,\\n `Added2` UInt32,\\n `AddedNested1.A` Array(UInt32),\\n" \ + " `AddedNested1.B` Array(UInt64),\\n `AddedNested1.C` Array(String),\\n `AddedNested2.A` Array(UInt32),\\n" \ + " `AddedNested2.B` Array(UInt64)\\n)\\n" \ + "ENGINE = MergeTree(StartDate, intHash32(UserID), (CounterID, StartDate, intHash32(UserID), VisitID), 8192)" + + assert_create_query([main_node, competing_node], "testdb.concurrent_test", expected) + + # test_create_replica_after_delay + main_node.query("DROP TABLE testdb.concurrent_test") + main_node.query("CREATE TABLE testdb.concurrent_test " + "(CounterID UInt32, StartDate Date, UserID UInt32, VisitID UInt32, NestedColumn Nested(A UInt8, S String), ToDrop UInt32) " + "ENGINE = ReplicatedMergeTree ORDER BY CounterID;") + + expected = "CREATE TABLE testdb.concurrent_test\\n(\\n `CounterID` UInt32,\\n `StartDate` Date,\\n `UserID` UInt32,\\n" \ + " `VisitID` UInt32,\\n `NestedColumn.A` Array(UInt8),\\n `NestedColumn.S` Array(String),\\n `ToDrop` UInt32\\n)\\n" \ + "ENGINE = ReplicatedMergeTree(\\'/clickhouse/tables/uuid/{shard}\\', \\'{replica}\\')\\nORDER BY CounterID\\nSETTINGS index_granularity = 8192" + + assert_create_query([main_node, competing_node], "testdb.concurrent_test", expected) + + main_node.query("INSERT INTO testdb.dist (CounterID, StartDate, UserID) SELECT number, addDays(toDate('2020-02-02'), number), intHash32(number) FROM numbers(10)") + + # test_replica_restart + main_node.restart_clickhouse() + + expected = "CREATE TABLE testdb.concurrent_test\\n(\\n `CounterID` UInt32,\\n `StartDate` Date,\\n `UserID` UInt32,\\n" \ + " `VisitID` UInt32,\\n `NestedColumn.A` Array(UInt8),\\n `NestedColumn.S` Array(String),\\n `ToDrop` UInt32\\n)\\n" \ + "ENGINE = ReplicatedMergeTree(\\'/clickhouse/tables/uuid/{shard}\\', \\'{replica}\\')\\nORDER BY CounterID\\nSETTINGS index_granularity = 8192" + + + # test_snapshot_and_snapshot_recover + snapshotting_node.query("CREATE DATABASE testdb ENGINE = Replicated('/clickhouse/databases/test1', 'shard2', 'replica1');") + snapshot_recovering_node.query("CREATE DATABASE testdb ENGINE = Replicated('/clickhouse/databases/test1', 'shard2', 'replica2');") + assert_create_query(all_nodes, "testdb.concurrent_test", expected) + + main_node.query("SYSTEM FLUSH DISTRIBUTED testdb.dist") + main_node.query("ALTER TABLE testdb.concurrent_test UPDATE StartDate = addYears(StartDate, 1) WHERE 1") + res = main_node.query("ALTER TABLE testdb.concurrent_test DELETE WHERE UserID % 2") + assert "shard1|replica1" in res and "shard1|replica2" in res and "shard1|replica3" in res + assert "shard2|replica1" in res and "shard2|replica2" in res + + expected = "1\t1\tmain_node\n" \ + "1\t2\tdummy_node\n" \ + "1\t3\tcompeting_node\n" \ + "2\t1\tsnapshotting_node\n" \ + "2\t2\tsnapshot_recovering_node\n" + assert main_node.query("SELECT shard_num, replica_num, host_name FROM system.clusters WHERE cluster='testdb'") == expected + + # test_drop_and_create_replica + main_node.query("DROP DATABASE testdb SYNC") + main_node.query("CREATE DATABASE testdb ENGINE = Replicated('/clickhouse/databases/test1', 'shard1', 'replica1');") + + expected = "CREATE TABLE testdb.concurrent_test\\n(\\n `CounterID` UInt32,\\n `StartDate` Date,\\n `UserID` UInt32,\\n" \ + " `VisitID` UInt32,\\n `NestedColumn.A` Array(UInt8),\\n `NestedColumn.S` Array(String),\\n `ToDrop` UInt32\\n)\\n" \ + "ENGINE = ReplicatedMergeTree(\\'/clickhouse/tables/uuid/{shard}\\', \\'{replica}\\')\\nORDER BY CounterID\\nSETTINGS index_granularity = 8192" + + assert_create_query([main_node, competing_node], "testdb.concurrent_test", expected) + assert_create_query(all_nodes, "testdb.concurrent_test", expected) + + for node in all_nodes: + node.query("SYSTEM SYNC REPLICA testdb.concurrent_test") + + expected = "0\t2021-02-02\t4249604106\n" \ + "1\t2021-02-03\t1343103100\n" \ + "4\t2021-02-06\t3902320246\n" \ + "7\t2021-02-09\t3844986530\n" \ + "9\t2021-02-11\t1241149650\n" + + assert_eq_with_retry(dummy_node, "SELECT CounterID, StartDate, UserID FROM testdb.dist ORDER BY CounterID", expected) + +def test_recover_staled_replica(started_cluster): + main_node.query("CREATE DATABASE recover ENGINE = Replicated('/clickhouse/databases/recover', 'shard1', 'replica1');") + started_cluster.get_kazoo_client('zoo1').set('/clickhouse/databases/recover/logs_to_keep', b'10') + dummy_node.query("CREATE DATABASE recover ENGINE = Replicated('/clickhouse/databases/recover', 'shard1', 'replica2');") + + settings = {"distributed_ddl_task_timeout": 0} + main_node.query("CREATE TABLE recover.t1 (n int) ENGINE=Memory", settings=settings) + dummy_node.query("CREATE TABLE recover.t2 (s String) ENGINE=Memory", settings=settings) + main_node.query("CREATE TABLE recover.mt1 (n int) ENGINE=MergeTree order by n", settings=settings) + dummy_node.query("CREATE TABLE recover.mt2 (n int) ENGINE=MergeTree order by n", settings=settings) + main_node.query("CREATE TABLE recover.rmt1 (n int) ENGINE=ReplicatedMergeTree order by n", settings=settings) + dummy_node.query("CREATE TABLE recover.rmt2 (n int) ENGINE=ReplicatedMergeTree order by n", settings=settings) + main_node.query("CREATE TABLE recover.rmt3 (n int) ENGINE=ReplicatedMergeTree order by n", settings=settings) + dummy_node.query("CREATE TABLE recover.rmt5 (n int) ENGINE=ReplicatedMergeTree order by n", settings=settings) + main_node.query("CREATE DICTIONARY recover.d1 (n int DEFAULT 0, m int DEFAULT 1) PRIMARY KEY n SOURCE(CLICKHOUSE(HOST 'localhost' PORT 9000 USER 'default' TABLE 'rmt1' PASSWORD '' DB 'recover')) LIFETIME(MIN 1 MAX 10) LAYOUT(FLAT())") + dummy_node.query("CREATE DICTIONARY recover.d2 (n int DEFAULT 0, m int DEFAULT 1) PRIMARY KEY n SOURCE(CLICKHOUSE(HOST 'localhost' PORT 9000 USER 'default' TABLE 'rmt2' PASSWORD '' DB 'recover')) LIFETIME(MIN 1 MAX 10) LAYOUT(FLAT())") + + for table in ['t1', 't2', 'mt1', 'mt2', 'rmt1', 'rmt2', 'rmt3', 'rmt5']: + main_node.query("INSERT INTO recover.{} VALUES (42)".format(table)) + for table in ['t1', 't2', 'mt1', 'mt2']: + dummy_node.query("INSERT INTO recover.{} VALUES (42)".format(table)) + for table in ['rmt1', 'rmt2', 'rmt3', 'rmt5']: + main_node.query("SYSTEM SYNC REPLICA recover.{}".format(table)) + + with PartitionManager() as pm: + pm.drop_instance_zk_connections(dummy_node) + dummy_node.query_and_get_error("RENAME TABLE recover.t1 TO recover.m1") + main_node.query("RENAME TABLE recover.t1 TO recover.m1", settings=settings) + main_node.query("ALTER TABLE recover.mt1 ADD COLUMN m int", settings=settings) + main_node.query("ALTER TABLE recover.rmt1 ADD COLUMN m int", settings=settings) + main_node.query("RENAME TABLE recover.rmt3 TO recover.rmt4", settings=settings) + main_node.query("DROP TABLE recover.rmt5", settings=settings) + main_node.query("DROP DICTIONARY recover.d2", settings=settings) + main_node.query("CREATE DICTIONARY recover.d2 (n int DEFAULT 0, m int DEFAULT 1) PRIMARY KEY n SOURCE(CLICKHOUSE(HOST 'localhost' PORT 9000 USER 'default' TABLE 'rmt1' PASSWORD '' DB 'recover')) LIFETIME(MIN 1 MAX 10) LAYOUT(FLAT());", settings=settings) + + main_node.query("CREATE TABLE recover.tmp AS recover.m1", settings=settings) + main_node.query("DROP TABLE recover.tmp", settings=settings) + main_node.query("CREATE TABLE recover.tmp AS recover.m1", settings=settings) + main_node.query("DROP TABLE recover.tmp", settings=settings) + main_node.query("CREATE TABLE recover.tmp AS recover.m1", settings=settings) + main_node.query("DROP TABLE recover.tmp", settings=settings) + main_node.query("CREATE TABLE recover.tmp AS recover.m1", settings=settings) + + assert main_node.query("SELECT name FROM system.tables WHERE database='recover' ORDER BY name") == "d1\nd2\nm1\nmt1\nmt2\nrmt1\nrmt2\nrmt4\nt2\ntmp\n" + query = "SELECT name, uuid, create_table_query FROM system.tables WHERE database='recover' ORDER BY name" + expected = main_node.query(query) + assert_eq_with_retry(dummy_node, query, expected) + + for table in ['m1', 't2', 'mt1', 'mt2', 'rmt1', 'rmt2', 'rmt4', 'd1', 'd2']: + assert main_node.query("SELECT (*,).1 FROM recover.{}".format(table)) == "42\n" + for table in ['t2', 'rmt1', 'rmt2', 'rmt4', 'd1', 'd2', 'mt2']: + assert dummy_node.query("SELECT (*,).1 FROM recover.{}".format(table)) == "42\n" + for table in ['m1', 'mt1']: + assert dummy_node.query("SELECT count() FROM recover.{}".format(table)) == "0\n" + + assert dummy_node.query("SELECT count() FROM system.tables WHERE database='recover_broken_tables'") == "2\n" + table = dummy_node.query("SHOW TABLES FROM recover_broken_tables LIKE 'mt1_26_%'").strip() + assert dummy_node.query("SELECT (*,).1 FROM recover_broken_tables.{}".format(table)) == "42\n" + table = dummy_node.query("SHOW TABLES FROM recover_broken_tables LIKE 'rmt5_26_%'").strip() + assert dummy_node.query("SELECT (*,).1 FROM recover_broken_tables.{}".format(table)) == "42\n" + + expected = "Cleaned 4 outdated objects: dropped 1 dictionaries and 1 tables, moved 2 tables" + assert_logs_contain(dummy_node, expected) + + dummy_node.query("DROP TABLE recover.tmp") + assert_eq_with_retry(main_node, "SELECT count() FROM system.tables WHERE database='recover' AND name='tmp'", "0\n") + +def test_startup_without_zk(started_cluster): + main_node.query("DROP DATABASE IF EXISTS testdb SYNC") + main_node.query("DROP DATABASE IF EXISTS recover SYNC") + with PartitionManager() as pm: + pm.drop_instance_zk_connections(main_node) + err = main_node.query_and_get_error("CREATE DATABASE startup ENGINE = Replicated('/clickhouse/databases/startup', 'shard1', 'replica1');") + assert "ZooKeeper" in err + main_node.query("CREATE DATABASE startup ENGINE = Replicated('/clickhouse/databases/startup', 'shard1', 'replica1');") + #main_node.query("CREATE TABLE startup.rmt (n int) ENGINE=ReplicatedMergeTree order by n") + main_node.query("CREATE TABLE startup.rmt (n int) ENGINE=MergeTree order by n") + main_node.query("INSERT INTO startup.rmt VALUES (42)") + with PartitionManager() as pm: + pm.drop_instance_zk_connections(main_node) + main_node.restart_clickhouse(stop_start_wait_sec=30) + assert main_node.query("SELECT (*,).1 FROM startup.rmt") == "42\n" + + for _ in range(10): + try: + main_node.query("CREATE TABLE startup.m (n int) ENGINE=Memory") + break + except: + time.sleep(1) + + main_node.query("EXCHANGE TABLES startup.rmt AND startup.m") + assert main_node.query("SELECT (*,).1 FROM startup.m") == "42\n" diff --git a/tests/integration/test_replicated_merge_tree_s3/configs/config.d/storage_conf.xml b/tests/integration/test_replicated_merge_tree_s3/configs/config.d/storage_conf.xml index 20b750ffff3..1f75a4efeae 100644 --- a/tests/integration/test_replicated_merge_tree_s3/configs/config.d/storage_conf.xml +++ b/tests/integration/test_replicated_merge_tree_s3/configs/config.d/storage_conf.xml @@ -21,6 +21,7 @@ 0 + 0 diff --git a/tests/integration/test_replicated_merge_tree_s3_zero_copy/__init__.py b/tests/integration/test_replicated_merge_tree_s3_zero_copy/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_replicated_merge_tree_s3_zero_copy/configs/config.d/storage_conf.xml b/tests/integration/test_replicated_merge_tree_s3_zero_copy/configs/config.d/storage_conf.xml new file mode 100644 index 00000000000..d8c7f49fc49 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_s3_zero_copy/configs/config.d/storage_conf.xml @@ -0,0 +1,50 @@ + + + + + s3 + http://minio1:9001/root/data/ + minio + minio123 + + + + + +
+ s3 +
+
+
+
+
+ + + 0 + 1 + + + + + + + node1 + 9000 + + + node2 + 9000 + + + node3 + 9000 + + + + + + + 0 + + +
diff --git a/tests/integration/test_replicated_merge_tree_s3_zero_copy/test.py b/tests/integration/test_replicated_merge_tree_s3_zero_copy/test.py new file mode 100644 index 00000000000..793abc53566 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_s3_zero_copy/test.py @@ -0,0 +1,105 @@ +import logging +import random +import string + +import pytest +from helpers.cluster import ClickHouseCluster + +logging.getLogger().setLevel(logging.INFO) +logging.getLogger().addHandler(logging.StreamHandler()) + + +@pytest.fixture(scope="module") +def cluster(): + try: + cluster = ClickHouseCluster(__file__) + + cluster.add_instance("node1", main_configs=["configs/config.d/storage_conf.xml"], macros={'replica': '1'}, + with_minio=True, with_zookeeper=True) + cluster.add_instance("node2", main_configs=["configs/config.d/storage_conf.xml"], macros={'replica': '2'}, + with_zookeeper=True) + cluster.add_instance("node3", main_configs=["configs/config.d/storage_conf.xml"], macros={'replica': '3'}, + with_zookeeper=True) + + logging.info("Starting cluster...") + cluster.start() + logging.info("Cluster started") + + yield cluster + finally: + cluster.shutdown() + + +FILES_OVERHEAD = 1 +FILES_OVERHEAD_PER_COLUMN = 2 # Data and mark files +FILES_OVERHEAD_PER_PART_WIDE = FILES_OVERHEAD_PER_COLUMN * 3 + 2 + 6 + 1 +FILES_OVERHEAD_PER_PART_COMPACT = 10 + 1 + + +def random_string(length): + letters = string.ascii_letters + return ''.join(random.choice(letters) for i in range(length)) + + +def generate_values(date_str, count, sign=1): + data = [[date_str, sign * (i + 1), random_string(10)] for i in range(count)] + data.sort(key=lambda tup: tup[1]) + return ",".join(["('{}',{},'{}')".format(x, y, z) for x, y, z in data]) + + +def create_table(cluster, additional_settings=None): + create_table_statement = """ + CREATE TABLE s3_test ON CLUSTER cluster( + dt Date, + id Int64, + data String, + INDEX min_max (id) TYPE minmax GRANULARITY 3 + ) ENGINE=ReplicatedMergeTree() + PARTITION BY dt + ORDER BY (dt, id) + SETTINGS storage_policy='s3' + """ + if additional_settings: + create_table_statement += "," + create_table_statement += additional_settings + + list(cluster.instances.values())[0].query(create_table_statement) + + +@pytest.fixture(autouse=True) +def drop_table(cluster): + yield + for node in list(cluster.instances.values()): + node.query("DROP TABLE IF EXISTS s3_test") + + minio = cluster.minio_client + # Remove extra objects to prevent tests cascade failing + for obj in list(minio.list_objects(cluster.minio_bucket, 'data/')): + minio.remove_object(cluster.minio_bucket, obj.object_name) + +@pytest.mark.parametrize( + "min_rows_for_wide_part,files_per_part", + [ + (0, FILES_OVERHEAD_PER_PART_WIDE), + (8192, FILES_OVERHEAD_PER_PART_COMPACT) + ] +) +def test_insert_select_replicated(cluster, min_rows_for_wide_part, files_per_part): + create_table(cluster, additional_settings="min_rows_for_wide_part={}".format(min_rows_for_wide_part)) + + all_values = "" + for node_idx in range(1, 4): + node = cluster.instances["node" + str(node_idx)] + values = generate_values("2020-01-0" + str(node_idx), 4096) + node.query("INSERT INTO s3_test VALUES {}".format(values), settings={"insert_quorum": 3}) + if node_idx != 1: + all_values += "," + all_values += values + + for node_idx in range(1, 4): + node = cluster.instances["node" + str(node_idx)] + assert node.query("SELECT * FROM s3_test order by dt, id FORMAT Values", + settings={"select_sequential_consistency": 1}) == all_values + + minio = cluster.minio_client + assert len(list(minio.list_objects(cluster.minio_bucket, 'data/'))) == (3 * FILES_OVERHEAD) + (files_per_part * 3) diff --git a/tests/integration/test_replicated_merge_tree_with_auxiliary_zookeepers/test.py b/tests/integration/test_replicated_merge_tree_with_auxiliary_zookeepers/test.py index 91a25ec8d8a..a9dcce1b9d4 100644 --- a/tests/integration/test_replicated_merge_tree_with_auxiliary_zookeepers/test.py +++ b/tests/integration/test_replicated_merge_tree_with_auxiliary_zookeepers/test.py @@ -6,7 +6,6 @@ from helpers.cluster import ClickHouseCluster from helpers.client import QueryRuntimeException from helpers.test_tools import TSV -cluster = ClickHouseCluster(__file__) cluster = ClickHouseCluster(__file__) node1 = cluster.add_instance("node1", main_configs=["configs/zookeeper_config.xml", "configs/remote_servers.xml"], with_zookeeper=True) node2 = cluster.add_instance("node2", main_configs=["configs/zookeeper_config.xml", "configs/remote_servers.xml"], with_zookeeper=True) @@ -78,3 +77,27 @@ def test_create_replicated_merge_tree_with_not_exists_auxiliary_zookeeper(starte ENGINE = ReplicatedMergeTree('zookeeper_not_exits:/clickhouse/tables/test/test_auxiliary_zookeeper', '{replica}') ORDER BY a; '''.format(replica=node1.name)) + +# Drop table with auxiliary zookeeper. +def test_drop_replicated_merge_tree_with_auxiliary_zookeeper(started_cluster): + drop_table([node1, node2], "test_auxiliary_zookeeper") + for node in [node1, node2]: + node.query( + ''' + CREATE TABLE test_auxiliary_zookeeper(a Int32) + ENGINE = ReplicatedMergeTree('zookeeper2:/clickhouse/tables/test/test_auxiliary_zookeeper', '{replica}') + ORDER BY a; + '''.format(replica=node.name)) + + # Insert data into node1, and query it from node2. + node1.query("INSERT INTO test_auxiliary_zookeeper VALUES (1)") + time.sleep(5) + + expected = "1\n" + assert TSV(node1.query("SELECT a FROM test_auxiliary_zookeeper")) == TSV(expected) + assert TSV(node2.query("SELECT a FROM test_auxiliary_zookeeper")) == TSV(expected) + + zk = cluster.get_kazoo_client('zoo1') + assert zk.exists('/clickhouse/tables/test/test_auxiliary_zookeeper') + drop_table([node1, node2], "test_auxiliary_zookeeper") + assert zk.exists('/clickhouse/tables/test/test_auxiliary_zookeeper') is None diff --git a/tests/integration/test_row_policy/normal_filter2_table2.xml b/tests/integration/test_row_policy/normal_filter2_table2.xml new file mode 100644 index 00000000000..aca6bddc334 --- /dev/null +++ b/tests/integration/test_row_policy/normal_filter2_table2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + a > 0 + + + + + + diff --git a/tests/integration/test_row_policy/test.py b/tests/integration/test_row_policy/test.py index c3c86f5a9c5..ffb6dcb0588 100644 --- a/tests/integration/test_row_policy/test.py +++ b/tests/integration/test_row_policy/test.py @@ -103,21 +103,32 @@ def test_join(): def test_cannot_trick_row_policy_with_keyword_with(): - assert node.query("WITH 0 AS a SELECT * FROM mydb.filtered_table1") == TSV([[1, 0], [1, 1]]) - assert node.query("WITH 0 AS a SELECT a, b FROM mydb.filtered_table1") == TSV([[0, 0], [0, 1]]) assert node.query("WITH 0 AS a SELECT a FROM mydb.filtered_table1") == TSV([[0], [0]]) assert node.query("WITH 0 AS a SELECT b FROM mydb.filtered_table1") == TSV([[0], [1]]) + assert node.query("WITH 0 AS a SELECT * FROM mydb.filtered_table1") == TSV([[1, 0], [1, 1]]) + assert node.query("WITH 0 AS a SELECT * FROM mydb.filtered_table1 WHERE a >= 0 AND b >= 0 SETTINGS optimize_move_to_prewhere = 0") == TSV([[1, 0], [1, 1]]) + assert node.query("WITH 0 AS a SELECT * FROM mydb.filtered_table1 PREWHERE a >= 0 AND b >= 0") == TSV([[1, 0], [1, 1]]) + assert node.query("WITH 0 AS a SELECT * FROM mydb.filtered_table1 PREWHERE a >= 0 WHERE b >= 0") == TSV([[1, 0], [1, 1]]) + assert node.query("WITH 0 AS a SELECT * FROM mydb.filtered_table1 PREWHERE b >= 0 WHERE a >= 0") == TSV([[1, 0], [1, 1]]) -def test_prewhere_not_supported(): - expected_error = "PREWHERE is not supported if the table is filtered by row-level security" - assert expected_error in node.query_and_get_error("SELECT * FROM mydb.filtered_table1 PREWHERE 1") - assert expected_error in node.query_and_get_error("SELECT * FROM mydb.filtered_table2 PREWHERE 1") - assert expected_error in node.query_and_get_error("SELECT * FROM mydb.filtered_table3 PREWHERE 1") + assert node.query("WITH 0 AS a SELECT a, b FROM mydb.filtered_table1") == TSV([[0, 0], [0, 1]]) + assert node.query("WITH 0 AS a SELECT a, b FROM mydb.filtered_table1 WHERE a >= 0 AND b >= 0 SETTINGS optimize_move_to_prewhere = 0") == TSV([[0, 0], [0, 1]]) + assert node.query("WITH 0 AS a SELECT a, b FROM mydb.filtered_table1 PREWHERE a >= 0 AND b >= 0") == TSV([[0, 0], [0, 1]]) + assert node.query("WITH 0 AS a SELECT a, b FROM mydb.filtered_table1 PREWHERE a >= 0 WHERE b >= 0") == TSV([[0, 0], [0, 1]]) + assert node.query("WITH 0 AS a SELECT a, b FROM mydb.filtered_table1 PREWHERE b >= 0 WHERE a >= 0") == TSV([[0, 0], [0, 1]]) - # However PREWHERE should still work for user without filtering. - assert node.query("SELECT * FROM mydb.filtered_table1 PREWHERE 1", user="another") == TSV( - [[0, 0], [0, 1], [1, 0], [1, 1]]) + assert node.query("WITH 0 AS c SELECT * FROM mydb.filtered_table3") == TSV([[0, 1], [1, 0]]) + assert node.query("WITH 0 AS c SELECT * FROM mydb.filtered_table3 WHERE c >= 0 AND a >= 0 SETTINGS optimize_move_to_prewhere = 0") == TSV([[0, 1], [1, 0]]) + assert node.query("WITH 0 AS c SELECT * FROM mydb.filtered_table3 PREWHERE c >= 0 AND a >= 0") == TSV([[0, 1], [1, 0]]) + assert node.query("WITH 0 AS c SELECT * FROM mydb.filtered_table3 PREWHERE c >= 0 WHERE a >= 0") == TSV([[0, 1], [1, 0]]) + assert node.query("WITH 0 AS c SELECT * FROM mydb.filtered_table3 PREWHERE a >= 0 WHERE c >= 0") == TSV([[0, 1], [1, 0]]) + + assert node.query("WITH 0 AS c SELECT a, b, c FROM mydb.filtered_table3") == TSV([[0, 1, 0], [1, 0, 0]]) + assert node.query("WITH 0 AS c SELECT a, b, c FROM mydb.filtered_table3 WHERE c >= 0 AND a >= 0 SETTINGS optimize_move_to_prewhere = 0") == TSV([[0, 1, 0], [1, 0, 0]]) + assert node.query("WITH 0 AS c SELECT a, b, c FROM mydb.filtered_table3 PREWHERE c >= 0 AND a >= 0") == TSV([[0, 1, 0], [1, 0, 0]]) + assert node.query("WITH 0 AS c SELECT a, b, c FROM mydb.filtered_table3 PREWHERE c >= 0 WHERE a >= 0") == TSV([[0, 1, 0], [1, 0, 0]]) + assert node.query("WITH 0 AS c SELECT a, b, c FROM mydb.filtered_table3 PREWHERE a >= 0 WHERE c >= 0") == TSV([[0, 1, 0], [1, 0, 0]]) def test_policy_from_users_xml_affects_only_user_assigned(): @@ -132,6 +143,57 @@ def test_policy_from_users_xml_affects_only_user_assigned(): assert node.query("SELECT * FROM mydb.local", user="another") == TSV([[1, 0], [1, 1]]) +def test_with_prewhere(): + copy_policy_xml('normal_filter2_table2.xml') + assert node.query("SELECT * FROM mydb.filtered_table2 WHERE a > 1 SETTINGS optimize_move_to_prewhere = 0") == TSV([[4, 3, 2, 1]]) + assert node.query("SELECT a FROM mydb.filtered_table2 WHERE a > 1 SETTINGS optimize_move_to_prewhere = 0") == TSV([[4]]) + assert node.query("SELECT a, b FROM mydb.filtered_table2 WHERE a > 1 SETTINGS optimize_move_to_prewhere = 0") == TSV([[4, 3]]) + assert node.query("SELECT b, c FROM mydb.filtered_table2 WHERE a > 1 SETTINGS optimize_move_to_prewhere = 0") == TSV([[3, 2]]) + assert node.query("SELECT d FROM mydb.filtered_table2 WHERE a > 1 SETTINGS optimize_move_to_prewhere = 0") == TSV([[1]]) + + assert node.query("SELECT * FROM mydb.filtered_table2 PREWHERE a > 1") == TSV([[4, 3, 2, 1]]) + assert node.query("SELECT a FROM mydb.filtered_table2 PREWHERE a > 1") == TSV([[4]]) + assert node.query("SELECT a, b FROM mydb.filtered_table2 PREWHERE a > 1") == TSV([[4, 3]]) + assert node.query("SELECT b, c FROM mydb.filtered_table2 PREWHERE a > 1") == TSV([[3, 2]]) + assert node.query("SELECT d FROM mydb.filtered_table2 PREWHERE a > 1") == TSV([[1]]) + + assert node.query("SELECT * FROM mydb.filtered_table2 PREWHERE a < 4 WHERE b < 10") == TSV([[1, 2, 3, 4]]) + assert node.query("SELECT a FROM mydb.filtered_table2 PREWHERE a < 4 WHERE b < 10") == TSV([[1]]) + assert node.query("SELECT b FROM mydb.filtered_table2 PREWHERE a < 4 WHERE b < 10") == TSV([[2]]) + assert node.query("SELECT a, b FROM mydb.filtered_table2 PREWHERE a < 4 WHERE b < 10") == TSV([[1, 2]]) + assert node.query("SELECT a, c FROM mydb.filtered_table2 PREWHERE a < 4 WHERE b < 10") == TSV([[1, 3]]) + assert node.query("SELECT b, d FROM mydb.filtered_table2 PREWHERE a < 4 WHERE b < 10") == TSV([[2, 4]]) + assert node.query("SELECT c, d FROM mydb.filtered_table2 PREWHERE a < 4 WHERE b < 10") == TSV([[3, 4]]) + + +def test_throwif_error_in_where_with_same_condition_as_filter(): + copy_policy_xml('normal_filter2_table2.xml') + assert 'expected' in node.query_and_get_error("SELECT * FROM mydb.filtered_table2 WHERE throwIf(a > 0, 'expected') = 0 SETTINGS optimize_move_to_prewhere = 0") + + +def test_throwif_error_in_prewhere_with_same_condition_as_filter(): + copy_policy_xml('normal_filter2_table2.xml') + assert 'expected' in node.query_and_get_error("SELECT * FROM mydb.filtered_table2 PREWHERE throwIf(a > 0, 'expected') = 0") + + +def test_throwif_in_where_doesnt_expose_restricted_data(): + copy_policy_xml('no_filters.xml') + assert 'expected' in node.query_and_get_error("SELECT * FROM mydb.filtered_table2 WHERE throwIf(a = 0, 'expected') = 0 SETTINGS optimize_move_to_prewhere = 0") + + copy_policy_xml('normal_filter2_table2.xml') + assert node.query("SELECT * FROM mydb.filtered_table2 WHERE throwIf(a = 0, 'pwned') = 0 SETTINGS optimize_move_to_prewhere = 0") == TSV([ + [1, 2, 3, 4], [4, 3, 2, 1]]) + + +def test_throwif_in_prewhere_doesnt_expose_restricted_data(): + copy_policy_xml('no_filters.xml') + assert 'expected' in node.query_and_get_error("SELECT * FROM mydb.filtered_table2 PREWHERE throwIf(a = 0, 'expected') = 0") + + copy_policy_xml('normal_filter2_table2.xml') + assert node.query("SELECT * FROM mydb.filtered_table2 PREWHERE throwIf(a = 0, 'pwned') = 0") == TSV([ + [1, 2, 3, 4], [4, 3, 2, 1]]) + + def test_change_of_users_xml_changes_row_policies(): copy_policy_xml('normal_filters.xml') assert node.query("SELECT * FROM mydb.filtered_table1") == TSV([[1, 0], [1, 1]]) @@ -154,6 +216,11 @@ def test_change_of_users_xml_changes_row_policies(): assert node.query("SELECT * FROM mydb.filtered_table2") == TSV([[0, 0, 0, 0], [0, 0, 6, 0]]) assert node.query("SELECT * FROM mydb.filtered_table3") == TSV([[0, 1], [1, 0]]) + copy_policy_xml('normal_filter2_table2.xml') + assert node.query("SELECT * FROM mydb.filtered_table1") == TSV([[0, 0], [0, 1], [1, 0], [1, 1]]) + assert node.query("SELECT * FROM mydb.filtered_table2") == TSV([[1, 2, 3, 4], [4, 3, 2, 1]]) + assert node.query("SELECT * FROM mydb.filtered_table3") == TSV([[0, 0], [0, 1], [1, 0], [1, 1]]) + copy_policy_xml('no_filters.xml') assert node.query("SELECT * FROM mydb.filtered_table1") == TSV([[0, 0], [0, 1], [1, 0], [1, 1]]) assert node.query("SELECT * FROM mydb.filtered_table2") == TSV( diff --git a/tests/integration/test_s3_zero_copy_replication/__init__.py b/tests/integration/test_s3_zero_copy_replication/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_s3_zero_copy_replication/configs/config.d/s3.xml b/tests/integration/test_s3_zero_copy_replication/configs/config.d/s3.xml new file mode 100644 index 00000000000..7d8492ed68c --- /dev/null +++ b/tests/integration/test_s3_zero_copy_replication/configs/config.d/s3.xml @@ -0,0 +1,50 @@ + + + + + + s3 + http://minio1:9001/root/data/ + minio + minio123 + + + + + +
+ s31 +
+
+
+
+
+ + + 0 + 1 + 1 + + + + + + + node1 + 9000 + + + + + node2 + 9000 + + + + + + + test_cluster + + +
diff --git a/tests/integration/test_s3_zero_copy_replication/test.py b/tests/integration/test_s3_zero_copy_replication/test.py new file mode 100644 index 00000000000..6a7336b9090 --- /dev/null +++ b/tests/integration/test_s3_zero_copy_replication/test.py @@ -0,0 +1,90 @@ +import logging +import time + +import pytest +from helpers.cluster import ClickHouseCluster + +logging.getLogger().setLevel(logging.INFO) +logging.getLogger().addHandler(logging.StreamHandler()) + + +@pytest.fixture(scope="module") +def cluster(): + try: + cluster = ClickHouseCluster(__file__) + cluster.add_instance("node1", main_configs=["configs/config.d/s3.xml"], macros={'replica': '1'}, + with_minio=True, + with_zookeeper=True) + cluster.add_instance("node2", main_configs=["configs/config.d/s3.xml"], macros={'replica': '2'}, + with_minio=True, + with_zookeeper=True) + logging.info("Starting cluster...") + cluster.start() + logging.info("Cluster started") + + yield cluster + finally: + cluster.shutdown() + + +def get_large_objects_count(cluster, size=100): + minio = cluster.minio_client + counter = 0 + for obj in minio.list_objects(cluster.minio_bucket, 'data/'): + if obj.size >= size: + counter = counter + 1 + return counter + + +@pytest.mark.parametrize( + "policy", ["s3"] +) +def test_s3_zero_copy_replication(cluster, policy): + node1 = cluster.instances["node1"] + node2 = cluster.instances["node2"] + + node1.query( + """ + CREATE TABLE s3_test ON CLUSTER test_cluster (id UInt32, value String) + ENGINE=ReplicatedMergeTree('/clickhouse/tables/s3_test', '{}') + ORDER BY id + SETTINGS storage_policy='{}' + """ + .format('{replica}', policy) + ) + + node1.query("INSERT INTO s3_test VALUES (0,'data'),(1,'data')") + time.sleep(1) + assert node1.query("SELECT * FROM s3_test order by id FORMAT Values") == "(0,'data'),(1,'data')" + assert node2.query("SELECT * FROM s3_test order by id FORMAT Values") == "(0,'data'),(1,'data')" + + # Based on version 20.x - should be only one file with size 100+ (checksums.txt), used by both nodes + assert get_large_objects_count(cluster) == 1 + + node2.query("INSERT INTO s3_test VALUES (2,'data'),(3,'data')") + time.sleep(1) + assert node2.query("SELECT * FROM s3_test order by id FORMAT Values") == "(0,'data'),(1,'data'),(2,'data'),(3,'data')" + assert node1.query("SELECT * FROM s3_test order by id FORMAT Values") == "(0,'data'),(1,'data'),(2,'data'),(3,'data')" + + # Based on version 20.x - two parts + assert get_large_objects_count(cluster) == 2 + + node1.query("OPTIMIZE TABLE s3_test") + + time.sleep(1) + + # Based on version 20.x - after merge, two old parts and one merged + assert get_large_objects_count(cluster) == 3 + + # Based on version 20.x - after cleanup - only one merged part + countdown = 60 + while countdown > 0: + if get_large_objects_count(cluster) == 1: + break + time.sleep(1) + countdown -= 1 + assert get_large_objects_count(cluster) == 1 + + node1.query("DROP TABLE IF EXISTS s3_test NO DELAY") + node2.query("DROP TABLE IF EXISTS s3_test NO DELAY") + diff --git a/tests/integration/test_settings_profile/test.py b/tests/integration/test_settings_profile/test.py index 3ceef9f25cf..1945875bf53 100644 --- a/tests/integration/test_settings_profile/test.py +++ b/tests/integration/test_settings_profile/test.py @@ -46,7 +46,7 @@ def reset_after_test(): def test_smoke(): - # Set settings and constraints via CREATE SETTINGS PROFILE ... TO user + # Set settings and constraints via CREATE SETTINGS PROFILE ... TO user instance.query( "CREATE SETTINGS PROFILE xyz SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000 TO robin") assert instance.query( @@ -194,13 +194,13 @@ def test_show_profiles(): assert instance.query("SHOW CREATE PROFILE xyz") == "CREATE SETTINGS PROFILE xyz\n" assert instance.query( - "SHOW CREATE SETTINGS PROFILE default") == "CREATE SETTINGS PROFILE default SETTINGS max_memory_usage = 10000000000, use_uncompressed_cache = 0, load_balancing = \\'random\\'\n" + "SHOW CREATE SETTINGS PROFILE default") == "CREATE SETTINGS PROFILE default SETTINGS max_memory_usage = 10000000000, load_balancing = \\'random\\'\n" assert instance.query( - "SHOW CREATE PROFILES") == "CREATE SETTINGS PROFILE default SETTINGS max_memory_usage = 10000000000, use_uncompressed_cache = 0, load_balancing = \\'random\\'\n" \ + "SHOW CREATE PROFILES") == "CREATE SETTINGS PROFILE default SETTINGS max_memory_usage = 10000000000, load_balancing = \\'random\\'\n" \ "CREATE SETTINGS PROFILE readonly SETTINGS readonly = 1\n" \ "CREATE SETTINGS PROFILE xyz\n" - expected_access = "CREATE SETTINGS PROFILE default SETTINGS max_memory_usage = 10000000000, use_uncompressed_cache = 0, load_balancing = \\'random\\'\n" \ + expected_access = "CREATE SETTINGS PROFILE default SETTINGS max_memory_usage = 10000000000, load_balancing = \\'random\\'\n" \ "CREATE SETTINGS PROFILE readonly SETTINGS readonly = 1\n" \ "CREATE SETTINGS PROFILE xyz\n" assert expected_access in instance.query("SHOW ACCESS") @@ -210,7 +210,7 @@ def test_allow_ddl(): assert "it's necessary to have grant" in instance.query_and_get_error("CREATE TABLE tbl(a Int32) ENGINE=Log", user="robin") assert "it's necessary to have grant" in instance.query_and_get_error("GRANT CREATE ON tbl TO robin", user="robin") assert "DDL queries are prohibited" in instance.query_and_get_error("CREATE TABLE tbl(a Int32) ENGINE=Log", settings={"allow_ddl": 0}) - + instance.query("GRANT CREATE ON tbl TO robin") instance.query("CREATE TABLE tbl(a Int32) ENGINE=Log", user="robin") instance.query("DROP TABLE tbl") diff --git a/tests/integration/test_storage_kafka/test.py b/tests/integration/test_storage_kafka/test.py index 5f2726832cc..c5691f3534e 100644 --- a/tests/integration/test_storage_kafka/test.py +++ b/tests/integration/test_storage_kafka/test.py @@ -18,10 +18,8 @@ from helpers.client import QueryRuntimeException from helpers.cluster import ClickHouseCluster from helpers.network import PartitionManager from helpers.test_tools import TSV -from kafka import KafkaAdminClient, KafkaProducer, KafkaConsumer, BrokerConnection +from kafka import KafkaAdminClient, KafkaProducer, KafkaConsumer from kafka.admin import NewTopic -from kafka.protocol.admin import DescribeGroupsRequest_v1 -from kafka.protocol.group import MemberAssignment """ protoc --version @@ -83,12 +81,16 @@ def wait_kafka_is_available(max_retries=50): def producer_serializer(x): return x.encode() if isinstance(x, str) else x -def kafka_produce(topic, messages, timestamp=None): - producer = KafkaProducer(bootstrap_servers="localhost:9092", value_serializer=producer_serializer) +def kafka_produce(topic, messages, timestamp=None, retries=2): + producer = KafkaProducer(bootstrap_servers="localhost:9092", value_serializer=producer_serializer, retries=retries, max_in_flight_requests_per_connection=1) for message in messages: producer.send(topic=topic, value=message, timestamp_ms=timestamp) producer.flush() +## just to ensure the python client / producer is working properly +def kafka_producer_send_heartbeat_msg(max_retries=50): + kafka_produce('test_heartbeat_topic', ['test'], retries=max_retries) + def kafka_consume(topic): consumer = KafkaConsumer(bootstrap_servers="localhost:9092", auto_offset_reset="earliest") consumer.subscribe(topics=(topic)) @@ -156,6 +158,132 @@ def avro_confluent_message(schema_registry_client, value): }) return serializer.encode_record_with_schema('test_subject', schema, value) +# Since everything is async and shaky when receiving messages from Kafka, +# we may want to try and check results multiple times in a loop. +def kafka_check_result(result, check=False, ref_file='test_kafka_json.reference'): + fpath = p.join(p.dirname(__file__), ref_file) + with open(fpath) as reference: + if check: + assert TSV(result) == TSV(reference) + else: + return TSV(result) == TSV(reference) + +def describe_consumer_group(name): + admin_client = KafkaAdminClient(bootstrap_servers="localhost:9092") + consumer_groups = admin_client.describe_consumer_groups([name]) + res = [] + for member in consumer_groups[0].members: + member_info = {} + member_info['member_id'] = member.member_id + member_info['client_id'] = member.client_id + member_info['client_host'] = member.client_host + member_topics_assignment = [] + for (topic, partitions) in member.member_assignment.assignment: + member_topics_assignment.append({'topic': topic, 'partitions': partitions}) + member_info['assignment'] = member_topics_assignment + res.append(member_info) + return res + +# Fixtures + +@pytest.fixture(scope="module") +def kafka_cluster(): + try: + global kafka_id + cluster.start() + kafka_id = instance.cluster.kafka_docker_id + print(("kafka_id is {}".format(kafka_id))) + yield cluster + + finally: + cluster.shutdown() + +@pytest.fixture(autouse=True) +def kafka_setup_teardown(): + instance.query('DROP DATABASE IF EXISTS test; CREATE DATABASE test;') + wait_kafka_is_available() # ensure kafka is alive + kafka_producer_send_heartbeat_msg() # ensure python kafka client is ok + # print("kafka is available - running test") + yield # run test + +# Tests + +@pytest.mark.timeout(180) +def test_kafka_settings_old_syntax(kafka_cluster): + assert TSV(instance.query("SELECT * FROM system.macros WHERE macro like 'kafka%' ORDER BY macro", + ignore_error=True)) == TSV('''kafka_broker kafka1 +kafka_client_id instance +kafka_format_json_each_row JSONEachRow +kafka_group_name_new new +kafka_group_name_old old +kafka_topic_new new +kafka_topic_old old +''') + + instance.query(''' + CREATE TABLE test.kafka (key UInt64, value UInt64) + ENGINE = Kafka('{kafka_broker}:19092', '{kafka_topic_old}', '{kafka_group_name_old}', '{kafka_format_json_each_row}', '\\n'); + ''') + + # Don't insert malformed messages since old settings syntax + # doesn't support skipping of broken messages. + messages = [] + for i in range(50): + messages.append(json.dumps({'key': i, 'value': i})) + kafka_produce('old', messages) + + result = '' + while True: + result += instance.query('SELECT * FROM test.kafka', ignore_error=True) + if kafka_check_result(result): + break + + kafka_check_result(result, True) + + members = describe_consumer_group('old') + assert members[0]['client_id'] == 'ClickHouse-instance-test-kafka' + # text_desc = kafka_cluster.exec_in_container(kafka_cluster.get_container_id('kafka1'),"kafka-consumer-groups --bootstrap-server localhost:9092 --describe --members --group old --verbose")) + + +@pytest.mark.timeout(180) +def test_kafka_settings_new_syntax(kafka_cluster): + instance.query(''' + CREATE TABLE test.kafka (key UInt64, value UInt64) + ENGINE = Kafka + SETTINGS kafka_broker_list = '{kafka_broker}:19092', + kafka_topic_list = '{kafka_topic_new}', + kafka_group_name = '{kafka_group_name_new}', + kafka_format = '{kafka_format_json_each_row}', + kafka_row_delimiter = '\\n', + kafka_client_id = '{kafka_client_id} test 1234', + kafka_skip_broken_messages = 1; + ''') + + messages = [] + for i in range(25): + messages.append(json.dumps({'key': i, 'value': i})) + kafka_produce('new', messages) + + # Insert couple of malformed messages. + kafka_produce('new', ['}{very_broken_message,']) + kafka_produce('new', ['}another{very_broken_message,']) + + messages = [] + for i in range(25, 50): + messages.append(json.dumps({'key': i, 'value': i})) + kafka_produce('new', messages) + + result = '' + while True: + result += instance.query('SELECT * FROM test.kafka', ignore_error=True) + if kafka_check_result(result): + break + + kafka_check_result(result, True) + + members = describe_consumer_group('new') + assert members[0]['client_id'] == 'instance test 1234' + @pytest.mark.timeout(180) def test_kafka_json_as_string(kafka_cluster): @@ -183,7 +311,7 @@ def test_kafka_json_as_string(kafka_cluster): "Parsing of message (topic: kafka_json_as_string, partition: 0, offset: 1) return no rows") -@pytest.mark.timeout(300) +@pytest.mark.timeout(120) def test_kafka_formats(kafka_cluster): # data was dumped from clickhouse itself in a following manner # clickhouse-client --format=Native --query='SELECT toInt64(number) as id, toUInt16( intDiv( id, 65536 ) ) as blockNo, reinterpretAsString(19777) as val1, toFloat32(0.5) as val2, toUInt8(1) as val3 from numbers(100) ORDER BY id' | xxd -ps | tr -d '\n' | sed 's/\(..\)/\\x\1/g' @@ -311,7 +439,7 @@ def test_kafka_formats(kafka_cluster): # On empty message exception happens: Line "" doesn't match the regexp.: (at row 1) # /src/Processors/Formats/Impl/RegexpRowInputFormat.cpp:140: DB::RegexpRowInputFormat::readRow(std::__1::vector::mutable_ptr, std::__1::allocator::mutable_ptr > >&, DB::RowReadExtension&) @ 0x1df82fcb in /usr/bin/clickhouse ], - 'extra_settings': ", format_regexp='\(id = (.+?), blockNo = (.+?), val1 = \"(.+?)\", val2 = (.+?), val3 = (.+?)\)', format_regexp_escaping_rule='Escaped'" + 'extra_settings': r", format_regexp='\(id = (.+?), blockNo = (.+?), val1 = \"(.+?)\", val2 = (.+?), val3 = (.+?)\)', format_regexp_escaping_rule='Escaped'" }, ## BINARY FORMATS @@ -545,7 +673,7 @@ def test_kafka_formats(kafka_cluster): '''.format(topic_name=topic_name, format_name=format_name, extra_settings=format_opts.get('extra_settings') or '')) - time.sleep(12) + instance.wait_for_log_line('kafka.*Committed offset [0-9]+.*format_tests_', repetitions=len(all_formats.keys()), look_behind_lines=12000) for format_name, format_opts in list(all_formats.items()): print(('Checking {}'.format(format_name))) @@ -574,148 +702,6 @@ def test_kafka_formats(kafka_cluster): '''.format(topic_name=topic_name, offset_0=offsets[0], offset_1=offsets[1], offset_2=offsets[2]) assert TSV(result) == TSV(expected), 'Proper result for format: {}'.format(format_name) - -# Since everything is async and shaky when receiving messages from Kafka, -# we may want to try and check results multiple times in a loop. -def kafka_check_result(result, check=False, ref_file='test_kafka_json.reference'): - fpath = p.join(p.dirname(__file__), ref_file) - with open(fpath) as reference: - if check: - assert TSV(result) == TSV(reference) - else: - return TSV(result) == TSV(reference) - - -# https://stackoverflow.com/a/57692111/1555175 -def describe_consumer_group(name): - client = BrokerConnection('localhost', 9092, socket.AF_INET) - client.connect_blocking() - - list_members_in_groups = DescribeGroupsRequest_v1(groups=[name]) - future = client.send(list_members_in_groups) - while not future.is_done: - for resp, f in client.recv(): - f.success(resp) - - (error_code, group_id, state, protocol_type, protocol, members) = future.value.groups[0] - - res = [] - for member in members: - (member_id, client_id, client_host, member_metadata, member_assignment) = member - member_info = {} - member_info['member_id'] = member_id - member_info['client_id'] = client_id - member_info['client_host'] = client_host - member_topics_assignment = [] - for (topic, partitions) in MemberAssignment.decode(member_assignment).assignment: - member_topics_assignment.append({'topic': topic, 'partitions': partitions}) - member_info['assignment'] = member_topics_assignment - res.append(member_info) - return res - - -# Fixtures - -@pytest.fixture(scope="module") -def kafka_cluster(): - try: - global kafka_id - cluster.start() - kafka_id = instance.cluster.kafka_docker_id - print(("kafka_id is {}".format(kafka_id))) - yield cluster - - finally: - cluster.shutdown() - - -@pytest.fixture(autouse=True) -def kafka_setup_teardown(): - instance.query('DROP DATABASE IF EXISTS test; CREATE DATABASE test;') - wait_kafka_is_available() - # print("kafka is available - running test") - yield # run test - - -# Tests - -@pytest.mark.timeout(180) -def test_kafka_settings_old_syntax(kafka_cluster): - assert TSV(instance.query("SELECT * FROM system.macros WHERE macro like 'kafka%' ORDER BY macro", - ignore_error=True)) == TSV('''kafka_broker kafka1 -kafka_client_id instance -kafka_format_json_each_row JSONEachRow -kafka_group_name_new new -kafka_group_name_old old -kafka_topic_new new -kafka_topic_old old -''') - - instance.query(''' - CREATE TABLE test.kafka (key UInt64, value UInt64) - ENGINE = Kafka('{kafka_broker}:19092', '{kafka_topic_old}', '{kafka_group_name_old}', '{kafka_format_json_each_row}', '\\n'); - ''') - - # Don't insert malformed messages since old settings syntax - # doesn't support skipping of broken messages. - messages = [] - for i in range(50): - messages.append(json.dumps({'key': i, 'value': i})) - kafka_produce('old', messages) - - result = '' - while True: - result += instance.query('SELECT * FROM test.kafka', ignore_error=True) - if kafka_check_result(result): - break - - kafka_check_result(result, True) - - members = describe_consumer_group('old') - assert members[0]['client_id'] == 'ClickHouse-instance-test-kafka' - # text_desc = kafka_cluster.exec_in_container(kafka_cluster.get_container_id('kafka1'),"kafka-consumer-groups --bootstrap-server localhost:9092 --describe --members --group old --verbose")) - - -@pytest.mark.timeout(180) -def test_kafka_settings_new_syntax(kafka_cluster): - instance.query(''' - CREATE TABLE test.kafka (key UInt64, value UInt64) - ENGINE = Kafka - SETTINGS kafka_broker_list = '{kafka_broker}:19092', - kafka_topic_list = '{kafka_topic_new}', - kafka_group_name = '{kafka_group_name_new}', - kafka_format = '{kafka_format_json_each_row}', - kafka_row_delimiter = '\\n', - kafka_client_id = '{kafka_client_id} test 1234', - kafka_skip_broken_messages = 1; - ''') - - messages = [] - for i in range(25): - messages.append(json.dumps({'key': i, 'value': i})) - kafka_produce('new', messages) - - # Insert couple of malformed messages. - kafka_produce('new', ['}{very_broken_message,']) - kafka_produce('new', ['}another{very_broken_message,']) - - messages = [] - for i in range(25, 50): - messages.append(json.dumps({'key': i, 'value': i})) - kafka_produce('new', messages) - - result = '' - while True: - result += instance.query('SELECT * FROM test.kafka', ignore_error=True) - if kafka_check_result(result): - break - - kafka_check_result(result, True) - - members = describe_consumer_group('new') - assert members[0]['client_id'] == 'instance test 1234' - - @pytest.mark.timeout(180) def test_kafka_issue11308(kafka_cluster): # Check that matview does respect Kafka SETTINGS @@ -796,6 +782,12 @@ def test_kafka_issue4116(kafka_cluster): @pytest.mark.timeout(180) def test_kafka_consumer_hang(kafka_cluster): + admin_client = KafkaAdminClient(bootstrap_servers="localhost:9092") + + topic_list = [] + topic_list.append(NewTopic(name="consumer_hang", num_partitions=8, replication_factor=1)) + admin_client.create_topics(new_topics=topic_list, validate_only=False) + instance.query(''' DROP TABLE IF EXISTS test.kafka; DROP TABLE IF EXISTS test.view; @@ -807,20 +799,18 @@ def test_kafka_consumer_hang(kafka_cluster): kafka_topic_list = 'consumer_hang', kafka_group_name = 'consumer_hang', kafka_format = 'JSONEachRow', - kafka_num_consumers = 8, - kafka_row_delimiter = '\\n'; + kafka_num_consumers = 8; CREATE TABLE test.view (key UInt64, value UInt64) ENGINE = Memory(); CREATE MATERIALIZED VIEW test.consumer TO test.view AS SELECT * FROM test.kafka; ''') - time.sleep(10) - instance.query('SELECT * FROM test.view') + instance.wait_for_log_line('kafka.*Stalled', repetitions=20) # This should trigger heartbeat fail, # which will trigger REBALANCE_IN_PROGRESS, # and which can lead to consumer hang. kafka_cluster.pause_container('kafka1') - time.sleep(0.5) + instance.wait_for_log_line('heartbeat error') kafka_cluster.unpause_container('kafka1') # print("Attempt to drop") @@ -844,6 +834,12 @@ def test_kafka_consumer_hang(kafka_cluster): @pytest.mark.timeout(180) def test_kafka_consumer_hang2(kafka_cluster): + admin_client = KafkaAdminClient(bootstrap_servers="localhost:9092") + + topic_list = [] + topic_list.append(NewTopic(name="consumer_hang2", num_partitions=1, replication_factor=1)) + admin_client.create_topics(new_topics=topic_list, validate_only=False) + instance.query(''' DROP TABLE IF EXISTS test.kafka; @@ -884,23 +880,22 @@ def test_kafka_consumer_hang2(kafka_cluster): assert int(instance.query("select count() from system.processes where position(lower(query),'dr'||'op')>0")) == 0 -@pytest.mark.timeout(180) +@pytest.mark.timeout(120) def test_kafka_csv_with_delimiter(kafka_cluster): + messages = [] + for i in range(50): + messages.append('{i}, {i}'.format(i=i)) + kafka_produce('csv', messages) + instance.query(''' CREATE TABLE test.kafka (key UInt64, value UInt64) ENGINE = Kafka SETTINGS kafka_broker_list = 'kafka1:19092', kafka_topic_list = 'csv', kafka_group_name = 'csv', - kafka_format = 'CSV', - kafka_row_delimiter = '\\n'; + kafka_format = 'CSV'; ''') - messages = [] - for i in range(50): - messages.append('{i}, {i}'.format(i=i)) - kafka_produce('csv', messages) - result = '' while True: result += instance.query('SELECT * FROM test.kafka', ignore_error=True) @@ -910,23 +905,22 @@ def test_kafka_csv_with_delimiter(kafka_cluster): kafka_check_result(result, True) -@pytest.mark.timeout(180) +@pytest.mark.timeout(120) def test_kafka_tsv_with_delimiter(kafka_cluster): + messages = [] + for i in range(50): + messages.append('{i}\t{i}'.format(i=i)) + kafka_produce('tsv', messages) + instance.query(''' CREATE TABLE test.kafka (key UInt64, value UInt64) ENGINE = Kafka SETTINGS kafka_broker_list = 'kafka1:19092', kafka_topic_list = 'tsv', kafka_group_name = 'tsv', - kafka_format = 'TSV', - kafka_row_delimiter = '\\n'; + kafka_format = 'TSV'; ''') - messages = [] - for i in range(50): - messages.append('{i}\t{i}'.format(i=i)) - kafka_produce('tsv', messages) - result = '' while True: result += instance.query('SELECT * FROM test.kafka', ignore_error=True) @@ -936,8 +930,13 @@ def test_kafka_tsv_with_delimiter(kafka_cluster): kafka_check_result(result, True) -@pytest.mark.timeout(180) +@pytest.mark.timeout(120) def test_kafka_select_empty(kafka_cluster): + admin_client = KafkaAdminClient(bootstrap_servers="localhost:9092") + topic_list = [] + topic_list.append(NewTopic(name="empty", num_partitions=1, replication_factor=1)) + admin_client.create_topics(new_topics=topic_list, validate_only=False) + instance.query(''' CREATE TABLE test.kafka (key UInt64) ENGINE = Kafka @@ -953,15 +952,6 @@ def test_kafka_select_empty(kafka_cluster): @pytest.mark.timeout(180) def test_kafka_json_without_delimiter(kafka_cluster): - instance.query(''' - CREATE TABLE test.kafka (key UInt64, value UInt64) - ENGINE = Kafka - SETTINGS kafka_broker_list = 'kafka1:19092', - kafka_topic_list = 'json', - kafka_group_name = 'json', - kafka_format = 'JSONEachRow'; - ''') - messages = '' for i in range(25): messages += json.dumps({'key': i, 'value': i}) + '\n' @@ -972,6 +962,15 @@ def test_kafka_json_without_delimiter(kafka_cluster): messages += json.dumps({'key': i, 'value': i}) + '\n' kafka_produce('json', [messages]) + instance.query(''' + CREATE TABLE test.kafka (key UInt64, value UInt64) + ENGINE = Kafka + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = 'json', + kafka_group_name = 'json', + kafka_format = 'JSONEachRow'; + ''') + result = '' while True: result += instance.query('SELECT * FROM test.kafka', ignore_error=True) @@ -983,6 +982,10 @@ def test_kafka_json_without_delimiter(kafka_cluster): @pytest.mark.timeout(180) def test_kafka_protobuf(kafka_cluster): + kafka_produce_protobuf_messages('pb', 0, 20) + kafka_produce_protobuf_messages('pb', 20, 1) + kafka_produce_protobuf_messages('pb', 21, 29) + instance.query(''' CREATE TABLE test.kafka (key UInt64, value String) ENGINE = Kafka @@ -993,10 +996,6 @@ def test_kafka_protobuf(kafka_cluster): kafka_schema = 'kafka.proto:KeyValuePair'; ''') - kafka_produce_protobuf_messages('pb', 0, 20) - kafka_produce_protobuf_messages('pb', 20, 1) - kafka_produce_protobuf_messages('pb', 21, 29) - result = '' while True: result += instance.query('SELECT * FROM test.kafka', ignore_error=True) @@ -1009,6 +1008,9 @@ def test_kafka_protobuf(kafka_cluster): @pytest.mark.timeout(180) def test_kafka_string_field_on_first_position_in_protobuf(kafka_cluster): # https://github.com/ClickHouse/ClickHouse/issues/12615 + kafka_produce_protobuf_social('string_field_on_first_position_in_protobuf', 0, 20) + kafka_produce_protobuf_social('string_field_on_first_position_in_protobuf', 20, 1) + kafka_produce_protobuf_social('string_field_on_first_position_in_protobuf', 21, 29) instance.query(''' CREATE TABLE test.kafka ( @@ -1021,14 +1023,8 @@ SETTINGS kafka_group_name = 'string_field_on_first_position_in_protobuf', kafka_format = 'Protobuf', kafka_schema = 'social:User'; - - SELECT * FROM test.kafka; ''') - kafka_produce_protobuf_social('string_field_on_first_position_in_protobuf', 0, 20) - kafka_produce_protobuf_social('string_field_on_first_position_in_protobuf', 20, 1) - kafka_produce_protobuf_social('string_field_on_first_position_in_protobuf', 21, 29) - result = instance.query('SELECT * FROM test.kafka', ignore_error=True) expected = '''\ John Doe 0 1000000 @@ -1170,7 +1166,7 @@ def test_kafka_materialized_view(kafka_cluster): kafka_check_result(result, True) @pytest.mark.timeout(180) -def test_librdkafka_snappy_regression(kafka_cluster): +def test_librdkafka_compression(kafka_cluster): """ Regression for UB in snappy-c (that is used in librdkafka), backport pr is [1]. @@ -1180,55 +1176,63 @@ def test_librdkafka_snappy_regression(kafka_cluster): Example of corruption: 2020.12.10 09:59:56.831507 [ 20 ] {} void DB::StorageKafka::threadFunc(size_t): Code: 27, e.displayText() = DB::Exception: Cannot parse input: expected '"' before: 'foo"}': (while reading the value of key value): (at row 1) -, Stack trace (when copying this message, always include the lines below): + + To trigger this regression there should duplicated messages + + Orignal reproducer is: + $ gcc --version |& fgrep gcc + gcc (GCC) 10.2.0 + $ yes foobarbaz | fold -w 80 | head -n10 >| in-… + $ make clean && make CFLAGS='-Wall -g -O2 -ftree-loop-vectorize -DNDEBUG=1 -DSG=1 -fPIC' + $ ./verify in + final comparision of in failed at 20 of 100 + """ - # create topic with snappy compression - admin_client = admin.AdminClient({'bootstrap.servers': 'localhost:9092'}) - topic_snappy = admin.NewTopic(topic='snappy_regression', num_partitions=1, replication_factor=1, config={ - 'compression.type': 'snappy', - }) - admin_client.create_topics(new_topics=[topic_snappy], validate_only=False) - - instance.query(''' - CREATE TABLE test.kafka (key UInt64, value String) - ENGINE = Kafka - SETTINGS kafka_broker_list = 'kafka1:19092', - kafka_topic_list = 'snappy_regression', - kafka_group_name = 'ch_snappy_regression', - kafka_format = 'JSONEachRow'; - ''') + supported_compression_types = ['gzip', 'snappy', 'lz4', 'zstd', 'uncompressed'] messages = [] expected = [] - # To trigger this regression there should duplicated messages - # Orignal reproducer is: - # - # $ gcc --version |& fgrep gcc - # gcc (GCC) 10.2.0 - # $ yes foobarbaz | fold -w 80 | head -n10 >| in-… - # $ make clean && make CFLAGS='-Wall -g -O2 -ftree-loop-vectorize -DNDEBUG=1 -DSG=1 -fPIC' - # $ ./verify in - # final comparision of in failed at 20 of 100 + value = 'foobarbaz'*10 number_of_messages = 50 for i in range(number_of_messages): messages.append(json.dumps({'key': i, 'value': value})) expected.append(f'{i}\t{value}') - kafka_produce('snappy_regression', messages) expected = '\n'.join(expected) - while True: - result = instance.query('SELECT * FROM test.kafka') - rows = len(result.strip('\n').split('\n')) - print(rows) - if rows == number_of_messages: - break + for compression_type in supported_compression_types: + print(('Check compression {}'.format(compression_type))) - assert TSV(result) == TSV(expected) + topic_name = 'test_librdkafka_compression_{}'.format(compression_type) + admin_client = admin.AdminClient({'bootstrap.servers': 'localhost:9092'}) + topic = admin.NewTopic(topic=topic_name, num_partitions=1, replication_factor=1, config={ + 'compression.type': compression_type, + }) + admin_client.create_topics(new_topics=[topic], validate_only=False) - instance.query('DROP TABLE test.kafka') + instance.query(''' + CREATE TABLE test.kafka (key UInt64, value String) + ENGINE = Kafka + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = '{topic_name}', + kafka_group_name = '{topic_name}_group', + kafka_format = 'JSONEachRow', + kafka_flush_interval_ms = 1000; + CREATE MATERIALIZED VIEW test.consumer Engine=Log AS + SELECT * FROM test.kafka; + '''.format(topic_name=topic_name) ) + + kafka_produce(topic_name, messages) + + instance.wait_for_log_line("Committed offset {}".format(number_of_messages)) + + result = instance.query('SELECT * FROM test.consumer') + assert TSV(result) == TSV(expected) + + instance.query('DROP TABLE test.kafka SYNC') + instance.query('DROP TABLE test.consumer SYNC') @pytest.mark.timeout(180) def test_kafka_materialized_view_with_subquery(kafka_cluster): @@ -1577,9 +1581,6 @@ def test_kafka_commit_on_block_write(kafka_cluster): DROP TABLE test.kafka; ''') - while int(instance.query("SELECT count() FROM system.tables WHERE database='test' AND name='kafka'")) == 1: - time.sleep(1) - instance.query(''' CREATE TABLE test.kafka (key UInt64, value UInt64) ENGINE = Kafka @@ -1874,7 +1875,8 @@ def test_kafka_lot_of_partitions_partial_commit_of_bulk(kafka_cluster): kafka_topic_list = 'topic_with_multiple_partitions2', kafka_group_name = 'topic_with_multiple_partitions2', kafka_format = 'JSONEachRow', - kafka_max_block_size = 211; + kafka_max_block_size = 211, + kafka_flush_interval_ms = 500; CREATE TABLE test.view (key UInt64, value UInt64) ENGINE = MergeTree() ORDER BY key; @@ -1892,7 +1894,7 @@ def test_kafka_lot_of_partitions_partial_commit_of_bulk(kafka_cluster): messages.append("\n".join(rows)) kafka_produce('topic_with_multiple_partitions2', messages) - time.sleep(30) + instance.wait_for_log_line('kafka.*Stalled', repetitions=5) result = instance.query('SELECT count(), uniqExact(key), max(key) FROM test.view') print(result) @@ -1961,7 +1963,8 @@ def test_kafka_rebalance(kafka_cluster): kafka_topic_list = 'topic_with_multiple_partitions', kafka_group_name = 'rebalance_test_group', kafka_format = 'JSONEachRow', - kafka_max_block_size = 33; + kafka_max_block_size = 33, + kafka_flush_interval_ms = 500; CREATE MATERIALIZED VIEW test.{0}_mv TO test.destination AS SELECT key, @@ -1975,21 +1978,15 @@ def test_kafka_rebalance(kafka_cluster): FROM test.{0}; '''.format(table_name)) # kafka_cluster.open_bash_shell('instance') - while int( - instance.query("SELECT count() FROM test.destination WHERE _consumed_by='{}'".format(table_name))) == 0: - print(("Waiting for test.kafka_consumer{} to start consume".format(consumer_index))) - time.sleep(1) + # Waiting for test.kafka_consumerX to start consume ... + instance.wait_for_log_line('kafka_consumer{}.*Polled offset [0-9]+'.format(consumer_index)) cancel.set() # I leave last one working by intent (to finish consuming after all rebalances) for consumer_index in range(NUMBER_OF_CONSURRENT_CONSUMERS - 1): print(("Dropping test.kafka_consumer{}".format(consumer_index))) - instance.query('DROP TABLE IF EXISTS test.kafka_consumer{}'.format(consumer_index)) - while int(instance.query( - "SELECT count() FROM system.tables WHERE database='test' AND name='kafka_consumer{}'".format( - consumer_index))) == 1: - time.sleep(1) + instance.query('DROP TABLE IF EXISTS test.kafka_consumer{} SYNC'.format(consumer_index)) # print(instance.query('SELECT count(), uniqExact(key), max(key) + 1 FROM test.destination')) # kafka_cluster.open_bash_shell('instance') @@ -2042,9 +2039,9 @@ def test_kafka_rebalance(kafka_cluster): assert result == 1, 'Messages from kafka get duplicated!' -@pytest.mark.timeout(1200) +@pytest.mark.timeout(120) def test_kafka_no_holes_when_write_suffix_failed(kafka_cluster): - messages = [json.dumps({'key': j + 1, 'value': 'x' * 300}) for j in range(1)] + messages = [json.dumps({'key': j + 1, 'value': 'x' * 300}) for j in range(22)] kafka_produce('no_holes_when_write_suffix_failed', messages) instance.query(''' @@ -2060,39 +2057,28 @@ def test_kafka_no_holes_when_write_suffix_failed(kafka_cluster): kafka_max_block_size = 20, kafka_flush_interval_ms = 2000; - SELECT * FROM test.kafka LIMIT 1; /* do subscription & assignment in advance (it can take different time, test rely on timing, so can flap otherwise) */ + CREATE TABLE test.view (key UInt64, value String) + ENGINE = ReplicatedMergeTree('/clickhouse/kafkatest/tables/no_holes_when_write_suffix_failed', 'node1') + ORDER BY key; ''') - messages = [json.dumps({'key': j + 1, 'value': 'x' * 300}) for j in range(22)] - kafka_produce('no_holes_when_write_suffix_failed', messages) - # init PartitionManager (it starts container) earlier pm = PartitionManager() instance.query(''' - CREATE TABLE test.view (key UInt64, value String) - ENGINE = ReplicatedMergeTree('/clickhouse/kafkatest/tables/no_holes_when_write_suffix_failed', 'node1') - ORDER BY key; - CREATE MATERIALIZED VIEW test.consumer TO test.view AS SELECT * FROM test.kafka - WHERE NOT sleepEachRow(1); + WHERE NOT sleepEachRow(0.25); ''') + instance.wait_for_log_line("Polled batch of 20 messages") # the tricky part here is that disconnect should happen after write prefix, but before write suffix - # so i use sleepEachRow - - time.sleep(3) + # we have 0.25 (sleepEachRow) * 20 ( Rows ) = 5 sec window after "Polled batch of 20 messages" + # while materialized view is working to inject zookeeper failure pm.drop_instance_zk_connections(instance) - time.sleep(20) + instance.wait_for_log_line("Error.*(session has been expired|Connection loss).*while write prefix to view") pm.heal_all() - - # connection restored and it will take a while until next block will be flushed - # it takes years on CI :\ - time.sleep(45) - - # as it's a bit tricky to hit the proper moment - let's check in logs if we did it correctly - assert instance.contains_in_log("ZooKeeper session has been expired.: while write prefix to view") + instance.wait_for_log_line("Committed offset 22") result = instance.query('SELECT count(), uniqExact(key), max(key) FROM test.view') print(result) @@ -2146,7 +2132,7 @@ def test_commits_of_unprocessed_messages_on_drop(kafka_cluster): kafka_produce('commits_of_unprocessed_messages_on_drop', messages) instance.query(''' - DROP TABLE IF EXISTS test.destination; + DROP TABLE IF EXISTS test.destination SYNC; CREATE TABLE test.destination ( key UInt64, value UInt64, @@ -2166,7 +2152,8 @@ def test_commits_of_unprocessed_messages_on_drop(kafka_cluster): kafka_topic_list = 'commits_of_unprocessed_messages_on_drop', kafka_group_name = 'commits_of_unprocessed_messages_on_drop_test_group', kafka_format = 'JSONEachRow', - kafka_max_block_size = 1000; + kafka_max_block_size = 1000, + kafka_flush_interval_ms = 1000; CREATE MATERIALIZED VIEW test.kafka_consumer TO test.destination AS SELECT @@ -2180,9 +2167,8 @@ def test_commits_of_unprocessed_messages_on_drop(kafka_cluster): FROM test.kafka; ''') - while int(instance.query("SELECT count() FROM test.destination")) == 0: - print("Waiting for test.kafka_consumer to start consume") - time.sleep(1) + # Waiting for test.kafka_consumer to start consume + instance.wait_for_log_line('Committed offset [0-9]+') cancel = threading.Event() @@ -2195,14 +2181,14 @@ def test_commits_of_unprocessed_messages_on_drop(kafka_cluster): messages.append(json.dumps({'key': i[0], 'value': i[0]})) i[0] += 1 kafka_produce('commits_of_unprocessed_messages_on_drop', messages) - time.sleep(1) + time.sleep(0.5) kafka_thread = threading.Thread(target=produce) kafka_thread.start() - time.sleep(12) + time.sleep(4) instance.query(''' - DROP TABLE test.kafka; + DROP TABLE test.kafka SYNC; ''') instance.query(''' @@ -2212,11 +2198,12 @@ def test_commits_of_unprocessed_messages_on_drop(kafka_cluster): kafka_topic_list = 'commits_of_unprocessed_messages_on_drop', kafka_group_name = 'commits_of_unprocessed_messages_on_drop_test_group', kafka_format = 'JSONEachRow', - kafka_max_block_size = 10000; + kafka_max_block_size = 10000, + kafka_flush_interval_ms = 1000; ''') cancel.set() - time.sleep(15) + instance.wait_for_log_line('kafka.*Stalled', repetitions=5) # kafka_cluster.open_bash_shell('instance') # SELECT key, _timestamp, _offset FROM test.destination where runningDifference(key) <> 1 ORDER BY key; @@ -2225,8 +2212,8 @@ def test_commits_of_unprocessed_messages_on_drop(kafka_cluster): print(result) instance.query(''' - DROP TABLE test.kafka_consumer; - DROP TABLE test.destination; + DROP TABLE test.kafka_consumer SYNC; + DROP TABLE test.destination SYNC; ''') kafka_thread.join() @@ -2245,7 +2232,8 @@ def test_bad_reschedule(kafka_cluster): kafka_topic_list = 'test_bad_reschedule', kafka_group_name = 'test_bad_reschedule', kafka_format = 'JSONEachRow', - kafka_max_block_size = 1000; + kafka_max_block_size = 1000, + kafka_flush_interval_ms = 1000; CREATE MATERIALIZED VIEW test.destination Engine=Log AS SELECT @@ -2260,21 +2248,19 @@ def test_bad_reschedule(kafka_cluster): FROM test.kafka; ''') - while int(instance.query("SELECT count() FROM test.destination")) < 20000: - print("Waiting for consume") - time.sleep(1) + instance.wait_for_log_line("Committed offset 20000") assert int(instance.query("SELECT max(consume_ts) - min(consume_ts) FROM test.destination")) < 8 @pytest.mark.timeout(300) def test_kafka_duplicates_when_commit_failed(kafka_cluster): - messages = [json.dumps({'key': j + 1, 'value': 'x' * 300}) for j in range(1)] + messages = [json.dumps({'key': j + 1, 'value': 'x' * 300}) for j in range(22)] kafka_produce('duplicates_when_commit_failed', messages) instance.query(''' - DROP TABLE IF EXISTS test.view; - DROP TABLE IF EXISTS test.consumer; + DROP TABLE IF EXISTS test.view SYNC; + DROP TABLE IF EXISTS test.consumer SYNC; CREATE TABLE test.kafka (key UInt64, value String) ENGINE = Kafka @@ -2285,51 +2271,42 @@ def test_kafka_duplicates_when_commit_failed(kafka_cluster): kafka_max_block_size = 20, kafka_flush_interval_ms = 1000; - SELECT * FROM test.kafka LIMIT 1; /* do subscription & assignment in advance (it can take different time, test rely on timing, so can flap otherwise) */ - ''') - - messages = [json.dumps({'key': j + 1, 'value': 'x' * 300}) for j in range(22)] - kafka_produce('duplicates_when_commit_failed', messages) - - instance.query(''' CREATE TABLE test.view (key UInt64, value String) ENGINE = MergeTree() ORDER BY key; - - CREATE MATERIALIZED VIEW test.consumer TO test.view AS - SELECT * FROM test.kafka - WHERE NOT sleepEachRow(0.5); ''') - # print time.strftime("%m/%d/%Y %H:%M:%S") - time.sleep(3) # MV will work for 10 sec, after that commit should happen, we want to pause before + instance.query(''' + CREATE MATERIALIZED VIEW test.consumer TO test.view AS + SELECT * FROM test.kafka + WHERE NOT sleepEachRow(0.25); + ''') - # print time.strftime("%m/%d/%Y %H:%M:%S") + instance.wait_for_log_line("Polled batch of 20 messages") + # the tricky part here is that disconnect should happen after write prefix, but before we do commit + # we have 0.25 (sleepEachRow) * 20 ( Rows ) = 5 sec window after "Polled batch of 20 messages" + # while materialized view is working to inject zookeeper failure kafka_cluster.pause_container('kafka1') - # that timeout it VERY important, and picked after lot of experiments - # when too low (<30sec) librdkafka will not report any timeout (alternative is to decrease the default session timeouts for librdkafka) - # when too high (>50sec) broker will decide to remove us from the consumer group, and will start answering "Broker: Unknown member" - time.sleep(42) - # print time.strftime("%m/%d/%Y %H:%M:%S") + # if we restore the connection too fast (<30sec) librdkafka will not report any timeout + # (alternative is to decrease the default session timeouts for librdkafka) + # + # when the delay is too long (>50sec) broker will decide to remove us from the consumer group, + # and will start answering "Broker: Unknown member" + instance.wait_for_log_line("Exception during commit attempt: Local: Waiting for coordinator", timeout=45) + instance.wait_for_log_line("All commit attempts failed", look_behind_lines=500) + kafka_cluster.unpause_container('kafka1') # kafka_cluster.open_bash_shell('instance') - - # connection restored and it will take a while until next block will be flushed - # it takes years on CI :\ - time.sleep(30) - - # as it's a bit tricky to hit the proper moment - let's check in logs if we did it correctly - assert instance.contains_in_log("Local: Waiting for coordinator") - assert instance.contains_in_log("All commit attempts failed") + instance.wait_for_log_line("Committed offset 22") result = instance.query('SELECT count(), uniqExact(key), max(key) FROM test.view') print(result) instance.query(''' - DROP TABLE test.consumer; - DROP TABLE test.view; + DROP TABLE test.consumer SYNC; + DROP TABLE test.view SYNC; ''') # After https://github.com/edenhill/librdkafka/issues/2631 @@ -2392,9 +2369,8 @@ def test_premature_flush_on_eof(kafka_cluster): # all subscriptions/assignments done during select, so it start sending data to test.destination # immediately after creation of MV - time.sleep(1.5) # that sleep is needed to ensure that first poll finished, and at least one 'empty' polls happened. - # Empty poll before the fix were leading to premature flush. - # TODO: wait for messages in log: "Polled batch of 1 messages", followed by "Stalled" + instance.wait_for_log_line("Polled batch of 1 messages") + instance.wait_for_log_line("Stalled") # produce more messages after delay kafka_produce('premature_flush_on_eof', messages) @@ -2402,7 +2378,7 @@ def test_premature_flush_on_eof(kafka_cluster): # data was not flushed yet (it will be flushed 7.5 sec after creating MV) assert int(instance.query("SELECT count() FROM test.destination")) == 0 - time.sleep(9) # TODO: wait for messages in log: "Committed offset ..." + instance.wait_for_log_line("Committed offset 2") # it should be single part, i.e. single insert result = instance.query('SELECT _part, count() FROM test.destination group by _part') @@ -2414,10 +2390,10 @@ def test_premature_flush_on_eof(kafka_cluster): ''') -@pytest.mark.timeout(180) +@pytest.mark.timeout(120) def test_kafka_unavailable(kafka_cluster): - messages = [json.dumps({'key': j + 1, 'value': j + 1}) for j in range(20000)] - kafka_produce('test_bad_reschedule', messages) + messages = [json.dumps({'key': j + 1, 'value': j + 1}) for j in range(2000)] + kafka_produce('test_kafka_unavailable', messages) kafka_cluster.pause_container('kafka1') @@ -2425,10 +2401,11 @@ def test_kafka_unavailable(kafka_cluster): CREATE TABLE test.kafka (key UInt64, value UInt64) ENGINE = Kafka SETTINGS kafka_broker_list = 'kafka1:19092', - kafka_topic_list = 'test_bad_reschedule', - kafka_group_name = 'test_bad_reschedule', + kafka_topic_list = 'test_kafka_unavailable', + kafka_group_name = 'test_kafka_unavailable', kafka_format = 'JSONEachRow', - kafka_max_block_size = 1000; + kafka_max_block_size = 1000, + kafka_flush_interval_ms = 1000; CREATE MATERIALIZED VIEW test.destination Engine=Log AS SELECT @@ -2444,19 +2421,22 @@ def test_kafka_unavailable(kafka_cluster): ''') instance.query("SELECT * FROM test.kafka") - instance.query("SELECT count() FROM test.destination") - # enough to trigger issue - time.sleep(30) + instance.wait_for_log_line('brokers are down') + instance.wait_for_log_line('stalled. Reschedule', repetitions=2) + kafka_cluster.unpause_container('kafka1') - while int(instance.query("SELECT count() FROM test.destination")) < 20000: - print("Waiting for consume") - time.sleep(1) - + instance.wait_for_log_line("Committed offset 2000") + assert int(instance.query("SELECT count() FROM test.destination")) == 2000 + time.sleep(5) # needed to give time for kafka client in python test to recovery @pytest.mark.timeout(180) def test_kafka_issue14202(kafka_cluster): + """ + INSERT INTO Kafka Engine from an empty SELECT sub query was leading to failure + """ + instance.query(''' CREATE TABLE test.empty_table ( dt Date, diff --git a/tests/integration/test_storage_postgresql/test.py b/tests/integration/test_storage_postgresql/test.py index 4f567c19f2b..cee495438a2 100644 --- a/tests/integration/test_storage_postgresql/test.py +++ b/tests/integration/test_storage_postgresql/test.py @@ -63,13 +63,13 @@ def test_postgres_conversions(started_cluster): cursor.execute( '''CREATE TABLE IF NOT EXISTS test_types ( a smallint, b integer, c bigint, d real, e double precision, f serial, g bigserial, - h timestamp, i date, j numeric(5, 5), k decimal(5, 5))''') + h timestamp, i date, j decimal(5, 3), k numeric)''') node1.query(''' INSERT INTO TABLE FUNCTION postgresql('postgres1:5432', 'clickhouse', 'test_types', 'postgres', 'mysecretpassword') VALUES - (-32768, -2147483648, -9223372036854775808, 1.12345, 1.1234567890, 2147483647, 9223372036854775807, '2000-05-12 12:12:12', '2000-05-12', 0.2, 0.2)''') + (-32768, -2147483648, -9223372036854775808, 1.12345, 1.1234567890, 2147483647, 9223372036854775807, '2000-05-12 12:12:12', '2000-05-12', 22.222, 22.222)''') result = node1.query(''' - SELECT * FROM postgresql('postgres1:5432', 'clickhouse', 'test_types', 'postgres', 'mysecretpassword')''') - assert(result == '-32768\t-2147483648\t-9223372036854775808\t1.12345\t1.123456789\t2147483647\t9223372036854775807\t2000-05-12 12:12:12\t2000-05-12\t0.20000\t0.20000\n') + SELECT a, b, c, d, e, f, g, h, i, j, toDecimal128(k, 3) FROM postgresql('postgres1:5432', 'clickhouse', 'test_types', 'postgres', 'mysecretpassword')''') + assert(result == '-32768\t-2147483648\t-9223372036854775808\t1.12345\t1.123456789\t2147483647\t9223372036854775807\t2000-05-12 12:12:12\t2000-05-12\t22.222\t22.222\n') cursor.execute( '''CREATE TABLE IF NOT EXISTS test_array_dimensions diff --git a/tests/integration/test_storage_rabbitmq/test.py b/tests/integration/test_storage_rabbitmq/test.py index 911f6d144f9..ca89ebdea0a 100644 --- a/tests/integration/test_storage_rabbitmq/test.py +++ b/tests/integration/test_storage_rabbitmq/test.py @@ -1912,6 +1912,59 @@ def test_rabbitmq_no_connection_at_startup(rabbitmq_cluster): assert int(result) == messages_num, 'ClickHouse lost some messages: {}'.format(result) +@pytest.mark.timeout(120) +def test_rabbitmq_format_factory_settings(rabbitmq_cluster): + instance.query(''' + CREATE TABLE test.format_settings ( + id String, date DateTime + ) ENGINE = RabbitMQ + SETTINGS rabbitmq_host_port = 'rabbitmq1:5672', + rabbitmq_exchange_name = 'format_settings', + rabbitmq_format = 'JSONEachRow', + date_time_input_format = 'best_effort'; + ''') + + credentials = pika.PlainCredentials('root', 'clickhouse') + parameters = pika.ConnectionParameters('localhost', 5672, '/', credentials) + connection = pika.BlockingConnection(parameters) + channel = connection.channel() + + message = json.dumps({"id":"format_settings_test","date":"2021-01-19T14:42:33.1829214Z"}) + expected = instance.query('''SELECT parseDateTimeBestEffort(CAST('2021-01-19T14:42:33.1829214Z', 'String'))''') + + channel.basic_publish(exchange='format_settings', routing_key='', body=message) + result = '' + while True: + result = instance.query('SELECT date FROM test.format_settings') + if result == expected: + break; + + instance.query(''' + DROP TABLE IF EXISTS test.view; + DROP TABLE IF EXISTS test.consumer; + CREATE TABLE test.view ( + id String, date DateTime + ) ENGINE = MergeTree ORDER BY id; + CREATE MATERIALIZED VIEW test.consumer TO test.view AS + SELECT * FROM test.format_settings; + ''') + + channel.basic_publish(exchange='format_settings', routing_key='', body=message) + result = '' + while True: + result = instance.query('SELECT date FROM test.view') + if result == expected: + break; + + connection.close() + instance.query(''' + DROP TABLE test.consumer; + DROP TABLE test.format_settings; + ''') + + assert(result == expected) + + if __name__ == '__main__': cluster.start() input("Cluster created, press any key to destroy...") diff --git a/tests/integration/test_storage_s3/test.py b/tests/integration/test_storage_s3/test.py index 1f445feb5a0..3b4c56b524b 100644 --- a/tests/integration/test_storage_s3/test.py +++ b/tests/integration/test_storage_s3/test.py @@ -14,6 +14,9 @@ from helpers.cluster import ClickHouseCluster, ClickHouseInstance logging.getLogger().setLevel(logging.INFO) logging.getLogger().addHandler(logging.StreamHandler()) +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) +CONFIG_PATH = os.path.join(SCRIPT_DIR, './_instances/dummy/configs/config.d/defaultS3.xml') + # Creates S3 bucket for tests and allows anonymous read-write access to it. def prepare_s3_bucket(cluster): @@ -85,7 +88,8 @@ def cluster(): cluster.add_instance("restricted_dummy", main_configs=["configs/config_for_test_remote_host_filter.xml"], with_minio=True) cluster.add_instance("dummy", with_minio=True, main_configs=["configs/defaultS3.xml"]) - cluster.add_instance("s3_max_redirects", with_minio=True, main_configs=["configs/defaultS3.xml"], user_configs=["configs/s3_max_redirects.xml"]) + cluster.add_instance("s3_max_redirects", with_minio=True, main_configs=["configs/defaultS3.xml"], + user_configs=["configs/s3_max_redirects.xml"]) logging.info("Starting cluster...") cluster.start() logging.info("Cluster started") @@ -277,9 +281,9 @@ def test_put_get_with_globs(cluster): # Test multipart put. @pytest.mark.parametrize("maybe_auth,positive", [ - ("", True), + ("", True) # ("'minio','minio123',",True), Redirect with credentials not working with nginx. - ("'wrongid','wrongkey',", False) + # ("'wrongid','wrongkey',", False) ClickHouse crashes in some time after this test, local integration tests run fails. ]) def test_multipart_put(cluster, maybe_auth, positive): # type: (ClickHouseCluster) -> None @@ -397,6 +401,16 @@ def run_s3_mock(cluster): logging.info("S3 mock started") +def replace_config(old, new): + config = open(CONFIG_PATH, 'r') + config_lines = config.readlines() + config.close() + config_lines = [line.replace(old, new) for line in config_lines] + config = open(CONFIG_PATH, 'w') + config.writelines(config_lines) + config.close() + + def test_custom_auth_headers(cluster): table_format = "column1 UInt32, column2 UInt32, column3 UInt32" filename = "test.csv" @@ -409,6 +423,22 @@ def test_custom_auth_headers(cluster): result = run_query(instance, get_query) assert result == '1\t2\t3\n' + instance.query( + "CREATE TABLE test ({table_format}) ENGINE = S3('http://resolver:8080/{bucket}/{file}', 'CSV')".format( + bucket=cluster.minio_restricted_bucket, + file=filename, + table_format=table_format + )) + assert run_query(instance, "SELECT * FROM test") == '1\t2\t3\n' + + replace_config("
Authorization: Bearer TOKEN", "
Authorization: Bearer INVALID_TOKEN") + instance.query("SYSTEM RELOAD CONFIG") + ret, err = instance.query_and_get_answer_with_error("SELECT * FROM test") + assert ret == "" and err != "" + replace_config("
Authorization: Bearer INVALID_TOKEN", "
Authorization: Bearer TOKEN") + instance.query("SYSTEM RELOAD CONFIG") + assert run_query(instance, "SELECT * FROM test") == '1\t2\t3\n' + def test_custom_auth_headers_exclusion(cluster): table_format = "column1 UInt32, column2 UInt32, column3 UInt32" diff --git a/tests/integration/test_system_clusters_actual_information/__init__.py b/tests/integration/test_system_clusters_actual_information/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_system_clusters_actual_information/configs/remote_servers.xml b/tests/integration/test_system_clusters_actual_information/configs/remote_servers.xml new file mode 100644 index 00000000000..b4f30a87520 --- /dev/null +++ b/tests/integration/test_system_clusters_actual_information/configs/remote_servers.xml @@ -0,0 +1,14 @@ + + + + + true + + node_1 + 9000 + + + + + + diff --git a/tests/integration/test_system_clusters_actual_information/configs/users.xml b/tests/integration/test_system_clusters_actual_information/configs/users.xml new file mode 100644 index 00000000000..156cd3a6b59 --- /dev/null +++ b/tests/integration/test_system_clusters_actual_information/configs/users.xml @@ -0,0 +1,8 @@ + + + + + 5 + + + diff --git a/tests/integration/test_system_clusters_actual_information/test.py b/tests/integration/test_system_clusters_actual_information/test.py new file mode 100644 index 00000000000..afbaf53089f --- /dev/null +++ b/tests/integration/test_system_clusters_actual_information/test.py @@ -0,0 +1,60 @@ +import os +import sys +import time + +import pytest + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from helpers.cluster import ClickHouseCluster +from helpers.network import PartitionManager + +cluster = ClickHouseCluster(__file__) +node = cluster.add_instance('node', with_zookeeper=True, main_configs=['configs/remote_servers.xml']) +node_1 = cluster.add_instance('node_1', with_zookeeper=True) + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + + node_1.query('''CREATE TABLE replicated (id UInt32, date Date) ENGINE = + ReplicatedMergeTree('/clickhouse/tables/replicated', 'node_1') ORDER BY id PARTITION BY toYYYYMM(date)''') + + node.query("CREATE TABLE distributed (id UInt32, date Date) ENGINE = Distributed('test_cluster', 'default', 'replicated')") + + yield cluster + + finally: + cluster.shutdown() + + + +def test(started_cluster): + cluster.pause_container("node_1") + + node.query("SYSTEM RELOAD CONFIG") + node.query_and_get_error("SELECT count() FROM distributed SETTINGS receive_timeout=1") + + result = node.query("SELECT errors_count, estimated_recovery_time FROM system.clusters WHERE cluster='test_cluster' and host_name='node_1'") + errors_count, recovery_time = map(int, result.split()) + assert errors_count == 3 + + while True: + time.sleep(1) + + result = node.query("SELECT errors_count, estimated_recovery_time FROM system.clusters WHERE cluster='test_cluster' and host_name='node_1'") + prev_time = recovery_time + errors_count, recovery_time = map(int, result.split()) + + if recovery_time == 0: + break + + assert recovery_time < prev_time + assert errors_count > 0 + + assert recovery_time == 0 + assert errors_count == 0 + + cluster.unpause_container("node_1") + diff --git a/tests/integration/test_system_merges/test.py b/tests/integration/test_system_merges/test.py index 1f2da606cd1..672b637f783 100644 --- a/tests/integration/test_system_merges/test.py +++ b/tests/integration/test_system_merges/test.py @@ -134,7 +134,9 @@ def test_mutation_simple(started_cluster, replicated): result_part = "all_{}_{}_0_{}".format(starting_block, starting_block, starting_block + 1) def alter(): - node1.query("ALTER TABLE {name} UPDATE a = 42 WHERE sleep(2) OR 1".format(name=name)) + node1.query("ALTER TABLE {name} UPDATE a = 42 WHERE sleep(2) OR 1".format(name=name), settings={ + 'mutations_sync': 1, + }) t = threading.Thread(target=alter) t.start() @@ -159,8 +161,6 @@ def test_mutation_simple(started_cluster, replicated): ] t.join() - time.sleep(1.5) - assert node_check.query("SELECT * FROM system.merges WHERE table = '{name}'".format(name=table_name)) == "" finally: diff --git a/tests/integration/test_testkeeper_back_to_back/configs/enable_test_keeper.xml b/tests/integration/test_testkeeper_back_to_back/configs/enable_test_keeper.xml index 79e993b41f7..137b46ab5a9 100644 --- a/tests/integration/test_testkeeper_back_to_back/configs/enable_test_keeper.xml +++ b/tests/integration/test_testkeeper_back_to_back/configs/enable_test_keeper.xml @@ -1,7 +1,23 @@ 9181 - 10000 - 30000 + 1 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + trace + false + + + + + 1 + localhost + 44444 + + diff --git a/tests/integration/test_testkeeper_back_to_back/configs/use_test_keeper.xml b/tests/integration/test_testkeeper_back_to_back/configs/use_test_keeper.xml new file mode 100644 index 00000000000..12dc7fd9447 --- /dev/null +++ b/tests/integration/test_testkeeper_back_to_back/configs/use_test_keeper.xml @@ -0,0 +1,8 @@ + + + + node1 + 9181 + + + diff --git a/tests/integration/test_testkeeper_back_to_back/test.py b/tests/integration/test_testkeeper_back_to_back/test.py index d3a9b742cdd..dd4e1f98cfd 100644 --- a/tests/integration/test_testkeeper_back_to_back/test.py +++ b/tests/integration/test_testkeeper_back_to_back/test.py @@ -8,32 +8,23 @@ from multiprocessing.dummy import Pool cluster = ClickHouseCluster(__file__) node = cluster.add_instance('node', main_configs=['configs/enable_test_keeper.xml', 'configs/logs_conf.xml'], with_zookeeper=True) -from kazoo.client import KazooClient, KazooState - -_genuine_zk_instance = None -_fake_zk_instance = None +from kazoo.client import KazooClient, KazooState, KeeperState def get_genuine_zk(): - global _genuine_zk_instance - if not _genuine_zk_instance: - print("Zoo1", cluster.get_instance_ip("zoo1")) - _genuine_zk_instance = cluster.get_kazoo_client('zoo1') - return _genuine_zk_instance - + print("Zoo1", cluster.get_instance_ip("zoo1")) + return cluster.get_kazoo_client('zoo1') def get_fake_zk(): - global _fake_zk_instance - if not _fake_zk_instance: - print("node", cluster.get_instance_ip("node")) - _fake_zk_instance = KazooClient(hosts=cluster.get_instance_ip("node") + ":9181") - def reset_last_zxid_listener(state): - print("Fake zk callback called for state", state) - global _fake_zk_instance - # reset last_zxid -- fake server doesn't support it - _fake_zk_instance.last_zxid = 0 + print("node", cluster.get_instance_ip("node")) + _fake_zk_instance = KazooClient(hosts=cluster.get_instance_ip("node") + ":9181", timeout=30.0) + def reset_last_zxid_listener(state): + print("Fake zk callback called for state", state) + nonlocal _fake_zk_instance + if state != KazooState.CONNECTED: + _fake_zk_instance._reset() - _fake_zk_instance.add_listener(reset_last_zxid_listener) - _fake_zk_instance.start() + _fake_zk_instance.add_listener(reset_last_zxid_listener) + _fake_zk_instance.start() return _fake_zk_instance def random_string(length): @@ -44,6 +35,15 @@ def create_random_path(prefix="", depth=1): return prefix return create_random_path(os.path.join(prefix, random_string(3)), depth - 1) +def stop_zk(zk): + try: + if zk: + zk.stop() + zk.close() + except: + pass + + @pytest.fixture(scope="module") def started_cluster(): try: @@ -53,44 +53,46 @@ def started_cluster(): finally: cluster.shutdown() - if _genuine_zk_instance: - _genuine_zk_instance.stop() - _genuine_zk_instance.close() - if _fake_zk_instance: - _fake_zk_instance.stop() - _fake_zk_instance.close() def test_simple_commands(started_cluster): - genuine_zk = get_genuine_zk() - fake_zk = get_fake_zk() + try: + genuine_zk = get_genuine_zk() + fake_zk = get_fake_zk() - for zk in [genuine_zk, fake_zk]: - zk.create("/test_simple_commands", b"") - zk.create("/test_simple_commands/somenode1", b"hello") - zk.set("/test_simple_commands/somenode1", b"world") + for zk in [genuine_zk, fake_zk]: + zk.create("/test_simple_commands", b"") + zk.create("/test_simple_commands/somenode1", b"hello") + zk.set("/test_simple_commands/somenode1", b"world") - for zk in [genuine_zk, fake_zk]: - assert zk.exists("/test_simple_commands") - assert zk.exists("/test_simple_commands/somenode1") - print(zk.get("/test_simple_commands/somenode1")) - assert zk.get("/test_simple_commands/somenode1")[0] == b"world" + for zk in [genuine_zk, fake_zk]: + assert zk.exists("/test_simple_commands") + assert zk.exists("/test_simple_commands/somenode1") + print(zk.get("/test_simple_commands/somenode1")) + assert zk.get("/test_simple_commands/somenode1")[0] == b"world" + finally: + for zk in [genuine_zk, fake_zk]: + stop_zk(zk) def test_sequential_nodes(started_cluster): - genuine_zk = get_genuine_zk() - fake_zk = get_fake_zk() - genuine_zk.create("/test_sequential_nodes") - fake_zk.create("/test_sequential_nodes") - for i in range(1, 11): - genuine_zk.create("/test_sequential_nodes/" + ("a" * i) + "-", sequence=True) - genuine_zk.create("/test_sequential_nodes/" + ("b" * i)) - fake_zk.create("/test_sequential_nodes/" + ("a" * i) + "-", sequence=True) - fake_zk.create("/test_sequential_nodes/" + ("b" * i)) + try: + genuine_zk = get_genuine_zk() + fake_zk = get_fake_zk() + genuine_zk.create("/test_sequential_nodes") + fake_zk.create("/test_sequential_nodes") + for i in range(1, 11): + genuine_zk.create("/test_sequential_nodes/" + ("a" * i) + "-", sequence=True) + genuine_zk.create("/test_sequential_nodes/" + ("b" * i)) + fake_zk.create("/test_sequential_nodes/" + ("a" * i) + "-", sequence=True) + fake_zk.create("/test_sequential_nodes/" + ("b" * i)) - genuine_childs = list(sorted(genuine_zk.get_children("/test_sequential_nodes"))) - fake_childs = list(sorted(fake_zk.get_children("/test_sequential_nodes"))) - assert genuine_childs == fake_childs + genuine_childs = list(sorted(genuine_zk.get_children("/test_sequential_nodes"))) + fake_childs = list(sorted(fake_zk.get_children("/test_sequential_nodes"))) + assert genuine_childs == fake_childs + finally: + for zk in [genuine_zk, fake_zk]: + stop_zk(zk) def assert_eq_stats(stat1, stat2): @@ -102,130 +104,141 @@ def assert_eq_stats(stat1, stat2): assert stat1.numChildren == stat2.numChildren def test_stats(started_cluster): - genuine_zk = get_genuine_zk() - fake_zk = get_fake_zk() - genuine_zk.create("/test_stats_nodes") - fake_zk.create("/test_stats_nodes") - genuine_stats = genuine_zk.exists("/test_stats_nodes") - fake_stats = fake_zk.exists("/test_stats_nodes") - assert_eq_stats(genuine_stats, fake_stats) - for i in range(1, 11): - genuine_zk.create("/test_stats_nodes/" + ("a" * i) + "-", sequence=True) - genuine_zk.create("/test_stats_nodes/" + ("b" * i)) - fake_zk.create("/test_stats_nodes/" + ("a" * i) + "-", sequence=True) - fake_zk.create("/test_stats_nodes/" + ("b" * i)) + try: + genuine_zk = get_genuine_zk() + fake_zk = get_fake_zk() + genuine_zk.create("/test_stats_nodes") + fake_zk.create("/test_stats_nodes") + genuine_stats = genuine_zk.exists("/test_stats_nodes") + fake_stats = fake_zk.exists("/test_stats_nodes") + assert_eq_stats(genuine_stats, fake_stats) + for i in range(1, 11): + genuine_zk.create("/test_stats_nodes/" + ("a" * i) + "-", sequence=True) + genuine_zk.create("/test_stats_nodes/" + ("b" * i)) + fake_zk.create("/test_stats_nodes/" + ("a" * i) + "-", sequence=True) + fake_zk.create("/test_stats_nodes/" + ("b" * i)) - genuine_stats = genuine_zk.exists("/test_stats_nodes") - fake_stats = fake_zk.exists("/test_stats_nodes") - assert_eq_stats(genuine_stats, fake_stats) - for i in range(1, 11): - print("/test_stats_nodes/" + ("a" * i) + "-" + "{:010d}".format((i - 1) * 2)) - genuine_zk.delete("/test_stats_nodes/" + ("a" * i) + "-" + "{:010d}".format((i - 1) * 2)) - genuine_zk.delete("/test_stats_nodes/" + ("b" * i)) - fake_zk.delete("/test_stats_nodes/" + ("a" * i) + "-" + "{:010d}".format((i - 1) * 2)) - fake_zk.delete("/test_stats_nodes/" + ("b" * i)) + genuine_stats = genuine_zk.exists("/test_stats_nodes") + fake_stats = fake_zk.exists("/test_stats_nodes") + assert_eq_stats(genuine_stats, fake_stats) + for i in range(1, 11): + print("/test_stats_nodes/" + ("a" * i) + "-" + "{:010d}".format((i - 1) * 2)) + genuine_zk.delete("/test_stats_nodes/" + ("a" * i) + "-" + "{:010d}".format((i - 1) * 2)) + genuine_zk.delete("/test_stats_nodes/" + ("b" * i)) + fake_zk.delete("/test_stats_nodes/" + ("a" * i) + "-" + "{:010d}".format((i - 1) * 2)) + fake_zk.delete("/test_stats_nodes/" + ("b" * i)) - genuine_stats = genuine_zk.exists("/test_stats_nodes") - fake_stats = fake_zk.exists("/test_stats_nodes") - print(genuine_stats) - print(fake_stats) - assert_eq_stats(genuine_stats, fake_stats) - for i in range(100): - genuine_zk.set("/test_stats_nodes", ("q" * i).encode()) - fake_zk.set("/test_stats_nodes", ("q" * i).encode()) + genuine_stats = genuine_zk.exists("/test_stats_nodes") + fake_stats = fake_zk.exists("/test_stats_nodes") + print(genuine_stats) + print(fake_stats) + assert_eq_stats(genuine_stats, fake_stats) + for i in range(100): + genuine_zk.set("/test_stats_nodes", ("q" * i).encode()) + fake_zk.set("/test_stats_nodes", ("q" * i).encode()) - genuine_stats = genuine_zk.exists("/test_stats_nodes") - fake_stats = fake_zk.exists("/test_stats_nodes") - print(genuine_stats) - print(fake_stats) - assert_eq_stats(genuine_stats, fake_stats) + genuine_stats = genuine_zk.exists("/test_stats_nodes") + fake_stats = fake_zk.exists("/test_stats_nodes") + print(genuine_stats) + print(fake_stats) + assert_eq_stats(genuine_stats, fake_stats) + finally: + for zk in [genuine_zk, fake_zk]: + stop_zk(zk) def test_watchers(started_cluster): - genuine_zk = get_genuine_zk() - fake_zk = get_fake_zk() - genuine_zk.create("/test_data_watches") - fake_zk.create("/test_data_watches") - genuine_data_watch_data = None + try: + genuine_zk = get_genuine_zk() + fake_zk = get_fake_zk() + genuine_zk.create("/test_data_watches") + fake_zk.create("/test_data_watches") + genuine_data_watch_data = None - def genuine_callback(event): - print("Genuine data watch called") - nonlocal genuine_data_watch_data - genuine_data_watch_data = event + def genuine_callback(event): + print("Genuine data watch called") + nonlocal genuine_data_watch_data + genuine_data_watch_data = event - fake_data_watch_data = None - def fake_callback(event): - print("Fake data watch called") - nonlocal fake_data_watch_data - fake_data_watch_data = event + fake_data_watch_data = None + def fake_callback(event): + print("Fake data watch called") + nonlocal fake_data_watch_data + fake_data_watch_data = event - genuine_zk.get("/test_data_watches", watch=genuine_callback) - fake_zk.get("/test_data_watches", watch=fake_callback) + genuine_zk.get("/test_data_watches", watch=genuine_callback) + fake_zk.get("/test_data_watches", watch=fake_callback) - print("Calling set genuine") - genuine_zk.set("/test_data_watches", b"a") - print("Calling set fake") - fake_zk.set("/test_data_watches", b"a") - time.sleep(3) + print("Calling set genuine") + genuine_zk.set("/test_data_watches", b"a") + print("Calling set fake") + fake_zk.set("/test_data_watches", b"a") + time.sleep(3) - print("Genuine data", genuine_data_watch_data) - print("Fake data", fake_data_watch_data) - assert genuine_data_watch_data == fake_data_watch_data + print("Genuine data", genuine_data_watch_data) + print("Fake data", fake_data_watch_data) + assert genuine_data_watch_data == fake_data_watch_data - genuine_children = None - def genuine_child_callback(event): - print("Genuine child watch called") - nonlocal genuine_children - genuine_children = event + genuine_children = None + def genuine_child_callback(event): + print("Genuine child watch called") + nonlocal genuine_children + genuine_children = event - fake_children = None - def fake_child_callback(event): - print("Fake child watch called") - nonlocal fake_children - fake_children = event + fake_children = None + def fake_child_callback(event): + print("Fake child watch called") + nonlocal fake_children + fake_children = event - genuine_zk.get_children("/test_data_watches", watch=genuine_child_callback) - fake_zk.get_children("/test_data_watches", watch=fake_child_callback) + genuine_zk.get_children("/test_data_watches", watch=genuine_child_callback) + fake_zk.get_children("/test_data_watches", watch=fake_child_callback) - print("Calling genuine child") - genuine_zk.create("/test_data_watches/child", b"b") - print("Calling fake child") - fake_zk.create("/test_data_watches/child", b"b") + print("Calling genuine child") + genuine_zk.create("/test_data_watches/child", b"b") + print("Calling fake child") + fake_zk.create("/test_data_watches/child", b"b") - time.sleep(3) + time.sleep(3) - print("Genuine children", genuine_children) - print("Fake children", fake_children) - assert genuine_children == fake_children + print("Genuine children", genuine_children) + print("Fake children", fake_children) + assert genuine_children == fake_children + finally: + for zk in [genuine_zk, fake_zk]: + stop_zk(zk) def test_multitransactions(started_cluster): - genuine_zk = get_genuine_zk() - fake_zk = get_fake_zk() - for zk in [genuine_zk, fake_zk]: - zk.create('/test_multitransactions') - t = zk.transaction() - t.create('/test_multitransactions/freddy') - t.create('/test_multitransactions/fred', ephemeral=True) - t.create('/test_multitransactions/smith', sequence=True) - results = t.commit() - assert len(results) == 3 - assert results[0] == '/test_multitransactions/freddy' - assert results[2].startswith('/test_multitransactions/smith0') is True - - from kazoo.exceptions import RolledBackError, NoNodeError - for i, zk in enumerate([genuine_zk, fake_zk]): - print("Processing ZK", i) - t = zk.transaction() - t.create('/test_multitransactions/q') - t.delete('/test_multitransactions/a') - t.create('/test_multitransactions/x') - results = t.commit() - print("Results", results) - assert results[0].__class__ == RolledBackError - assert results[1].__class__ == NoNodeError - assert zk.exists('/test_multitransactions/q') is None - assert zk.exists('/test_multitransactions/a') is None - assert zk.exists('/test_multitransactions/x') is None + try: + genuine_zk = get_genuine_zk() + fake_zk = get_fake_zk() + for zk in [genuine_zk, fake_zk]: + zk.create('/test_multitransactions') + t = zk.transaction() + t.create('/test_multitransactions/freddy') + t.create('/test_multitransactions/fred', ephemeral=True) + t.create('/test_multitransactions/smith', sequence=True) + results = t.commit() + assert len(results) == 3 + assert results[0] == '/test_multitransactions/freddy' + assert results[2].startswith('/test_multitransactions/smith0') is True + from kazoo.exceptions import RolledBackError, NoNodeError + for i, zk in enumerate([genuine_zk, fake_zk]): + print("Processing ZK", i) + t = zk.transaction() + t.create('/test_multitransactions/q') + t.delete('/test_multitransactions/a') + t.create('/test_multitransactions/x') + results = t.commit() + print("Results", results) + assert results[0].__class__ == RolledBackError + assert results[1].__class__ == NoNodeError + assert zk.exists('/test_multitransactions/q') is None + assert zk.exists('/test_multitransactions/a') is None + assert zk.exists('/test_multitransactions/x') is None + finally: + for zk in [genuine_zk, fake_zk]: + stop_zk(zk) def exists(zk, path): result = zk.exists(path) @@ -278,13 +291,13 @@ class Request(object): arg_str = ', '.join([str(k) + "=" + str(v) for k, v in self.arguments.items()]) return "ZKRequest name {} with arguments {}".format(self.name, arg_str) -def generate_requests(iters=1): +def generate_requests(prefix="/", iters=1): requests = [] existing_paths = [] for i in range(iters): for _ in range(100): rand_length = random.randint(0, 10) - path = "/" + path = prefix for j in range(1, rand_length): path = create_random_path(path, 1) existing_paths.append(path) @@ -322,31 +335,43 @@ def generate_requests(iters=1): def test_random_requests(started_cluster): - requests = generate_requests(10) - genuine_zk = get_genuine_zk() - fake_zk = get_fake_zk() - for i, request in enumerate(requests): - genuine_throw = False - fake_throw = False - fake_result = None - genuine_result = None - try: - genuine_result = request.callback(genuine_zk) - except Exception as ex: - genuine_throw = True + try: + requests = generate_requests("/test_random_requests", 10) + print("Generated", len(requests), "requests") + genuine_zk = get_genuine_zk() + fake_zk = get_fake_zk() + genuine_zk.create("/test_random_requests") + fake_zk.create("/test_random_requests") + for i, request in enumerate(requests): + genuine_throw = False + fake_throw = False + fake_result = None + genuine_result = None + try: + genuine_result = request.callback(genuine_zk) + except Exception as ex: + print("i", i, "request", request) + print("Genuine exception", str(ex)) + genuine_throw = True - try: - fake_result = request.callback(fake_zk) - except Exception as ex: - fake_throw = True + try: + fake_result = request.callback(fake_zk) + except Exception as ex: + print("i", i, "request", request) + print("Fake exception", str(ex)) + fake_throw = True - assert fake_throw == genuine_throw, "Fake throw genuine not or vise versa" - assert fake_result == genuine_result, "Zookeeper results differ" - root_children_genuine = [elem for elem in list(sorted(genuine_zk.get_children("/"))) if elem not in ('clickhouse', 'zookeeper')] - root_children_fake = [elem for elem in list(sorted(fake_zk.get_children("/"))) if elem not in ('clickhouse', 'zookeeper')] - assert root_children_fake == root_children_genuine + assert fake_throw == genuine_throw, "Fake throw genuine not or vise versa request {}" + assert fake_result == genuine_result, "Zookeeper results differ" + root_children_genuine = [elem for elem in list(sorted(genuine_zk.get_children("/test_random_requests"))) if elem not in ('clickhouse', 'zookeeper')] + root_children_fake = [elem for elem in list(sorted(fake_zk.get_children("/test_random_requests"))) if elem not in ('clickhouse', 'zookeeper')] + assert root_children_fake == root_children_genuine + finally: + for zk in [genuine_zk, fake_zk]: + stop_zk(zk) def test_end_of_session(started_cluster): + fake_zk1 = None fake_zk2 = None genuine_zk1 = None @@ -401,13 +426,8 @@ def test_end_of_session(started_cluster): assert fake_ephemeral_event == genuine_ephemeral_event finally: - try: - for zk in [fake_zk1, fake_zk2, genuine_zk1, genuine_zk2]: - if zk: - zk.stop() - zk.close() - except: - pass + for zk in [fake_zk1, fake_zk2, genuine_zk1, genuine_zk2]: + stop_zk(zk) def test_end_of_watches_session(started_cluster): fake_zk1 = None @@ -442,91 +462,89 @@ def test_end_of_watches_session(started_cluster): assert dummy_set == 2 finally: - try: - for zk in [fake_zk1, fake_zk2]: - if zk: - zk.stop() - zk.close() - except: - pass + for zk in [fake_zk1, fake_zk2]: + stop_zk(zk) def test_concurrent_watches(started_cluster): - fake_zk = get_fake_zk() - fake_zk.restart() - global_path = "/test_concurrent_watches_0" - fake_zk.create(global_path) + try: + fake_zk = get_fake_zk() + fake_zk.restart() + global_path = "/test_concurrent_watches_0" + fake_zk.create(global_path) - dumb_watch_triggered_counter = 0 - all_paths_triggered = [] + dumb_watch_triggered_counter = 0 + all_paths_triggered = [] - existing_path = [] - all_paths_created = [] - watches_created = 0 - def create_path_and_watch(i): - nonlocal watches_created - nonlocal all_paths_created - fake_zk.ensure_path(global_path + "/" + str(i)) - # new function each time - def dumb_watch(event): - nonlocal dumb_watch_triggered_counter - dumb_watch_triggered_counter += 1 - nonlocal all_paths_triggered - all_paths_triggered.append(event.path) + existing_path = [] + all_paths_created = [] + watches_created = 0 + def create_path_and_watch(i): + nonlocal watches_created + nonlocal all_paths_created + fake_zk.ensure_path(global_path + "/" + str(i)) + # new function each time + def dumb_watch(event): + nonlocal dumb_watch_triggered_counter + dumb_watch_triggered_counter += 1 + nonlocal all_paths_triggered + all_paths_triggered.append(event.path) - fake_zk.get(global_path + "/" + str(i), watch=dumb_watch) - all_paths_created.append(global_path + "/" + str(i)) - watches_created += 1 - existing_path.append(i) + fake_zk.get(global_path + "/" + str(i), watch=dumb_watch) + all_paths_created.append(global_path + "/" + str(i)) + watches_created += 1 + existing_path.append(i) - trigger_called = 0 - def trigger_watch(i): - nonlocal trigger_called - trigger_called += 1 - fake_zk.set(global_path + "/" + str(i), b"somevalue") - try: - existing_path.remove(i) - except: - pass - - def call(total): - for i in range(total): - create_path_and_watch(random.randint(0, 1000)) - time.sleep(random.random() % 0.5) + trigger_called = 0 + def trigger_watch(i): + nonlocal trigger_called + trigger_called += 1 + fake_zk.set(global_path + "/" + str(i), b"somevalue") try: - rand_num = random.choice(existing_path) - trigger_watch(rand_num) - except: - pass - while existing_path: - try: - rand_num = random.choice(existing_path) - trigger_watch(rand_num) + existing_path.remove(i) except: pass - p = Pool(10) - arguments = [100] * 10 - watches_must_be_created = sum(arguments) - watches_trigger_must_be_called = sum(arguments) - watches_must_be_triggered = sum(arguments) - p.map(call, arguments) - p.close() + def call(total): + for i in range(total): + create_path_and_watch(random.randint(0, 1000)) + time.sleep(random.random() % 0.5) + try: + rand_num = random.choice(existing_path) + trigger_watch(rand_num) + except: + pass + while existing_path: + try: + rand_num = random.choice(existing_path) + trigger_watch(rand_num) + except: + pass - # waiting for late watches - for i in range(50): - if dumb_watch_triggered_counter == watches_must_be_triggered: - break + p = Pool(10) + arguments = [100] * 10 + watches_must_be_created = sum(arguments) + watches_trigger_must_be_called = sum(arguments) + watches_must_be_triggered = sum(arguments) + p.map(call, arguments) + p.close() - time.sleep(0.1) + # waiting for late watches + for i in range(50): + if dumb_watch_triggered_counter == watches_must_be_triggered: + break - assert watches_created == watches_must_be_created - assert trigger_called >= watches_trigger_must_be_called - assert len(existing_path) == 0 - if dumb_watch_triggered_counter != watches_must_be_triggered: - print("All created paths", all_paths_created) - print("All triggerred paths", all_paths_triggered) - print("All paths len", len(all_paths_created)) - print("All triggered len", len(all_paths_triggered)) - print("Diff", list(set(all_paths_created) - set(all_paths_triggered))) + time.sleep(0.1) - assert dumb_watch_triggered_counter == watches_must_be_triggered + assert watches_created == watches_must_be_created + assert trigger_called >= watches_trigger_must_be_called + assert len(existing_path) == 0 + if dumb_watch_triggered_counter != watches_must_be_triggered: + print("All created paths", all_paths_created) + print("All triggerred paths", all_paths_triggered) + print("All paths len", len(all_paths_created)) + print("All triggered len", len(all_paths_triggered)) + print("Diff", list(set(all_paths_created) - set(all_paths_triggered))) + + assert dumb_watch_triggered_counter == watches_must_be_triggered + finally: + stop_zk(fake_zk) diff --git a/tests/integration/test_testkeeper_multinode_blocade_leader/__init__.py b/tests/integration/test_testkeeper_multinode_blocade_leader/__init__.py new file mode 100644 index 00000000000..e5a0d9b4834 --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_blocade_leader/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/tests/integration/test_testkeeper_multinode_blocade_leader/configs/enable_test_keeper1.xml b/tests/integration/test_testkeeper_multinode_blocade_leader/configs/enable_test_keeper1.xml new file mode 100644 index 00000000000..d60e2536faf --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_blocade_leader/configs/enable_test_keeper1.xml @@ -0,0 +1,41 @@ + + + 9181 + 1 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + 75 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_multinode_blocade_leader/configs/enable_test_keeper2.xml b/tests/integration/test_testkeeper_multinode_blocade_leader/configs/enable_test_keeper2.xml new file mode 100644 index 00000000000..ec5af6f746f --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_blocade_leader/configs/enable_test_keeper2.xml @@ -0,0 +1,41 @@ + + + 9181 + 2 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + 75 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_multinode_blocade_leader/configs/enable_test_keeper3.xml b/tests/integration/test_testkeeper_multinode_blocade_leader/configs/enable_test_keeper3.xml new file mode 100644 index 00000000000..4c8eb9e1d48 --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_blocade_leader/configs/enable_test_keeper3.xml @@ -0,0 +1,41 @@ + + + 9181 + 3 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + 75 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_multinode_blocade_leader/configs/log_conf.xml b/tests/integration/test_testkeeper_multinode_blocade_leader/configs/log_conf.xml new file mode 100644 index 00000000000..318a6bca95d --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_blocade_leader/configs/log_conf.xml @@ -0,0 +1,12 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + diff --git a/tests/integration/test_testkeeper_multinode_blocade_leader/configs/use_test_keeper.xml b/tests/integration/test_testkeeper_multinode_blocade_leader/configs/use_test_keeper.xml new file mode 100644 index 00000000000..b6139005d2f --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_blocade_leader/configs/use_test_keeper.xml @@ -0,0 +1,16 @@ + + + + node1 + 9181 + + + node2 + 9181 + + + node3 + 9181 + + + diff --git a/tests/integration/test_testkeeper_multinode_blocade_leader/test.py b/tests/integration/test_testkeeper_multinode_blocade_leader/test.py new file mode 100644 index 00000000000..47064413b45 --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_blocade_leader/test.py @@ -0,0 +1,373 @@ +import pytest +from helpers.cluster import ClickHouseCluster +import random +import string +import os +import time +from multiprocessing.dummy import Pool +from helpers.network import PartitionManager +from helpers.test_tools import assert_eq_with_retry + +cluster = ClickHouseCluster(__file__) +node1 = cluster.add_instance('node1', main_configs=['configs/enable_test_keeper1.xml', 'configs/log_conf.xml', 'configs/use_test_keeper.xml'], stay_alive=True) +node2 = cluster.add_instance('node2', main_configs=['configs/enable_test_keeper2.xml', 'configs/log_conf.xml', 'configs/use_test_keeper.xml'], stay_alive=True) +node3 = cluster.add_instance('node3', main_configs=['configs/enable_test_keeper3.xml', 'configs/log_conf.xml', 'configs/use_test_keeper.xml'], stay_alive=True) + +from kazoo.client import KazooClient, KazooState + +""" +In this test, we blockade RAFT leader and check that the whole system is +able to recover. It's not a good test because we use ClickHouse's replicated +tables to check connectivity, but they may require special operations (or a long +wait) after session expiration. We don't use kazoo, because this client pretends +to be very smart: SUSPEND sessions, try to recover them, and so on. The test +will be even less predictable than with ClickHouse tables. + +TODO find (or write) not so smart python client. +TODO remove this when jepsen tests will be written. +""" + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + + yield cluster + + finally: + cluster.shutdown() + +def smaller_exception(ex): + return '\n'.join(str(ex).split('\n')[0:2]) + +def wait_node(node): + for _ in range(100): + zk = None + try: + node.query("SELECT * FROM system.zookeeper WHERE path = '/'") + zk = get_fake_zk(node.name, timeout=30.0) + zk.create("/test", sequence=True) + print("node", node.name, "ready") + break + except Exception as ex: + time.sleep(0.2) + print("Waiting until", node.name, "will be ready, exception", ex) + finally: + if zk: + zk.stop() + zk.close() + else: + raise Exception("Can't wait node", node.name, "to become ready") + +def wait_nodes(): + for node in [node1, node2, node3]: + wait_node(node) + + +def get_fake_zk(nodename, timeout=30.0): + _fake_zk_instance = KazooClient(hosts=cluster.get_instance_ip(nodename) + ":9181", timeout=timeout) + def reset_listener(state): + nonlocal _fake_zk_instance + if state != KazooState.CONNECTED: + _fake_zk_instance._reset() + + _fake_zk_instance.add_listener(reset_listener) + _fake_zk_instance.start() + return _fake_zk_instance + + +# in extremely rare case it can take more than 5 minutes in debug build with sanitizer +@pytest.mark.timeout(600) +def test_blocade_leader(started_cluster): + for i in range(100): + wait_nodes() + try: + for i, node in enumerate([node1, node2, node3]): + node.query("CREATE DATABASE IF NOT EXISTS ordinary ENGINE=Ordinary") + node.query("CREATE TABLE IF NOT EXISTS ordinary.t1 (value UInt64) ENGINE = ReplicatedMergeTree('/clickhouse/t1', '{}') ORDER BY tuple()".format(i + 1)) + break + except Exception as ex: + print("Got exception from node", smaller_exception(ex)) + time.sleep(0.1) + + node2.query("INSERT INTO ordinary.t1 SELECT number FROM numbers(10)") + + node1.query("SYSTEM SYNC REPLICA ordinary.t1", timeout=10) + node3.query("SYSTEM SYNC REPLICA ordinary.t1", timeout=10) + + assert_eq_with_retry(node1, "SELECT COUNT() FROM ordinary.t1", "10") + assert_eq_with_retry(node2, "SELECT COUNT() FROM ordinary.t1", "10") + assert_eq_with_retry(node3, "SELECT COUNT() FROM ordinary.t1", "10") + + with PartitionManager() as pm: + pm.partition_instances(node2, node1) + pm.partition_instances(node3, node1) + + for i in range(100): + try: + restart_replica_for_sure(node2, "ordinary.t1", "/clickhouse/t1/replicas/2") + node2.query("INSERT INTO ordinary.t1 SELECT rand() FROM numbers(100)") + break + except Exception as ex: + try: + node2.query("ATTACH TABLE ordinary.t1") + except Exception as attach_ex: + print("Got exception node2", smaller_exception(attach_ex)) + print("Got exception node2", smaller_exception(ex)) + time.sleep(0.5) + else: + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t1', '/clickhouse/t1/replicas/{}'.format(num + 1)) + assert False, "Cannot insert anything node2" + + for i in range(100): + try: + restart_replica_for_sure(node3, "ordinary.t1", "/clickhouse/t1/replicas/3") + node3.query("INSERT INTO ordinary.t1 SELECT rand() FROM numbers(100)") + break + except Exception as ex: + try: + node3.query("ATTACH TABLE ordinary.t1") + except Exception as attach_ex: + print("Got exception node3", smaller_exception(attach_ex)) + print("Got exception node3", smaller_exception(ex)) + time.sleep(0.5) + else: + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t1', '/clickhouse/t1/replicas/{}'.format(num + 1)) + assert False, "Cannot insert anything node3" + + for n, node in enumerate([node1, node2, node3]): + for i in range(100): + try: + restart_replica_for_sure(node, "ordinary.t1", "/clickhouse/t1/replicas/{}".format(n + 1)) + break + except Exception as ex: + try: + node.query("ATTACH TABLE ordinary.t1") + except Exception as attach_ex: + print("Got exception node{}".format(n + 1), smaller_exception(attach_ex)) + + print("Got exception node{}".format(n + 1), smaller_exception(ex)) + time.sleep(0.5) + else: + assert False, "Cannot reconnect for node{}".format(n + 1) + + for i in range(100): + try: + node1.query("INSERT INTO ordinary.t1 SELECT rand() FROM numbers(100)") + break + except Exception as ex: + print("Got exception node1", smaller_exception(ex)) + time.sleep(0.5) + else: + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t1', '/clickhouse/t1/replicas/{}'.format(num + 1)) + assert False, "Cannot insert anything node1" + + for n, node in enumerate([node1, node2, node3]): + for i in range(100): + try: + restart_replica_for_sure(node, "ordinary.t1", "/clickhouse/t1/replicas/{}".format(n + 1)) + node.query("SYSTEM SYNC REPLICA ordinary.t1", timeout=10) + break + except Exception as ex: + try: + node.query("ATTACH TABLE ordinary.t1") + except Exception as attach_ex: + print("Got exception node{}".format(n + 1), smaller_exception(attach_ex)) + + print("Got exception node{}".format(n + 1), smaller_exception(ex)) + time.sleep(0.5) + else: + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t1', '/clickhouse/t1/replicas/{}'.format(num + 1)) + assert False, "Cannot sync replica node{}".format(n+1) + + if node1.query("SELECT COUNT() FROM ordinary.t1") != "310\n": + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t1', '/clickhouse/t1/replicas/{}'.format(num + 1)) + + assert_eq_with_retry(node1, "SELECT COUNT() FROM ordinary.t1", "310") + assert_eq_with_retry(node2, "SELECT COUNT() FROM ordinary.t1", "310") + assert_eq_with_retry(node3, "SELECT COUNT() FROM ordinary.t1", "310") + + +def dump_zk(node, zk_path, replica_path): + print(node.query("SELECT * FROM system.replication_queue FORMAT Vertical")) + print("Replicas") + print(node.query("SELECT * FROM system.replicas FORMAT Vertical")) + print("Replica 2 info") + print(node.query("SELECT * FROM system.zookeeper WHERE path = '{}' FORMAT Vertical".format(zk_path))) + print("Queue") + print(node.query("SELECT * FROM system.zookeeper WHERE path = '{}/queue' FORMAT Vertical".format(replica_path))) + print("Log") + print(node.query("SELECT * FROM system.zookeeper WHERE path = '{}/log' FORMAT Vertical".format(zk_path))) + print("Parts") + print(node.query("SELECT name FROM system.zookeeper WHERE path = '{}/parts' FORMAT Vertical".format(replica_path))) + +def restart_replica_for_sure(node, table_name, zk_replica_path): + fake_zk = None + try: + node.query("DETACH TABLE {}".format(table_name)) + fake_zk = get_fake_zk(node.name) + if fake_zk.exists(zk_replica_path + "/is_active") is not None: + fake_zk.delete(zk_replica_path + "/is_active") + + node.query("ATTACH TABLE {}".format(table_name)) + except Exception as ex: + print("Exception", ex) + raise ex + finally: + if fake_zk: + fake_zk.stop() + fake_zk.close() + + + +# in extremely rare case it can take more than 5 minutes in debug build with sanitizer +@pytest.mark.timeout(600) +def test_blocade_leader_twice(started_cluster): + for i in range(100): + wait_nodes() + try: + for i, node in enumerate([node1, node2, node3]): + node.query("CREATE DATABASE IF NOT EXISTS ordinary ENGINE=Ordinary") + node.query("CREATE TABLE IF NOT EXISTS ordinary.t2 (value UInt64) ENGINE = ReplicatedMergeTree('/clickhouse/t2', '{}') ORDER BY tuple()".format(i + 1)) + break + except Exception as ex: + print("Got exception from node", smaller_exception(ex)) + time.sleep(0.1) + + node2.query("INSERT INTO ordinary.t2 SELECT number FROM numbers(10)") + + node1.query("SYSTEM SYNC REPLICA ordinary.t2", timeout=10) + node3.query("SYSTEM SYNC REPLICA ordinary.t2", timeout=10) + + assert_eq_with_retry(node1, "SELECT COUNT() FROM ordinary.t2", "10") + assert_eq_with_retry(node2, "SELECT COUNT() FROM ordinary.t2", "10") + assert_eq_with_retry(node3, "SELECT COUNT() FROM ordinary.t2", "10") + + with PartitionManager() as pm: + pm.partition_instances(node2, node1) + pm.partition_instances(node3, node1) + + for i in range(100): + try: + restart_replica_for_sure(node2, "ordinary.t2", "/clickhouse/t2/replicas/2") + node2.query("INSERT INTO ordinary.t2 SELECT rand() FROM numbers(100)") + break + except Exception as ex: + try: + node2.query("ATTACH TABLE ordinary.t2") + except Exception as attach_ex: + print("Got exception node2", smaller_exception(attach_ex)) + print("Got exception node2", smaller_exception(ex)) + time.sleep(0.5) + else: + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t2', '/clickhouse/t2/replicas/{}'.format(num + 1)) + assert False, "Cannot reconnect for node2" + + for i in range(100): + try: + restart_replica_for_sure(node3, "ordinary.t2", "/clickhouse/t2/replicas/3") + node3.query("SYSTEM SYNC REPLICA ordinary.t2", timeout=10) + node3.query("INSERT INTO ordinary.t2 SELECT rand() FROM numbers(100)") + break + except Exception as ex: + try: + node3.query("ATTACH TABLE ordinary.t2") + except Exception as attach_ex: + print("Got exception node3", smaller_exception(attach_ex)) + print("Got exception node3", smaller_exception(ex)) + time.sleep(0.5) + else: + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t2', '/clickhouse/t2/replicas/{}'.format(num + 1)) + assert False, "Cannot reconnect for node3" + + node2.query("SYSTEM SYNC REPLICA ordinary.t2", timeout=10) + + assert_eq_with_retry(node2, "SELECT COUNT() FROM ordinary.t2", "210") + assert_eq_with_retry(node3, "SELECT COUNT() FROM ordinary.t2", "210") + + # Total network partition + pm.partition_instances(node3, node2) + + for i in range(10): + try: + node3.query("INSERT INTO ordinary.t2 SELECT rand() FROM numbers(100)") + assert False, "Node3 became leader?" + except Exception as ex: + time.sleep(0.5) + + for i in range(10): + try: + node2.query("INSERT INTO ordinary.t2 SELECT rand() FROM numbers(100)") + assert False, "Node2 became leader?" + except Exception as ex: + time.sleep(0.5) + + for n, node in enumerate([node1, node2, node3]): + for i in range(100): + try: + restart_replica_for_sure(node, "ordinary.t2", "/clickhouse/t2/replicas/{}".format(n + 1)) + break + except Exception as ex: + try: + node.query("ATTACH TABLE ordinary.t2") + except Exception as attach_ex: + print("Got exception node{}".format(n + 1), smaller_exception(attach_ex)) + + print("Got exception node{}".format(n + 1), smaller_exception(ex)) + time.sleep(0.5) + else: + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t2', '/clickhouse/t2/replicas/{}'.format(num + 1)) + assert False, "Cannot reconnect for node{}".format(n + 1) + + for n, node in enumerate([node1, node2, node3]): + for i in range(100): + try: + node.query("INSERT INTO ordinary.t2 SELECT rand() FROM numbers(100)") + break + except Exception as ex: + print("Got exception node{}".format(n + 1), smaller_exception(ex)) + time.sleep(0.5) + else: + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t2', '/clickhouse/t2/replicas/{}'.format(num + 1)) + assert False, "Cannot reconnect for node{}".format(n + 1) + + for i in range(100): + all_done = True + for n, node in enumerate([node1, node2, node3]): + try: + restart_replica_for_sure(node, "ordinary.t2", "/clickhouse/t2/replicas/{}".format(n + 1)) + node.query("SYSTEM SYNC REPLICA ordinary.t2", timeout=10) + break + except Exception as ex: + all_done = False + try: + node.query("ATTACH TABLE ordinary.t2") + except Exception as attach_ex: + print("Got exception node{}".format(n + 1), smaller_exception(attach_ex)) + + print("Got exception node{}".format(n + 1), smaller_exception(ex)) + time.sleep(0.5) + + if all_done: + break + else: + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t2', '/clickhouse/t2/replicas/{}'.format(num + 1)) + assert False, "Cannot reconnect in i {} retries".format(i) + + assert_eq_with_retry(node1, "SELECT COUNT() FROM ordinary.t2", "510") + if node2.query("SELECT COUNT() FROM ordinary.t2") != "510\n": + for num, node in enumerate([node1, node2, node3]): + dump_zk(node, '/clickhouse/t2', '/clickhouse/t2/replicas/{}'.format(num + 1)) + + assert_eq_with_retry(node2, "SELECT COUNT() FROM ordinary.t2", "510") + assert_eq_with_retry(node3, "SELECT COUNT() FROM ordinary.t2", "510") diff --git a/tests/integration/test_testkeeper_multinode_simple/__init__.py b/tests/integration/test_testkeeper_multinode_simple/__init__.py new file mode 100644 index 00000000000..e5a0d9b4834 --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_simple/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/tests/integration/test_testkeeper_multinode_simple/configs/enable_test_keeper1.xml b/tests/integration/test_testkeeper_multinode_simple/configs/enable_test_keeper1.xml new file mode 100644 index 00000000000..d60e2536faf --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_simple/configs/enable_test_keeper1.xml @@ -0,0 +1,41 @@ + + + 9181 + 1 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + 75 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_multinode_simple/configs/enable_test_keeper2.xml b/tests/integration/test_testkeeper_multinode_simple/configs/enable_test_keeper2.xml new file mode 100644 index 00000000000..ec5af6f746f --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_simple/configs/enable_test_keeper2.xml @@ -0,0 +1,41 @@ + + + 9181 + 2 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + 75 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_multinode_simple/configs/enable_test_keeper3.xml b/tests/integration/test_testkeeper_multinode_simple/configs/enable_test_keeper3.xml new file mode 100644 index 00000000000..4c8eb9e1d48 --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_simple/configs/enable_test_keeper3.xml @@ -0,0 +1,41 @@ + + + 9181 + 3 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + 75 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_multinode_simple/configs/log_conf.xml b/tests/integration/test_testkeeper_multinode_simple/configs/log_conf.xml new file mode 100644 index 00000000000..318a6bca95d --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_simple/configs/log_conf.xml @@ -0,0 +1,12 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + diff --git a/tests/integration/test_testkeeper_multinode_simple/configs/use_test_keeper.xml b/tests/integration/test_testkeeper_multinode_simple/configs/use_test_keeper.xml new file mode 100644 index 00000000000..b6139005d2f --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_simple/configs/use_test_keeper.xml @@ -0,0 +1,16 @@ + + + + node1 + 9181 + + + node2 + 9181 + + + node3 + 9181 + + + diff --git a/tests/integration/test_testkeeper_multinode_simple/test.py b/tests/integration/test_testkeeper_multinode_simple/test.py new file mode 100644 index 00000000000..985915e10a1 --- /dev/null +++ b/tests/integration/test_testkeeper_multinode_simple/test.py @@ -0,0 +1,240 @@ +import pytest +from helpers.cluster import ClickHouseCluster +import random +import string +import os +import time +from multiprocessing.dummy import Pool +from helpers.network import PartitionManager +from helpers.test_tools import assert_eq_with_retry + +cluster = ClickHouseCluster(__file__) +node1 = cluster.add_instance('node1', main_configs=['configs/enable_test_keeper1.xml', 'configs/log_conf.xml', 'configs/use_test_keeper.xml'], stay_alive=True) +node2 = cluster.add_instance('node2', main_configs=['configs/enable_test_keeper2.xml', 'configs/log_conf.xml', 'configs/use_test_keeper.xml'], stay_alive=True) +node3 = cluster.add_instance('node3', main_configs=['configs/enable_test_keeper3.xml', 'configs/log_conf.xml', 'configs/use_test_keeper.xml'], stay_alive=True) + +from kazoo.client import KazooClient, KazooState + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + + yield cluster + + finally: + cluster.shutdown() + +def smaller_exception(ex): + return '\n'.join(str(ex).split('\n')[0:2]) + +def wait_node(node): + for _ in range(100): + zk = None + try: + node.query("SELECT * FROM system.zookeeper WHERE path = '/'") + zk = get_fake_zk(node.name, timeout=30.0) + zk.create("/test", sequence=True) + print("node", node.name, "ready") + break + except Exception as ex: + time.sleep(0.2) + print("Waiting until", node.name, "will be ready, exception", ex) + finally: + if zk: + zk.stop() + zk.close() + else: + raise Exception("Can't wait node", node.name, "to become ready") + +def wait_nodes(): + for node in [node1, node2, node3]: + wait_node(node) + + +def get_fake_zk(nodename, timeout=30.0): + _fake_zk_instance = KazooClient(hosts=cluster.get_instance_ip(nodename) + ":9181", timeout=timeout) + def reset_listener(state): + nonlocal _fake_zk_instance + print("Fake zk callback called for state", state) + if state != KazooState.CONNECTED: + _fake_zk_instance._reset() + + _fake_zk_instance.add_listener(reset_listener) + _fake_zk_instance.start() + return _fake_zk_instance + +def test_read_write_multinode(started_cluster): + try: + wait_nodes() + node1_zk = get_fake_zk("node1") + node2_zk = get_fake_zk("node2") + node3_zk = get_fake_zk("node3") + + node1_zk.create("/test_read_write_multinode_node1", b"somedata1") + node2_zk.create("/test_read_write_multinode_node2", b"somedata2") + node3_zk.create("/test_read_write_multinode_node3", b"somedata3") + + # stale reads are allowed + while node1_zk.exists("/test_read_write_multinode_node2") is None: + time.sleep(0.1) + + while node1_zk.exists("/test_read_write_multinode_node3") is None: + time.sleep(0.1) + + while node2_zk.exists("/test_read_write_multinode_node3") is None: + time.sleep(0.1) + + assert node3_zk.get("/test_read_write_multinode_node1")[0] == b"somedata1" + assert node2_zk.get("/test_read_write_multinode_node1")[0] == b"somedata1" + assert node1_zk.get("/test_read_write_multinode_node1")[0] == b"somedata1" + + assert node3_zk.get("/test_read_write_multinode_node2")[0] == b"somedata2" + assert node2_zk.get("/test_read_write_multinode_node2")[0] == b"somedata2" + assert node1_zk.get("/test_read_write_multinode_node2")[0] == b"somedata2" + + assert node3_zk.get("/test_read_write_multinode_node3")[0] == b"somedata3" + assert node2_zk.get("/test_read_write_multinode_node3")[0] == b"somedata3" + assert node1_zk.get("/test_read_write_multinode_node3")[0] == b"somedata3" + + finally: + try: + for zk_conn in [node1_zk, node2_zk, node3_zk]: + zk_conn.stop() + zk_conn.close() + except: + pass + + +def test_watch_on_follower(started_cluster): + try: + wait_nodes() + node1_zk = get_fake_zk("node1") + node2_zk = get_fake_zk("node2") + node3_zk = get_fake_zk("node3") + + node1_zk.create("/test_data_watches") + node2_zk.set("/test_data_watches", b"hello") + node3_zk.set("/test_data_watches", b"world") + + node1_data = None + def node1_callback(event): + print("node1 data watch called") + nonlocal node1_data + node1_data = event + + node1_zk.get("/test_data_watches", watch=node1_callback) + + node2_data = None + def node2_callback(event): + print("node2 data watch called") + nonlocal node2_data + node2_data = event + + node2_zk.get("/test_data_watches", watch=node2_callback) + + node3_data = None + def node3_callback(event): + print("node3 data watch called") + nonlocal node3_data + node3_data = event + + node3_zk.get("/test_data_watches", watch=node3_callback) + + node1_zk.set("/test_data_watches", b"somevalue") + time.sleep(3) + + print(node1_data) + print(node2_data) + print(node3_data) + + assert node1_data == node2_data + assert node3_data == node2_data + + finally: + try: + for zk_conn in [node1_zk, node2_zk, node3_zk]: + zk_conn.stop() + zk_conn.close() + except: + pass + + +def test_session_expiration(started_cluster): + try: + wait_nodes() + node1_zk = get_fake_zk("node1") + node2_zk = get_fake_zk("node2") + node3_zk = get_fake_zk("node3", timeout=3.0) + print("Node3 session id", node3_zk._session_id) + + node3_zk.create("/test_ephemeral_node", b"world", ephemeral=True) + + with PartitionManager() as pm: + pm.partition_instances(node3, node2) + pm.partition_instances(node3, node1) + node3_zk.stop() + node3_zk.close() + for _ in range(100): + if node1_zk.exists("/test_ephemeral_node") is None and node2_zk.exists("/test_ephemeral_node") is None: + break + print("Node1 exists", node1_zk.exists("/test_ephemeral_node")) + print("Node2 exists", node2_zk.exists("/test_ephemeral_node")) + time.sleep(0.1) + node1_zk.sync("/") + node2_zk.sync("/") + + assert node1_zk.exists("/test_ephemeral_node") is None + assert node2_zk.exists("/test_ephemeral_node") is None + + finally: + try: + for zk_conn in [node1_zk, node2_zk, node3_zk]: + try: + zk_conn.stop() + zk_conn.close() + except: + pass + except: + pass + + +def test_follower_restart(started_cluster): + try: + wait_nodes() + node1_zk = get_fake_zk("node1") + + node1_zk.create("/test_restart_node", b"hello") + + node3.restart_clickhouse(kill=True) + + node3_zk = get_fake_zk("node3") + + # got data from log + assert node3_zk.get("/test_restart_node")[0] == b"hello" + + finally: + try: + for zk_conn in [node1_zk, node3_zk]: + try: + zk_conn.stop() + zk_conn.close() + except: + pass + except: + pass + + +def test_simple_replicated_table(started_cluster): + wait_nodes() + for i, node in enumerate([node1, node2, node3]): + node.query("CREATE TABLE t (value UInt64) ENGINE = ReplicatedMergeTree('/clickhouse/t', '{}') ORDER BY tuple()".format(i + 1)) + + node2.query("INSERT INTO t SELECT number FROM numbers(10)") + + node1.query("SYSTEM SYNC REPLICA t", timeout=10) + node3.query("SYSTEM SYNC REPLICA t", timeout=10) + + assert_eq_with_retry(node1, "SELECT COUNT() FROM t", "10") + assert_eq_with_retry(node2, "SELECT COUNT() FROM t", "10") + assert_eq_with_retry(node3, "SELECT COUNT() FROM t", "10") diff --git a/tests/integration/test_testkeeper_persistent_log/__init__.py b/tests/integration/test_testkeeper_persistent_log/__init__.py new file mode 100644 index 00000000000..e5a0d9b4834 --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/tests/integration/test_testkeeper_persistent_log/configs/enable_test_keeper.xml b/tests/integration/test_testkeeper_persistent_log/configs/enable_test_keeper.xml new file mode 100644 index 00000000000..e5046f2831d --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log/configs/enable_test_keeper.xml @@ -0,0 +1,22 @@ + + + 9181 + 1 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + trace + + + + + 1 + localhost + 44444 + + + + diff --git a/tests/integration/test_testkeeper_persistent_log/configs/logs_conf.xml b/tests/integration/test_testkeeper_persistent_log/configs/logs_conf.xml new file mode 100644 index 00000000000..318a6bca95d --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log/configs/logs_conf.xml @@ -0,0 +1,12 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + diff --git a/tests/integration/test_testkeeper_persistent_log/configs/use_test_keeper.xml b/tests/integration/test_testkeeper_persistent_log/configs/use_test_keeper.xml new file mode 100644 index 00000000000..2e48e91bca5 --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log/configs/use_test_keeper.xml @@ -0,0 +1,8 @@ + + + + node + 9181 + + + diff --git a/tests/integration/test_testkeeper_persistent_log/test.py b/tests/integration/test_testkeeper_persistent_log/test.py new file mode 100644 index 00000000000..71fee94088f --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log/test.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +import pytest +from helpers.cluster import ClickHouseCluster +import random +import string +import os +import time +from kazoo.client import KazooClient, KazooState + + +cluster = ClickHouseCluster(__file__) + +node = cluster.add_instance('node', main_configs=['configs/enable_test_keeper.xml', 'configs/logs_conf.xml', 'configs/use_test_keeper.xml'], stay_alive=True) + + +def random_string(length): + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length)) + +def create_random_path(prefix="", depth=1): + if depth == 0: + return prefix + return create_random_path(os.path.join(prefix, random_string(3)), depth - 1) + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + + yield cluster + + finally: + cluster.shutdown() + +def get_connection_zk(nodename, timeout=30.0): + _fake_zk_instance = KazooClient(hosts=cluster.get_instance_ip(nodename) + ":9181", timeout=timeout) + def reset_listener(state): + nonlocal _fake_zk_instance + print("Fake zk callback called for state", state) + if state != KazooState.CONNECTED: + _fake_zk_instance._reset() + + _fake_zk_instance.add_listener(reset_listener) + _fake_zk_instance.start() + return _fake_zk_instance + +def test_state_after_restart(started_cluster): + try: + node_zk = None + node_zk2 = None + node_zk = get_connection_zk("node") + + node_zk.create("/test_state_after_restart", b"somevalue") + strs = [] + for i in range(100): + strs.append(random_string(123).encode()) + node_zk.create("/test_state_after_restart/node" + str(i), strs[i]) + + for i in range(100): + if i % 7 == 0: + node_zk.delete("/test_state_after_restart/node" + str(i)) + + node.restart_clickhouse(kill=True) + + node_zk2 = get_connection_zk("node") + + assert node_zk2.get("/test_state_after_restart")[0] == b"somevalue" + for i in range(100): + if i % 7 == 0: + assert node_zk2.exists("/test_state_after_restart/node" + str(i)) is None + else: + assert len(node_zk2.get("/test_state_after_restart/node" + str(i))[0]) == 123 + assert node_zk2.get("/test_state_after_restart/node" + str(i))[0] == strs[i] + finally: + try: + if node_zk is not None: + node_zk.stop() + node_zk.close() + + if node_zk2 is not None: + node_zk2.stop() + node_zk2.close() + except: + pass + + +# http://zookeeper-user.578899.n2.nabble.com/Why-are-ephemeral-nodes-written-to-disk-tp7583403p7583418.html +def test_ephemeral_after_restart(started_cluster): + try: + node_zk = None + node_zk2 = None + node_zk = get_connection_zk("node") + + node_zk.create("/test_ephemeral_after_restart", b"somevalue") + strs = [] + for i in range(100): + strs.append(random_string(123).encode()) + node_zk.create("/test_ephemeral_after_restart/node" + str(i), strs[i], ephemeral=True) + + for i in range(100): + if i % 7 == 0: + node_zk.delete("/test_ephemeral_after_restart/node" + str(i)) + + node.restart_clickhouse(kill=True) + + node_zk2 = get_connection_zk("node") + + assert node_zk2.get("/test_ephemeral_after_restart")[0] == b"somevalue" + for i in range(100): + if i % 7 == 0: + assert node_zk2.exists("/test_ephemeral_after_restart/node" + str(i)) is None + else: + assert len(node_zk2.get("/test_ephemeral_after_restart/node" + str(i))[0]) == 123 + assert node_zk2.get("/test_ephemeral_after_restart/node" + str(i))[0] == strs[i] + finally: + try: + if node_zk is not None: + node_zk.stop() + node_zk.close() + + if node_zk2 is not None: + node_zk2.stop() + node_zk2.close() + except: + pass diff --git a/tests/integration/test_testkeeper_persistent_log_multinode/__init__.py b/tests/integration/test_testkeeper_persistent_log_multinode/__init__.py new file mode 100644 index 00000000000..e5a0d9b4834 --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log_multinode/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/tests/integration/test_testkeeper_persistent_log_multinode/configs/enable_test_keeper1.xml b/tests/integration/test_testkeeper_persistent_log_multinode/configs/enable_test_keeper1.xml new file mode 100644 index 00000000000..009ea95a1a2 --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log_multinode/configs/enable_test_keeper1.xml @@ -0,0 +1,40 @@ + + + 9181 + 1 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_persistent_log_multinode/configs/enable_test_keeper2.xml b/tests/integration/test_testkeeper_persistent_log_multinode/configs/enable_test_keeper2.xml new file mode 100644 index 00000000000..5afe84e8d20 --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log_multinode/configs/enable_test_keeper2.xml @@ -0,0 +1,40 @@ + + + 9181 + 2 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_persistent_log_multinode/configs/enable_test_keeper3.xml b/tests/integration/test_testkeeper_persistent_log_multinode/configs/enable_test_keeper3.xml new file mode 100644 index 00000000000..10a50db1444 --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log_multinode/configs/enable_test_keeper3.xml @@ -0,0 +1,40 @@ + + + 9181 + 3 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_persistent_log_multinode/configs/log_conf.xml b/tests/integration/test_testkeeper_persistent_log_multinode/configs/log_conf.xml new file mode 100644 index 00000000000..318a6bca95d --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log_multinode/configs/log_conf.xml @@ -0,0 +1,12 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + diff --git a/tests/integration/test_testkeeper_persistent_log_multinode/configs/use_test_keeper.xml b/tests/integration/test_testkeeper_persistent_log_multinode/configs/use_test_keeper.xml new file mode 100644 index 00000000000..b6139005d2f --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log_multinode/configs/use_test_keeper.xml @@ -0,0 +1,16 @@ + + + + node1 + 9181 + + + node2 + 9181 + + + node3 + 9181 + + + diff --git a/tests/integration/test_testkeeper_persistent_log_multinode/test.py b/tests/integration/test_testkeeper_persistent_log_multinode/test.py new file mode 100644 index 00000000000..cb9cf5a59d1 --- /dev/null +++ b/tests/integration/test_testkeeper_persistent_log_multinode/test.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +import pytest +from helpers.cluster import ClickHouseCluster +import random +import string +import os +import time + +cluster = ClickHouseCluster(__file__) +node1 = cluster.add_instance('node1', main_configs=['configs/enable_test_keeper1.xml', 'configs/log_conf.xml', 'configs/use_test_keeper.xml'], stay_alive=True) +node2 = cluster.add_instance('node2', main_configs=['configs/enable_test_keeper2.xml', 'configs/log_conf.xml', 'configs/use_test_keeper.xml'], stay_alive=True) +node3 = cluster.add_instance('node3', main_configs=['configs/enable_test_keeper3.xml', 'configs/log_conf.xml', 'configs/use_test_keeper.xml'], stay_alive=True) + +from kazoo.client import KazooClient, KazooState + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + + yield cluster + + finally: + cluster.shutdown() + +def get_fake_zk(nodename, timeout=30.0): + _fake_zk_instance = KazooClient(hosts=cluster.get_instance_ip(nodename) + ":9181", timeout=timeout) + def reset_listener(state): + nonlocal _fake_zk_instance + print("Fake zk callback called for state", state) + if state != KazooState.CONNECTED: + _fake_zk_instance._reset() + + _fake_zk_instance.add_listener(reset_listener) + _fake_zk_instance.start() + return _fake_zk_instance + +def stop_zk(zk): + try: + if zk: + zk.stop() + zk.close() + except: + pass + +def test_restart_multinode(started_cluster): + try: + node1_zk = node2_zk = node3_zk = None + + node1_zk = get_fake_zk("node1") + node2_zk = get_fake_zk("node2") + node3_zk = get_fake_zk("node3") + + for i in range(100): + node1_zk.create("/test_read_write_multinode_node" + str(i), ("somedata" + str(i)).encode()) + + for i in range(100): + if i % 10 == 0: + node1_zk.delete("/test_read_write_multinode_node" + str(i)) + + node2_zk.sync("/test_read_write_multinode_node0") + node3_zk.sync("/test_read_write_multinode_node0") + + for i in range(100): + if i % 10 != 0: + assert node2_zk.get("/test_read_write_multinode_node" + str(i))[0] == ("somedata" + str(i)).encode() + assert node3_zk.get("/test_read_write_multinode_node" + str(i))[0] == ("somedata" + str(i)).encode() + else: + assert node2_zk.exists("/test_read_write_multinode_node" + str(i)) is None + assert node3_zk.exists("/test_read_write_multinode_node" + str(i)) is None + + finally: + for zk in [node1_zk, node2_zk, node3_zk]: + stop_zk(zk) + + node1.restart_clickhouse(kill=True) + node2.restart_clickhouse(kill=True) + node3.restart_clickhouse(kill=True) + for i in range(100): + try: + node1_zk = get_fake_zk("node1") + node2_zk = get_fake_zk("node2") + node3_zk = get_fake_zk("node3") + for i in range(100): + if i % 10 != 0: + assert node1_zk.get("/test_read_write_multinode_node" + str(i))[0] == ("somedata" + str(i)).encode() + assert node2_zk.get("/test_read_write_multinode_node" + str(i))[0] == ("somedata" + str(i)).encode() + assert node3_zk.get("/test_read_write_multinode_node" + str(i))[0] == ("somedata" + str(i)).encode() + else: + assert node1_zk.exists("/test_read_write_multinode_node" + str(i)) is None + assert node2_zk.exists("/test_read_write_multinode_node" + str(i)) is None + assert node3_zk.exists("/test_read_write_multinode_node" + str(i)) is None + break + except Exception as ex: + print("Got exception as ex", ex) + finally: + for zk in [node1_zk, node2_zk, node3_zk]: + stop_zk(zk) diff --git a/tests/integration/test_testkeeper_restore_from_snapshot/__init__.py b/tests/integration/test_testkeeper_restore_from_snapshot/__init__.py new file mode 100644 index 00000000000..e5a0d9b4834 --- /dev/null +++ b/tests/integration/test_testkeeper_restore_from_snapshot/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/tests/integration/test_testkeeper_restore_from_snapshot/configs/enable_test_keeper1.xml b/tests/integration/test_testkeeper_restore_from_snapshot/configs/enable_test_keeper1.xml new file mode 100644 index 00000000000..7d56a9137e9 --- /dev/null +++ b/tests/integration/test_testkeeper_restore_from_snapshot/configs/enable_test_keeper1.xml @@ -0,0 +1,43 @@ + + + 9181 + 1 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + trace + 100 + 10 + 1 + + + + + 1 + node1 + 44444 + true + 70 + + + 2 + node2 + 44444 + true + true + 20 + + + 3 + node3 + 44444 + true + true + 10 + + + + diff --git a/tests/integration/test_testkeeper_restore_from_snapshot/configs/enable_test_keeper2.xml b/tests/integration/test_testkeeper_restore_from_snapshot/configs/enable_test_keeper2.xml new file mode 100644 index 00000000000..e4c031281ac --- /dev/null +++ b/tests/integration/test_testkeeper_restore_from_snapshot/configs/enable_test_keeper2.xml @@ -0,0 +1,43 @@ + + + 9181 + 2 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + trace + 100 + 10 + 1 + + + + + 1 + node1 + 44444 + true + 70 + + + 2 + node2 + 44444 + true + true + 20 + + + 3 + node3 + 44444 + true + true + 10 + + + + diff --git a/tests/integration/test_testkeeper_restore_from_snapshot/configs/enable_test_keeper3.xml b/tests/integration/test_testkeeper_restore_from_snapshot/configs/enable_test_keeper3.xml new file mode 100644 index 00000000000..8db7647c877 --- /dev/null +++ b/tests/integration/test_testkeeper_restore_from_snapshot/configs/enable_test_keeper3.xml @@ -0,0 +1,43 @@ + + + 9181 + 3 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 5000 + 10000 + trace + 100 + 10 + 1 + + + + + 1 + node1 + 44444 + true + 70 + + + 2 + node2 + 44444 + true + true + 20 + + + 3 + node3 + 44444 + true + true + 10 + + + + diff --git a/tests/integration/test_testkeeper_restore_from_snapshot/configs/log_conf.xml b/tests/integration/test_testkeeper_restore_from_snapshot/configs/log_conf.xml new file mode 100644 index 00000000000..318a6bca95d --- /dev/null +++ b/tests/integration/test_testkeeper_restore_from_snapshot/configs/log_conf.xml @@ -0,0 +1,12 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + diff --git a/tests/integration/test_testkeeper_restore_from_snapshot/test.py b/tests/integration/test_testkeeper_restore_from_snapshot/test.py new file mode 100644 index 00000000000..62122751623 --- /dev/null +++ b/tests/integration/test_testkeeper_restore_from_snapshot/test.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +import pytest +from helpers.cluster import ClickHouseCluster +import random +import string +import os +import time + +cluster = ClickHouseCluster(__file__) +node1 = cluster.add_instance('node1', main_configs=['configs/enable_test_keeper1.xml', 'configs/log_conf.xml'], stay_alive=True) +node2 = cluster.add_instance('node2', main_configs=['configs/enable_test_keeper2.xml', 'configs/log_conf.xml'], stay_alive=True) +node3 = cluster.add_instance('node3', main_configs=['configs/enable_test_keeper3.xml', 'configs/log_conf.xml'], stay_alive=True) + +from kazoo.client import KazooClient, KazooState + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + + yield cluster + + finally: + cluster.shutdown() + +def get_fake_zk(nodename, timeout=30.0): + _fake_zk_instance = KazooClient(hosts=cluster.get_instance_ip(nodename) + ":9181", timeout=timeout) + def reset_listener(state): + nonlocal _fake_zk_instance + print("Fake zk callback called for state", state) + if state != KazooState.CONNECTED: + _fake_zk_instance._reset() + + _fake_zk_instance.add_listener(reset_listener) + _fake_zk_instance.start() + return _fake_zk_instance + +def stop_zk(zk): + try: + if zk: + zk.stop() + zk.close() + except: + pass + + +def test_recover_from_snapshot(started_cluster): + try: + node1_zk = node2_zk = node3_zk = None + node1_zk = get_fake_zk("node1") + node2_zk = get_fake_zk("node2") + node3_zk = get_fake_zk("node3") + + node1_zk.create("/test_snapshot_multinode_recover", "somedata".encode()) + + node2_zk.sync("/test_snapshot_multinode_recover") + node3_zk.sync("/test_snapshot_multinode_recover") + + assert node1_zk.get("/test_snapshot_multinode_recover")[0] == b"somedata" + assert node2_zk.get("/test_snapshot_multinode_recover")[0] == b"somedata" + assert node3_zk.get("/test_snapshot_multinode_recover")[0] == b"somedata" + + node3.stop_clickhouse(kill=True) + + # at least we will have 2 snapshots + for i in range(435): + node1_zk.create("/test_snapshot_multinode_recover" + str(i), ("somedata" + str(i)).encode()) + + for i in range(435): + if i % 10 == 0: + node1_zk.delete("/test_snapshot_multinode_recover" + str(i)) + + finally: + for zk in [node1_zk, node2_zk, node3_zk]: + stop_zk(zk) + + # stale node should recover from leader's snapshot + # with some sanitizers can start longer than 5 seconds + node3.start_clickhouse(20) + + try: + node1_zk = node2_zk = node3_zk = None + node1_zk = get_fake_zk("node1") + node2_zk = get_fake_zk("node2") + node3_zk = get_fake_zk("node3") + + node1_zk.sync("/test_snapshot_multinode_recover") + node2_zk.sync("/test_snapshot_multinode_recover") + node3_zk.sync("/test_snapshot_multinode_recover") + + assert node1_zk.get("/test_snapshot_multinode_recover")[0] == b"somedata" + assert node2_zk.get("/test_snapshot_multinode_recover")[0] == b"somedata" + assert node3_zk.get("/test_snapshot_multinode_recover")[0] == b"somedata" + + for i in range(435): + if i % 10 != 0: + assert node1_zk.get("/test_snapshot_multinode_recover" + str(i))[0] == ("somedata" + str(i)).encode() + assert node2_zk.get("/test_snapshot_multinode_recover" + str(i))[0] == ("somedata" + str(i)).encode() + assert node3_zk.get("/test_snapshot_multinode_recover" + str(i))[0] == ("somedata" + str(i)).encode() + else: + assert node1_zk.exists("/test_snapshot_multinode_recover" + str(i)) is None + assert node2_zk.exists("/test_snapshot_multinode_recover" + str(i)) is None + assert node3_zk.exists("/test_snapshot_multinode_recover" + str(i)) is None + finally: + for zk in [node1_zk, node2_zk, node3_zk]: + stop_zk(zk) diff --git a/tests/integration/test_testkeeper_snapshots/__init__.py b/tests/integration/test_testkeeper_snapshots/__init__.py new file mode 100644 index 00000000000..e5a0d9b4834 --- /dev/null +++ b/tests/integration/test_testkeeper_snapshots/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/tests/integration/test_testkeeper_snapshots/configs/enable_test_keeper.xml b/tests/integration/test_testkeeper_snapshots/configs/enable_test_keeper.xml new file mode 100644 index 00000000000..f7d3c548f87 --- /dev/null +++ b/tests/integration/test_testkeeper_snapshots/configs/enable_test_keeper.xml @@ -0,0 +1,24 @@ + + + 9181 + 1 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 10 + 5 + 5000 + 10000 + trace + + + + + 1 + localhost + 44444 + + + + diff --git a/tests/integration/test_testkeeper_snapshots/configs/logs_conf.xml b/tests/integration/test_testkeeper_snapshots/configs/logs_conf.xml new file mode 100644 index 00000000000..318a6bca95d --- /dev/null +++ b/tests/integration/test_testkeeper_snapshots/configs/logs_conf.xml @@ -0,0 +1,12 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + diff --git a/tests/integration/test_testkeeper_snapshots/test.py b/tests/integration/test_testkeeper_snapshots/test.py new file mode 100644 index 00000000000..8dece678652 --- /dev/null +++ b/tests/integration/test_testkeeper_snapshots/test.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 + +#!/usr/bin/env python3 +import pytest +from helpers.cluster import ClickHouseCluster +import random +import string +import os +import time +from kazoo.client import KazooClient, KazooState + + +cluster = ClickHouseCluster(__file__) + +# clickhouse itself will use external zookeeper +node = cluster.add_instance('node', main_configs=['configs/enable_test_keeper.xml', 'configs/logs_conf.xml'], stay_alive=True, with_zookeeper=True) + +def random_string(length): + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length)) + +def create_random_path(prefix="", depth=1): + if depth == 0: + return prefix + return create_random_path(os.path.join(prefix, random_string(3)), depth - 1) + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + + yield cluster + + finally: + cluster.shutdown() + +def get_connection_zk(nodename, timeout=30.0): + _fake_zk_instance = KazooClient(hosts=cluster.get_instance_ip(nodename) + ":9181", timeout=timeout) + def reset_listener(state): + nonlocal _fake_zk_instance + print("Fake zk callback called for state", state) + if state != KazooState.CONNECTED: + _fake_zk_instance._reset() + + _fake_zk_instance.add_listener(reset_listener) + _fake_zk_instance.start() + return _fake_zk_instance + +def test_state_after_restart(started_cluster): + try: + node_zk = None + node_zk2 = None + node_zk = get_connection_zk("node") + + node_zk.create("/test_state_after_restart", b"somevalue") + strs = [] + for i in range(100): + strs.append(random_string(123).encode()) + node_zk.create("/test_state_after_restart/node" + str(i), strs[i]) + + existing_children = [] + for i in range(100): + if i % 7 == 0: + node_zk.delete("/test_state_after_restart/node" + str(i)) + else: + existing_children.append("node" + str(i)) + + + node.restart_clickhouse(kill=True) + + node_zk2 = get_connection_zk("node") + + assert node_zk2.get("/test_state_after_restart")[0] == b"somevalue" + for i in range(100): + if i % 7 == 0: + assert node_zk2.exists("/test_state_after_restart/node" + str(i)) is None + else: + data, stat = node_zk2.get("/test_state_after_restart/node" + str(i)) + assert len(data) == 123 + assert data == strs[i] + assert stat.ephemeralOwner == 0 + + assert list(sorted(existing_children)) == list(sorted(node_zk2.get_children("/test_state_after_restart"))) + finally: + try: + if node_zk is not None: + node_zk.stop() + node_zk.close() + + if node_zk2 is not None: + node_zk2.stop() + node_zk2.close() + except: + pass + + +def test_ephemeral_after_restart(started_cluster): + try: + node_zk = None + node_zk2 = None + node_zk = get_connection_zk("node") + + session_id = node_zk._session_id + node_zk.create("/test_ephemeral_after_restart", b"somevalue") + strs = [] + for i in range(100): + strs.append(random_string(123).encode()) + node_zk.create("/test_ephemeral_after_restart/node" + str(i), strs[i], ephemeral=True) + + existing_children = [] + for i in range(100): + if i % 7 == 0: + node_zk.delete("/test_ephemeral_after_restart/node" + str(i)) + else: + existing_children.append("node" + str(i)) + + node.restart_clickhouse(kill=True) + + node_zk2 = get_connection_zk("node") + + assert node_zk2.get("/test_ephemeral_after_restart")[0] == b"somevalue" + for i in range(100): + if i % 7 == 0: + assert node_zk2.exists("/test_ephemeral_after_restart/node" + str(i)) is None + else: + data, stat = node_zk2.get("/test_ephemeral_after_restart/node" + str(i)) + assert len(data) == 123 + assert data == strs[i] + assert stat.ephemeralOwner == session_id + assert list(sorted(existing_children)) == list(sorted(node_zk2.get_children("/test_ephemeral_after_restart"))) + finally: + try: + if node_zk is not None: + node_zk.stop() + node_zk.close() + + if node_zk2 is not None: + node_zk2.stop() + node_zk2.close() + except: + pass diff --git a/tests/integration/test_testkeeper_snapshots_multinode/__init__.py b/tests/integration/test_testkeeper_snapshots_multinode/__init__.py new file mode 100644 index 00000000000..e5a0d9b4834 --- /dev/null +++ b/tests/integration/test_testkeeper_snapshots_multinode/__init__.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/tests/integration/test_testkeeper_snapshots_multinode/configs/enable_test_keeper1.xml b/tests/integration/test_testkeeper_snapshots_multinode/configs/enable_test_keeper1.xml new file mode 100644 index 00000000000..46b352f498e --- /dev/null +++ b/tests/integration/test_testkeeper_snapshots_multinode/configs/enable_test_keeper1.xml @@ -0,0 +1,42 @@ + + + 9181 + 1 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 10 + 5 + 5000 + 10000 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_snapshots_multinode/configs/enable_test_keeper2.xml b/tests/integration/test_testkeeper_snapshots_multinode/configs/enable_test_keeper2.xml new file mode 100644 index 00000000000..848a14b9feb --- /dev/null +++ b/tests/integration/test_testkeeper_snapshots_multinode/configs/enable_test_keeper2.xml @@ -0,0 +1,42 @@ + + + 9181 + 2 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 10 + 5 + 5000 + 10000 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_snapshots_multinode/configs/enable_test_keeper3.xml b/tests/integration/test_testkeeper_snapshots_multinode/configs/enable_test_keeper3.xml new file mode 100644 index 00000000000..6b37884ab3e --- /dev/null +++ b/tests/integration/test_testkeeper_snapshots_multinode/configs/enable_test_keeper3.xml @@ -0,0 +1,42 @@ + + + 9181 + 3 + /var/lib/clickhouse/coordination/log + /var/lib/clickhouse/coordination/snapshots + + + 10 + 5 + 5000 + 10000 + trace + + + + + 1 + node1 + 44444 + true + 3 + + + 2 + node2 + 44444 + true + true + 2 + + + 3 + node3 + 44444 + true + true + 1 + + + + diff --git a/tests/integration/test_testkeeper_snapshots_multinode/configs/log_conf.xml b/tests/integration/test_testkeeper_snapshots_multinode/configs/log_conf.xml new file mode 100644 index 00000000000..318a6bca95d --- /dev/null +++ b/tests/integration/test_testkeeper_snapshots_multinode/configs/log_conf.xml @@ -0,0 +1,12 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + diff --git a/tests/integration/test_testkeeper_snapshots_multinode/test.py b/tests/integration/test_testkeeper_snapshots_multinode/test.py new file mode 100644 index 00000000000..3ddb7767f2a --- /dev/null +++ b/tests/integration/test_testkeeper_snapshots_multinode/test.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +import pytest +from helpers.cluster import ClickHouseCluster +import random +import string +import os +import time + +cluster = ClickHouseCluster(__file__) +node1 = cluster.add_instance('node1', main_configs=['configs/enable_test_keeper1.xml', 'configs/log_conf.xml'], stay_alive=True) +node2 = cluster.add_instance('node2', main_configs=['configs/enable_test_keeper2.xml', 'configs/log_conf.xml'], stay_alive=True) +node3 = cluster.add_instance('node3', main_configs=['configs/enable_test_keeper3.xml', 'configs/log_conf.xml'], stay_alive=True) + +from kazoo.client import KazooClient, KazooState + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + + yield cluster + + finally: + cluster.shutdown() + +def get_fake_zk(nodename, timeout=30.0): + _fake_zk_instance = KazooClient(hosts=cluster.get_instance_ip(nodename) + ":9181", timeout=timeout) + def reset_listener(state): + nonlocal _fake_zk_instance + print("Fake zk callback called for state", state) + if state != KazooState.CONNECTED: + _fake_zk_instance._reset() + + _fake_zk_instance.add_listener(reset_listener) + _fake_zk_instance.start() + return _fake_zk_instance + +def stop_zk(zk): + try: + if zk: + zk.stop() + zk.close() + except: + pass + +def test_restart_multinode(started_cluster): + try: + node1_zk = node2_zk = node3_zk = None + + node1_zk = get_fake_zk("node1") + node2_zk = get_fake_zk("node2") + node3_zk = get_fake_zk("node3") + + for i in range(100): + node1_zk.create("/test_read_write_multinode_node" + str(i), ("somedata" + str(i)).encode()) + + for i in range(100): + if i % 10 == 0: + node1_zk.delete("/test_read_write_multinode_node" + str(i)) + + node2_zk.sync("/test_read_write_multinode_node0") + node3_zk.sync("/test_read_write_multinode_node0") + + for i in range(100): + if i % 10 != 0: + assert node2_zk.get("/test_read_write_multinode_node" + str(i))[0] == ("somedata" + str(i)).encode() + assert node3_zk.get("/test_read_write_multinode_node" + str(i))[0] == ("somedata" + str(i)).encode() + else: + assert node2_zk.exists("/test_read_write_multinode_node" + str(i)) is None + assert node3_zk.exists("/test_read_write_multinode_node" + str(i)) is None + + finally: + for zk in [node1_zk, node2_zk, node3_zk]: + stop_zk(zk) + + node1.restart_clickhouse(kill=True) + node2.restart_clickhouse(kill=True) + node3.restart_clickhouse(kill=True) + for i in range(100): + try: + node1_zk = get_fake_zk("node1") + node2_zk = get_fake_zk("node2") + node3_zk = get_fake_zk("node3") + for i in range(100): + if i % 10 != 0: + assert node1_zk.get("/test_read_write_multinode_node" + str(i))[0] == ("somedata" + str(i)).encode() + assert node2_zk.get("/test_read_write_multinode_node" + str(i))[0] == ("somedata" + str(i)).encode() + assert node3_zk.get("/test_read_write_multinode_node" + str(i))[0] == ("somedata" + str(i)).encode() + else: + assert node1_zk.exists("/test_read_write_multinode_node" + str(i)) is None + assert node2_zk.exists("/test_read_write_multinode_node" + str(i)) is None + assert node3_zk.exists("/test_read_write_multinode_node" + str(i)) is None + break + except Exception as ex: + print("Got exception as ex", ex) + finally: + for zk in [node1_zk, node2_zk, node3_zk]: + stop_zk(zk) diff --git a/tests/integration/test_zookeeper_config/test.py b/tests/integration/test_zookeeper_config/test.py index eb5ab2da98f..584f76c80f0 100644 --- a/tests/integration/test_zookeeper_config/test.py +++ b/tests/integration/test_zookeeper_config/test.py @@ -1,6 +1,7 @@ import time +import threading from os import path as p, unlink from tempfile import NamedTemporaryFile @@ -129,7 +130,7 @@ def test_secure_connection(): # We need absolute path in zookeeper volumes. Generate it dynamically. TEMPLATE = ''' zoo{zoo_id}: - image: zookeeper:3.5.6 + image: zookeeper:3.6.2 restart: always environment: ZOO_TICK_TIME: 500 @@ -174,6 +175,20 @@ def test_secure_connection(): assert node1.query("SELECT count() FROM system.zookeeper WHERE path = '/'") == '2\n' assert node2.query("SELECT count() FROM system.zookeeper WHERE path = '/'") == '2\n' + + kThreadsNumber = 16 + kIterations = 100 + threads = [] + for _ in range(kThreadsNumber): + threads.append(threading.Thread(target=(lambda: + [node1.query("SELECT count() FROM system.zookeeper WHERE path = '/'") for _ in range(kIterations)]))) + + for thread in threads: + thread.start() + + for thread in threads: + thread.join() + finally: cluster.shutdown() unlink(docker_compose.name) diff --git a/tests/performance/aggfunc_col_data_copy.xml b/tests/performance/aggfunc_col_data_copy.xml deleted file mode 100644 index 111f7959d58..00000000000 --- a/tests/performance/aggfunc_col_data_copy.xml +++ /dev/null @@ -1,24 +0,0 @@ - - drop table if EXISTS test_bm2; - drop table if EXISTS test_bm_join2; - create table test_bm2( - dim UInt64, - id UInt64) - ENGINE = MergeTree() - ORDER BY( dim ) - SETTINGS index_granularity = 8192; - - - create table test_bm_join2( - dim UInt64, - ids AggregateFunction(groupBitmap, UInt64) ) - ENGINE = MergeTree() - ORDER BY(dim) - SETTINGS index_granularity = 8192; - - insert into test_bm2 SELECT 1,number FROM numbers(0, 1000) - insert into test_bm_join2 SELECT 1, bitmapBuild(range(toUInt64(0),toUInt64(11000000))) - select a.dim,bitmapCardinality(b.ids) from test_bm2 a left join test_bm_join2 b using(dim) - drop table if exists test_bm2 - drop table if exists test_bm_join2 - diff --git a/tests/performance/direct_dictionary.xml b/tests/performance/direct_dictionary.xml new file mode 100644 index 00000000000..eb1b4e0da00 --- /dev/null +++ b/tests/performance/direct_dictionary.xml @@ -0,0 +1,80 @@ + + + CREATE TABLE simple_direct_dictionary_test_table + ( + id UInt64, + value_int UInt64, + value_string String, + value_decimal Decimal64(8), + value_string_nullable Nullable(String) + ) ENGINE = TinyLog; + + + + INSERT INTO simple_direct_dictionary_test_table + SELECT number, number, toString(number), toDecimal64(number, 8), toString(number) + FROM system.numbers + LIMIT 100000; + + + + CREATE DICTIONARY simple_direct_dictionary + ( + id UInt64, + value_int UInt64, + value_string String, + value_decimal Decimal64(8), + value_string_nullable Nullable(String) + ) + PRIMARY KEY id + SOURCE(CLICKHOUSE(DB 'default' TABLE 'simple_direct_dictionary_test_table')) + LAYOUT(DIRECT()) + + + + CREATE TABLE complex_direct_dictionary_test_table + ( + id UInt64, + id_key String, + value_int UInt64, + value_string String, + value_decimal Decimal64(8), + value_string_nullable Nullable(String) + ) ENGINE = TinyLog; + + + + INSERT INTO complex_direct_dictionary_test_table + SELECT number, toString(number), number, toString(number), toDecimal64(number, 8), toString(number) + FROM system.numbers + LIMIT 100000; + + + + CREATE DICTIONARY complex_direct_dictionary + ( + id UInt64, + id_key String, + value_int UInt64, + value_string String, + value_decimal Decimal64(8), + value_string_nullable Nullable(String) + ) + PRIMARY KEY id, id_key + SOURCE(CLICKHOUSE(DB 'default' TABLE 'complex_direct_dictionary_test_table')) + LAYOUT(COMPLEX_KEY_DIRECT()) + + + SELECT dictGet('default.simple_direct_dictionary', 'value_int', number) FROM system.numbers LIMIT 150000; + SELECT dictGet('default.simple_direct_dictionary', 'value_string', number) FROM system.numbers LIMIT 150000; + SELECT dictGet('default.simple_direct_dictionary', 'value_decimal', number) FROM system.numbers LIMIT 150000; + SELECT dictGet('default.simple_direct_dictionary', 'value_string_nullable', number) FROM system.numbers LIMIT 150000; + SELECT dictHas('default.simple_direct_dictionary', number) FROM system.numbers LIMIT 150000; + + SELECT dictGet('default.complex_direct_dictionary', 'value_int', (number, toString(number))) FROM system.numbers LIMIT 150000; + SELECT dictGet('default.complex_direct_dictionary', 'value_string', (number, toString(number))) FROM system.numbers LIMIT 150000; + SELECT dictGet('default.complex_direct_dictionary', 'value_decimal', (number, toString(number))) FROM system.numbers LIMIT 150000; + SELECT dictGet('default.complex_direct_dictionary', 'value_string_nullable', (number, toString(number))) FROM system.numbers LIMIT 150000; + SELECT dictHas('default.complex_direct_dictionary', (number, toString(number))) FROM system.numbers LIMIT 150000; + + diff --git a/tests/performance/group_by_fixed_keys.xml b/tests/performance/group_by_fixed_keys.xml new file mode 100644 index 00000000000..0be29ff11ac --- /dev/null +++ b/tests/performance/group_by_fixed_keys.xml @@ -0,0 +1,7 @@ + + WITH toUInt8(number) AS k, toUInt64(k) AS k1, k AS k2 SELECT k1, k2, count() FROM numbers(100000000) GROUP BY k1, k2 + WITH toUInt8(number) AS k, toUInt16(k) AS k1, toUInt32(k) AS k2, k AS k3 SELECT k1, k2, k3, count() FROM numbers(100000000) GROUP BY k1, k2, k3 + WITH toUInt8(number) AS k, k AS k1, k + 1 AS k2 SELECT k1, k2, count() FROM numbers(100000000) GROUP BY k1, k2 + WITH toUInt8(number) AS k, k AS k1, k + 1 AS k2, k + 2 AS k3, k + 3 AS k4 SELECT k1, k2, k3, k4, count() FROM numbers(100000000) GROUP BY k1, k2, k3, k4 + WITH toUInt8(number) AS k, toUInt64(k) AS k1, k1 + 1 AS k2 SELECT k1, k2, count() FROM numbers(100000000) GROUP BY k1, k2 + diff --git a/tests/performance/modulo.xml b/tests/performance/modulo.xml index 77b544ff389..7c33855ff32 100644 --- a/tests/performance/modulo.xml +++ b/tests/performance/modulo.xml @@ -1,7 +1,4 @@ - - - SELECT number % 128 FROM numbers(300000000) FORMAT Null SELECT number % 255 FROM numbers(300000000) FORMAT Null SELECT number % 256 FROM numbers(300000000) FORMAT Null diff --git a/tests/performance/prewhere_with_row_level_filter.xml b/tests/performance/prewhere_with_row_level_filter.xml new file mode 100644 index 00000000000..9448fdcb408 --- /dev/null +++ b/tests/performance/prewhere_with_row_level_filter.xml @@ -0,0 +1,20 @@ + + + 0 + + + DROP TABLE IF EXISTS test_prl + CREATE TABLE test_prl (n UInt64) ENGINE MergeTree ORDER BY n + CREATE ROW POLICY OR REPLACE test_prl_policy ON test_prl AS PERMISSIVE FOR SELECT USING n % 7 TO ALL + + INSERT INTO test_prl SELECT number FROM numbers(100000000) SETTINGS max_insert_threads=8 + + SELECT sum(n) FROM test_prl + SELECT sum(n) FROM test_prl WHERE n % 3 AND n % 5 + SELECT sum(n) FROM test_prl PREWHERE n % 3 AND n % 5 + SELECT sum(n) FROM test_prl PREWHERE n % 3 WHERE n % 5 + SELECT sum(n) FROM test_prl PREWHERE n % 5 WHERE n % 3 + + DROP ROW POLICY IF EXISTS test_prl_policy ON test_prl + DROP TABLE IF EXISTS test_prl + diff --git a/tests/performance/reinterpret_as.xml b/tests/performance/reinterpret_as.xml index 17c5fd9da11..b9b6fec2084 100644 --- a/tests/performance/reinterpret_as.xml +++ b/tests/performance/reinterpret_as.xml @@ -19,7 +19,7 @@ toInt256(number) as d, toString(number) as f, toFixedString(f, 20) as g - FROM numbers_mt(20000000) + FROM numbers_mt(200000000) SETTINGS max_threads = 8 FORMAT Null @@ -38,7 +38,7 @@ toInt256(number) as d, toString(number) as f, toFixedString(f, 20) as g - FROM numbers_mt(20000000) + FROM numbers_mt(200000000) SETTINGS max_threads = 8 FORMAT Null @@ -76,7 +76,7 @@ toInt256(number) as d, toString(number) as f, toFixedString(f, 20) as g - FROM numbers_mt(20000000) + FROM numbers_mt(200000000) SETTINGS max_threads = 8 FORMAT Null @@ -115,7 +115,7 @@ toInt256(number) as d, toString(number) as f, toFixedString(f, 20) as g - FROM numbers_mt(20000000) + FROM numbers_mt(200000000) SETTINGS max_threads = 8 FORMAT Null @@ -134,7 +134,7 @@ toInt256(number) as d, toString(number) as f, toFixedString(f, 20) as g - FROM numbers_mt(20000000) + FROM numbers_mt(200000000) SETTINGS max_threads = 8 FORMAT Null @@ -153,7 +153,7 @@ toInt256(number) as d, toString(number) as f, toFixedString(f, 20) as g - FROM numbers_mt(20000000) + FROM numbers_mt(200000000) SETTINGS max_threads = 8 FORMAT Null @@ -172,7 +172,7 @@ toInt256(number) as d, toString(number) as f, toFixedString(f, 20) as g - FROM numbers_mt(20000000) + FROM numbers_mt(200000000) SETTINGS max_threads = 8 FORMAT Null @@ -191,7 +191,7 @@ toInt256(number) as d, toString(number) as f, toFixedString(f, 20) as g - FROM numbers_mt(20000000) + FROM numbers_mt(200000000) SETTINGS max_threads = 8 FORMAT Null @@ -230,7 +230,7 @@ toInt256(number) as d, toString(number) as f, toFixedString(f, 20) as g - FROM numbers_mt(2000000) + FROM numbers_mt(20000000) SETTINGS max_threads = 8 FORMAT Null @@ -249,7 +249,7 @@ toInt256(number) as d, toString(number) as f, toFixedString(f, 20) as g - FROM numbers_mt(20000000) + FROM numbers_mt(100000000) SETTINGS max_threads = 8 FORMAT Null diff --git a/tests/performance/subqueries.xml b/tests/performance/subqueries.xml new file mode 100644 index 00000000000..0d41099841b --- /dev/null +++ b/tests/performance/subqueries.xml @@ -0,0 +1,7 @@ + + create table tab (a UInt32, b UInt32) engine = MergeTree order by (a, b) + insert into tab values (1, 1) + select a, b from tab where (a, b) in (select toUInt32(number) as x, toUInt32(sleep(0.1) + 1) from numbers_mt(16)) settings max_threads = 2, max_block_size = 4 + select a, b from tab where (1, 1) = (select min(toUInt32(number + 1)) as x, min(toUInt32(sleep(0.1) + 1)) from numbers_mt(16)) settings max_threads = 2, max_block_size = 4 + DROP TABLE tab + diff --git a/tests/performance/window_functions.xml b/tests/performance/window_functions.xml index 74df2b64a3b..622e349d060 100644 --- a/tests/performance/window_functions.xml +++ b/tests/performance/window_functions.xml @@ -86,4 +86,28 @@ format Null + + + select + min(number) over w, + count(*) over w, + max(number) over w + from + (select number, intDiv(number, 1111) p, mod(number, 111) o + from numbers(10000000)) t + window w as (partition by p order by o) + format Null + + + + select + first_value(number) over w, + dense_rank() over w + from + (select number, intDiv(number, 1111) p, mod(number, 111) o + from numbers(10000000)) t + window w as (partition by p order by o) + format Null + + diff --git a/tests/queries/0_stateless/00205_scalar_subqueries.sql b/tests/queries/0_stateless/00205_scalar_subqueries.sql index 14244377e5f..03bcd0a3ebc 100644 --- a/tests/queries/0_stateless/00205_scalar_subqueries.sql +++ b/tests/queries/0_stateless/00205_scalar_subqueries.sql @@ -7,3 +7,4 @@ SELECT (SELECT toDate('2015-01-02'), 'Hello'); SELECT (SELECT toDate('2015-01-02'), 'Hello') AS x, x, identity((SELECT 1)), identity((SELECT 1) AS y); -- SELECT (SELECT uniqState('')); + SELECT ( SELECT throwIf(1 + dummy) ); -- { serverError 395 } diff --git a/tests/queries/0_stateless/00502_sum_map.reference b/tests/queries/0_stateless/00502_sum_map.reference index 0002c43945a..c38fb2ec7d6 100644 --- a/tests/queries/0_stateless/00502_sum_map.reference +++ b/tests/queries/0_stateless/00502_sum_map.reference @@ -22,3 +22,5 @@ ([1.01],[1]) (['a','b'],[1,2]) (['a','ab','abc'],[3,2,1]) +([1,2,3,4,5,6,7,8],[1.00000,2.00000,6.00000,8.00000,10.00000,12.00000,7.00000,8.00000]) +([1,2,3,4,5,6,7,8],[1.00000,2.00000,6.00000,8.00000,10.00000,12.00000,7.00000,8.00000]) diff --git a/tests/queries/0_stateless/00502_sum_map.sql b/tests/queries/0_stateless/00502_sum_map.sql index 021aaf3cd3b..51007a9c78a 100644 --- a/tests/queries/0_stateless/00502_sum_map.sql +++ b/tests/queries/0_stateless/00502_sum_map.sql @@ -38,3 +38,19 @@ select sumMap(val, cnt) from ( SELECT [ CAST(1.01, 'Decimal(10,2)') ] as val, [1 select sumMap(val, cnt) from ( SELECT [ CAST('a', 'FixedString(1)'), CAST('b', 'FixedString(1)' ) ] as val, [1, 2] as cnt ); select sumMap(val, cnt) from ( SELECT [ CAST('abc', 'String'), CAST('ab', 'String'), CAST('a', 'String') ] as val, [1, 2, 3] as cnt ); + +DROP TABLE IF EXISTS sum_map_decimal; + +CREATE TABLE sum_map_decimal( + statusMap Nested( + goal_id UInt16, + revenue Decimal32(5) + ) +) ENGINE = Log; + +INSERT INTO sum_map_decimal VALUES ([1, 2, 3], [1.0, 2.0, 3.0]), ([3, 4, 5], [3.0, 4.0, 5.0]), ([4, 5, 6], [4.0, 5.0, 6.0]), ([6, 7, 8], [6.0, 7.0, 8.0]); + +SELECT sumMap(statusMap.goal_id, statusMap.revenue) FROM sum_map_decimal; +SELECT sumMapWithOverflow(statusMap.goal_id, statusMap.revenue) FROM sum_map_decimal; + +DROP TABLE sum_map_decimal; diff --git a/tests/queries/0_stateless/00561_storage_join.reference b/tests/queries/0_stateless/00561_storage_join.reference index 867b945ba1c..2fe12a38360 100644 --- a/tests/queries/0_stateless/00561_storage_join.reference +++ b/tests/queries/0_stateless/00561_storage_join.reference @@ -2,3 +2,4 @@ 2 22 92 82 123457 1 11 91 81 123456 2 22 92 82 123457 +11 1 91 81 123456 diff --git a/tests/queries/0_stateless/00561_storage_join.sql b/tests/queries/0_stateless/00561_storage_join.sql index 62ca80d31fe..01e66d0c380 100644 --- a/tests/queries/0_stateless/00561_storage_join.sql +++ b/tests/queries/0_stateless/00561_storage_join.sql @@ -36,5 +36,13 @@ from ( ) js1 SEMI LEFT JOIN joinbug_join using id2; +/* type conversion */ +SELECT * FROM +( + SELECT toUInt32(11) AS id2 +) AS js1 +SEMI LEFT JOIN joinbug_join USING (id2); + + DROP TABLE joinbug; DROP TABLE joinbug_join; diff --git a/tests/queries/0_stateless/00597_push_down_predicate.reference b/tests/queries/0_stateless/00597_push_down_predicate.reference index cea533d6ccb..bd1c4791df4 100644 --- a/tests/queries/0_stateless/00597_push_down_predicate.reference +++ b/tests/queries/0_stateless/00597_push_down_predicate.reference @@ -114,7 +114,8 @@ FROM ( SELECT 1 AS id, - identity(cast(1, \'UInt8\')) AS subquery + identity(CAST(1, \'UInt8\')) AS subquery + WHERE subquery = 1 ) WHERE subquery = 1 1 1 diff --git a/tests/queries/0_stateless/00600_replace_running_query.sh b/tests/queries/0_stateless/00600_replace_running_query.sh index be5523e06ea..78ea4daf6bb 100755 --- a/tests/queries/0_stateless/00600_replace_running_query.sh +++ b/tests/queries/0_stateless/00600_replace_running_query.sh @@ -6,6 +6,8 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # shellcheck source=../shell_config.sh . "$CURDIR"/../shell_config.sh +${CLICKHOUSE_CLIENT} -q "drop user if exists u_00600" +${CLICKHOUSE_CLIENT} -q "create user u_00600 settings max_execution_time=60, readonly=1" function wait_for_query_to_start() { @@ -22,7 +24,7 @@ $CLICKHOUSE_CURL -sS "$CLICKHOUSE_URL&query_id=hello&replace_running_query=1" -d # Wait for it to be replaced wait -${CLICKHOUSE_CLIENT_BINARY} --user=readonly --query_id=42 --query='SELECT 2, count() FROM system.numbers' 2>&1 | grep -cF 'was cancelled' & +${CLICKHOUSE_CLIENT_BINARY} --user=u_00600 --query_id=42 --query='SELECT 2, count() FROM system.numbers' 2>&1 | grep -cF 'was cancelled' & wait_for_query_to_start '42' # Trying to run another query with the same query_id @@ -39,3 +41,4 @@ wait_for_query_to_start '42' ${CLICKHOUSE_CLIENT} --query_id=42 --replace_running_query=1 --replace_running_query_max_wait_ms=500 --query='SELECT 43' 2>&1 | grep -F "can't be stopped" > /dev/null wait ${CLICKHOUSE_CLIENT} --query_id=42 --replace_running_query=1 --query='SELECT 44' +${CLICKHOUSE_CLIENT} -q "drop user u_00600" diff --git a/tests/queries/0_stateless/00642_cast.reference b/tests/queries/0_stateless/00642_cast.reference index 3d5572932fb..7f5333f590e 100644 --- a/tests/queries/0_stateless/00642_cast.reference +++ b/tests/queries/0_stateless/00642_cast.reference @@ -10,11 +10,11 @@ hello CREATE TABLE default.cast ( `x` UInt8, - `e` Enum8('hello' = 1, 'world' = 2) DEFAULT cast(x, 'Enum8(\'hello\' = 1, \'world\' = 2)') + `e` Enum8('hello' = 1, 'world' = 2) DEFAULT CAST(x, 'Enum8(\'hello\' = 1, \'world\' = 2)') ) ENGINE = MergeTree ORDER BY e SETTINGS index_granularity = 8192 x UInt8 -e Enum8(\'hello\' = 1, \'world\' = 2) DEFAULT cast(x, \'Enum8(\\\'hello\\\' = 1, \\\'world\\\' = 2)\') +e Enum8(\'hello\' = 1, \'world\' = 2) DEFAULT CAST(x, \'Enum8(\\\'hello\\\' = 1, \\\'world\\\' = 2)\') 1 hello diff --git a/tests/queries/0_stateless/00643_cast_zookeeper.reference b/tests/queries/0_stateless/00643_cast_zookeeper.reference index 658233be742..9123463de1a 100644 --- a/tests/queries/0_stateless/00643_cast_zookeeper.reference +++ b/tests/queries/0_stateless/00643_cast_zookeeper.reference @@ -1,12 +1,12 @@ CREATE TABLE default.cast1 ( `x` UInt8, - `e` Enum8('hello' = 1, 'world' = 2) DEFAULT cast(x, 'Enum8(\'hello\' = 1, \'world\' = 2)') + `e` Enum8('hello' = 1, 'world' = 2) DEFAULT CAST(x, 'Enum8(\'hello\' = 1, \'world\' = 2)') ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/test_00643/cast', 'r1') ORDER BY e SETTINGS index_granularity = 8192 x UInt8 -e Enum8(\'hello\' = 1, \'world\' = 2) DEFAULT cast(x, \'Enum8(\\\'hello\\\' = 1, \\\'world\\\' = 2)\') +e Enum8(\'hello\' = 1, \'world\' = 2) DEFAULT CAST(x, \'Enum8(\\\'hello\\\' = 1, \\\'world\\\' = 2)\') 1 hello 1 hello diff --git a/tests/queries/0_stateless/00643_cast_zookeeper.sql b/tests/queries/0_stateless/00643_cast_zookeeper.sql index c52d44bd88b..c9760f00ca7 100644 --- a/tests/queries/0_stateless/00643_cast_zookeeper.sql +++ b/tests/queries/0_stateless/00643_cast_zookeeper.sql @@ -1,3 +1,5 @@ +SET database_atomic_wait_for_drop_and_detach_synchronously=1; + DROP TABLE IF EXISTS cast1; DROP TABLE IF EXISTS cast2; diff --git a/tests/queries/0_stateless/00753_distributed_system_columns_and_system_tables.reference b/tests/queries/0_stateless/00753_distributed_system_columns_and_system_tables.reference new file mode 100644 index 00000000000..042e79f1b80 --- /dev/null +++ b/tests/queries/0_stateless/00753_distributed_system_columns_and_system_tables.reference @@ -0,0 +1,4 @@ +Check total_bytes/total_rows for Distributed +0 \N +1 \N +0 \N diff --git a/tests/queries/0_stateless/00753_distributed_system_columns_and_system_tables.sql b/tests/queries/0_stateless/00753_distributed_system_columns_and_system_tables.sql new file mode 100644 index 00000000000..fd9786be011 --- /dev/null +++ b/tests/queries/0_stateless/00753_distributed_system_columns_and_system_tables.sql @@ -0,0 +1,11 @@ +SELECT 'Check total_bytes/total_rows for Distributed'; +CREATE TABLE check_system_tables_null (key Int) Engine=Null(); +CREATE TABLE check_system_tables AS check_system_tables_null Engine=Distributed(test_shard_localhost, currentDatabase(), check_system_tables_null); +SYSTEM STOP DISTRIBUTED SENDS check_system_tables; +SELECT total_bytes, total_rows FROM system.tables WHERE database = currentDatabase() AND name = 'check_system_tables'; +INSERT INTO check_system_tables SELECT * FROM numbers(1) SETTINGS prefer_localhost_replica=0; +SELECT total_bytes>0, total_rows FROM system.tables WHERE database = currentDatabase() AND name = 'check_system_tables'; +SYSTEM FLUSH DISTRIBUTED check_system_tables; +SELECT total_bytes, total_rows FROM system.tables WHERE database = currentDatabase() AND name = 'check_system_tables'; +DROP TABLE check_system_tables_null; +DROP TABLE check_system_tables; diff --git a/tests/queries/0_stateless/00825_protobuf_format_array_3dim.reference b/tests/queries/0_stateless/00825_protobuf_format_array_3dim.reference new file mode 100644 index 00000000000..69e7d5e1da8 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_array_3dim.reference @@ -0,0 +1,52 @@ +[[],[[]],[[1]],[[2,3],[4]]] +[[[5,6,7]],[[8,9,10]]] + +Binary representation: +00000000 1a 0a 00 0a 02 0a 00 0a 05 0a 03 0a 01 01 0a 0b |................| +00000010 0a 04 0a 02 02 03 0a 03 0a 01 04 12 0a 07 0a 05 |................| +00000020 0a 03 05 06 07 0a 07 0a 05 0a 03 08 09 0a |..............| +0000002e + +MESSAGE #1 AT 0x00000001 +a { +} +a { + b { + } +} +a { + b { + c: 1 + } +} +a { + b { + c: 2 + c: 3 + } + b { + c: 4 + } +} +MESSAGE #2 AT 0x0000001C +a { + b { + c: 5 + c: 6 + c: 7 + } +} +a { + b { + c: 8 + c: 9 + c: 10 + } +} + +Binary representation is as expected + +[[],[[]],[[1]],[[2,3],[4]]] +[[[5,6,7]],[[8,9,10]]] +[[],[[]],[[1]],[[2,3],[4]]] +[[[5,6,7]],[[8,9,10]]] diff --git a/tests/queries/0_stateless/00825_protobuf_format_array_3dim.sh b/tests/queries/0_stateless/00825_protobuf_format_array_3dim.sh new file mode 100755 index 00000000000..762f8a937e4 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_array_3dim.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +SCHEMADIR=$CURDIR/format_schemas +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +set -eo pipefail + +# Run the client. +$CLICKHOUSE_CLIENT --multiquery < "$BINARY_FILE_PATH" + +# Check the output in the protobuf format +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_array_3dim:ABC" --input "$BINARY_FILE_PATH" + +# Check the input in the protobuf format (now the table contains the same data twice). +echo +$CLICKHOUSE_CLIENT --query "INSERT INTO array_3dim_protobuf_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_array_3dim:ABC'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM array_3dim_protobuf_00825" + +rm "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "DROP TABLE array_3dim_protobuf_00825" diff --git a/tests/queries/0_stateless/00825_protobuf_format_array_of_arrays.reference b/tests/queries/0_stateless/00825_protobuf_format_array_of_arrays.reference new file mode 100644 index 00000000000..5ea6780a3ba --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_array_of_arrays.reference @@ -0,0 +1,41 @@ +one [[1,2,3],[0.5,0.25],[],[4,5],[0.125,0.0625],[6]] + +Binary representation: +00000000 6b 0a 03 6f 6e 65 12 1a 12 18 00 00 00 00 00 00 |k..one..........| +00000010 f0 3f 00 00 00 00 00 00 00 40 00 00 00 00 00 00 |.?.......@......| +00000020 08 40 12 12 12 10 00 00 00 00 00 00 e0 3f 00 00 |.@...........?..| +00000030 00 00 00 00 d0 3f 12 00 12 12 12 10 00 00 00 00 |.....?..........| +00000040 00 00 10 40 00 00 00 00 00 00 14 40 12 12 12 10 |...@.......@....| +00000050 00 00 00 00 00 00 c0 3f 00 00 00 00 00 00 b0 3f |.......?.......?| +00000060 12 0a 12 08 00 00 00 00 00 00 18 40 |...........@| +0000006c + +MESSAGE #1 AT 0x00000001 +a: "one" +b { + c: 1 + c: 2 + c: 3 +} +b { + c: 0.5 + c: 0.25 +} +b { +} +b { + c: 4 + c: 5 +} +b { + c: 0.125 + c: 0.0625 +} +b { + c: 6 +} + +Binary representation is as expected + +one [[1,2,3],[0.5,0.25],[],[4,5],[0.125,0.0625],[6]] +one [[1,2,3],[0.5,0.25],[],[4,5],[0.125,0.0625],[6]] diff --git a/tests/queries/0_stateless/00825_protobuf_format_array_of_arrays.sh b/tests/queries/0_stateless/00825_protobuf_format_array_of_arrays.sh new file mode 100755 index 00000000000..243446f9438 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_array_of_arrays.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +# https://github.com/ClickHouse/ClickHouse/issues/9069 + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +SCHEMADIR=$CURDIR/format_schemas +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +set -eo pipefail + +# Run the client. +$CLICKHOUSE_CLIENT --multiquery < "$BINARY_FILE_PATH" + +# Check the output in the protobuf format +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_array_of_arrays:AA" --input "$BINARY_FILE_PATH" + +# Check the input in the protobuf format (now the table contains the same data twice). +echo +$CLICKHOUSE_CLIENT --query "INSERT INTO array_of_arrays_protobuf_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_array_of_arrays:AA'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM array_of_arrays_protobuf_00825" + +rm "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "DROP TABLE array_of_arrays_protobuf_00825" diff --git a/tests/queries/0_stateless/00825_protobuf_format_enum_mapping.reference b/tests/queries/0_stateless/00825_protobuf_format_enum_mapping.reference new file mode 100644 index 00000000000..ef8059bac28 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_enum_mapping.reference @@ -0,0 +1,31 @@ +Second +Third +First +First +Second + +Binary representation: +00000000 02 08 01 02 08 64 00 00 02 08 01 |.....d.....| +0000000b + +MESSAGE #1 AT 0x00000001 +x: SECOND +MESSAGE #2 AT 0x00000004 +x: HUNDRED +MESSAGE #3 AT 0x00000007 +MESSAGE #4 AT 0x00000008 +MESSAGE #5 AT 0x00000009 +x: SECOND + +Binary representation is as expected + +Second +Third +First +First +Second +Second +Third +First +First +Second diff --git a/tests/queries/0_stateless/00825_protobuf_format_enum_mapping.sh b/tests/queries/0_stateless/00825_protobuf_format_enum_mapping.sh new file mode 100755 index 00000000000..300f82e5ca2 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_enum_mapping.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# https://github.com/ClickHouse/ClickHouse/issues/7438 + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +SCHEMADIR=$CURDIR/format_schemas +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +set -eo pipefail + +# Run the client. +$CLICKHOUSE_CLIENT --multiquery < "$BINARY_FILE_PATH" + +# Check the output in the protobuf format +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_enum_mapping:Message" --input "$BINARY_FILE_PATH" + +# Check the input in the protobuf format (now the table contains the same data twice). +echo +$CLICKHOUSE_CLIENT --query "INSERT INTO enum_mapping_protobuf_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_enum_mapping:Message'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM enum_mapping_protobuf_00825" + +rm "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "DROP TABLE enum_mapping_protobuf_00825" diff --git a/tests/queries/0_stateless/00825_protobuf_format_input.insh b/tests/queries/0_stateless/00825_protobuf_format_input.insh deleted file mode 100644 index 39a2f17c98f..00000000000 --- a/tests/queries/0_stateless/00825_protobuf_format_input.insh +++ /dev/null @@ -1,5 +0,0 @@ -echo -ne '\xf3\x01\x0a\x24\x61\x37\x35\x32\x32\x31\x35\x38\x2d\x33\x64\x34\x31\x2d\x34\x62\x37\x37\x2d\x61\x64\x36\x39\x2d\x36\x63\x35\x39\x38\x65\x65\x35\x35\x63\x34\x39\x12\x04\x49\x76\x61\x6e\x1a\x06\x50\x65\x74\x72\x6f\x76\x20\x01\x28\xaf\x1f\x32\x03\x70\x6e\x67\x3a\x0c\x2b\x37\x34\x39\x35\x31\x32\x33\x34\x35\x36\x37\x40\x01\x4d\xfc\xd0\x30\x5c\x50\x26\x58\x09\x62\x09\x59\x65\x73\x74\x65\x72\x64\x61\x79\x62\x07\x46\x6c\x6f\x77\x65\x72\x73\x6a\x04\xff\x01\x00\x00\x72\x06\x4d\x6f\x73\x63\x6f\x77\x7a\x08\x4b\x03\x5f\x42\x72\x7d\x16\x42\x81\x01\x1f\x85\xeb\x51\xb8\x1e\x09\x40\x89\x01\x33\x33\x33\x33\x33\xc3\x6a\x40\x95\x01\xcd\xcc\xcc\x3d\x9d\x01\x9a\x99\xb9\x40\xa0\x01\x80\xc4\xd7\x8d\x7f\xaa\x01\x0c\x0a\x05\x6d\x65\x74\x65\x72\x15\x00\x00\x80\x3f\xaa\x01\x11\x0a\x0a\x63\x65\x6e\x74\x69\x6d\x65\x74\x65\x72\x15\x0a\xd7\x23\x3c\xaa\x01\x10\x0a\x09\x6b\x69\x6c\x6f\x6d\x65\x74\x65\x72\x15\x00\x00\x7a\x44\xb2\x01\x10\x0a\x0e\xa2\x06\x0b\x0a\x09\x08\xf4\x03\x12\x04\xf5\x03\xf6\x03\x7e\x0a\x24\x63\x36\x39\x34\x61\x64\x38\x61\x2d\x66\x37\x31\x34\x2d\x34\x65\x61\x33\x2d\x39\x30\x37\x64\x2d\x66\x64\x35\x34\x66\x62\x32\x35\x64\x39\x62\x35\x12\x07\x4e\x61\x74\x61\x6c\x69\x61\x1a\x08\x53\x6f\x6b\x6f\x6c\x6f\x76\x61\x28\xa6\x3f\x32\x03\x6a\x70\x67\x50\x1a\x58\x0b\x6a\x04\x64\xc8\x01\x32\x72\x08\x50\x6c\x79\x6d\x6f\x75\x74\x68\x7a\x08\x6a\x9d\x49\x42\x46\x8c\x84\xc0\x81\x01\x6e\x86\x1b\xf0\xf9\x21\x09\x40\x95\x01\x42\x60\xe5\x3b\x9d\x01\xcd\xcc\xac\x40\xa0\x01\xff\xff\xa9\xce\x93\x8c\x09\xc0\x01\x0a\x24\x61\x37\x64\x61\x31\x61\x61\x36\x2d\x66\x34\x32\x35\x2d\x34\x37\x38\x39\x2d\x38\x39\x34\x37\x2d\x62\x30\x33\x34\x37\x38\x36\x65\x64\x33\x37\x34\x12\x06\x56\x61\x73\x69\x6c\x79\x1a\x07\x53\x69\x64\x6f\x72\x6f\x76\x20\x01\x28\xfb\x48\x32\x03\x62\x6d\x70\x3a\x0d\x2b\x34\x34\x32\x30\x31\x32\x33\x34\x35\x36\x37\x38\x40\x01\x4d\x50\xe0\x27\x5c\x50\x17\x58\x04\x62\x05\x53\x75\x6e\x6e\x79\x6a\x05\xfa\x01\xf4\x01\x0a\x72\x08\x4d\x75\x72\x6d\x61\x6e\x73\x6b\x7a\x08\xfd\xf0\x89\x42\xc8\x4c\x04\x42\x81\x01\x11\x2d\x44\x54\xfb\x21\x09\x40\x89\x01\x00\x00\x00\xe8\x76\x48\x37\x42\x95\x01\x00\x00\x48\x44\x9d\x01\xcd\xcc\x4c\xc0\xa0\x01\x80\xd4\x9f\x93\x01\xaa\x01\x0c\x0a\x05\x70\x6f\x75\x6e\x64\x15\x00\x00\x80\x41\xb2\x01\x0a\x0a\x08\xa2\x06\x05\x0a\x03\x08\xf7\x03' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_persons_00825 FORMAT Protobuf SETTINGS format_schema = '$CURDIR/00825_protobuf_format:Person'" -echo -ne '\xb3\x01\x12\x05\x46\x72\x69\x64\x61\x28\x99\xe1\xf3\xd1\x0b\x52\x08\x45\x72\x6d\x61\x6b\x6f\x76\x61\x72\x0c\x00\x00\xdc\x42\x00\x00\x52\x43\x00\x00\x94\x42\x79\x48\xce\x3d\x51\x00\x00\x00\x00\xc8\x02\x14\xc2\x05\x08\x00\x00\x80\x44\x00\x00\x80\x49\x9a\x06\x02\x4b\x42\x9a\x06\x02\x4d\x42\xa1\x06\x00\x00\x00\x00\x00\x00\xe0\x3f\xa8\x06\x2a\xa8\x06\xa8\xff\xff\xff\xff\xff\xff\xff\xff\x01\xb0\x06\x01\xbd\x06\x25\x06\x49\x40\xfa\x06\x02\x34\x30\x90\x08\xe2\x08\xe1\x08\x89\xe6\x6e\xdd\x01\x00\x00\x00\xb0\x09\xc3\x19\xd0\x0c\xb7\x02\xe2\x12\x24\x32\x30\x66\x63\x64\x39\x35\x61\x2d\x33\x33\x32\x64\x2d\x34\x31\x64\x62\x2d\x61\x39\x65\x63\x2d\x31\x36\x31\x66\x36\x34\x34\x64\x30\x35\x39\x63\xa0\x38\xbc\x05\xaa\x38\x02\xbd\x05\xb4\x01\x08\x01\x12\x06\x49\x73\x6f\x6c\x64\x65\x52\x07\x4c\x61\x76\x72\x6f\x76\x61\x72\x0c\x00\x00\x7f\x43\x00\x00\x00\x00\x00\x00\x7f\x43\xaa\x01\x03\x61\x62\x63\xc8\x02\x32\xc2\x05\x08\x00\x00\x00\x41\x00\x00\x80\x3f\x9a\x06\x04\x42\x79\x74\x65\x9a\x06\x03\x42\x69\x74\xa1\x06\x00\x00\x00\x00\x00\x00\x12\x40\xa8\x06\x1a\xa8\x06\xb0\xff\xff\xff\xff\xff\xff\xff\xff\x01\xb0\x06\x01\xbd\x06\xf9\x0f\x49\x40\xc2\x06\x01\x2c\xfa\x06\x02\x33\x32\x90\x08\x78\xe1\x08\x39\x4e\x2b\xfe\xe4\xf5\xff\xff\xb0\x09\xe8\x30\xd8\x12\x01\xe2\x12\x24\x37\x63\x66\x61\x36\x38\x35\x36\x2d\x61\x35\x34\x61\x2d\x34\x37\x38\x36\x2d\x62\x38\x65\x35\x2d\x37\x34\x35\x31\x35\x39\x64\x35\x32\x32\x37\x38\xa0\x38\xbe\x05\xc2\x3e\x05\x15\x00\x00\xb6\x42' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_persons_00825 FORMAT Protobuf SETTINGS format_schema = '$CURDIR/00825_protobuf_format:AltPerson'" -echo -ne '\xa5\x02\x0a\x24\x61\x61\x30\x65\x35\x61\x30\x36\x2d\x63\x61\x62\x32\x2d\x34\x30\x33\x34\x2d\x61\x36\x61\x32\x2d\x34\x38\x65\x38\x32\x62\x39\x31\x36\x36\x34\x65\x12\x06\x4c\x65\x6f\x6e\x69\x64\x1a\x08\x4b\x69\x72\x69\x6c\x6c\x6f\x76\x22\x04\x6d\x61\x6c\x65\x2a\x0a\x31\x39\x38\x33\x2d\x30\x36\x2d\x32\x34\x3a\x0c\x2b\x37\x34\x39\x35\x30\x32\x37\x35\x38\x36\x34\x42\x01\x31\x4a\x13\x32\x30\x31\x39\x2d\x30\x32\x2d\x30\x34\x20\x30\x39\x3a\x34\x35\x3a\x30\x30\x52\x02\x33\x35\x5a\x06\x63\x61\x6e\x63\x65\x72\x62\x07\x37\x20\x72\x69\x6e\x67\x73\x62\x08\x45\x61\x73\x74\x73\x69\x64\x65\x62\x0b\x4c\x61\x73\x74\x20\x48\x75\x72\x72\x61\x68\x6a\x01\x30\x6a\x01\x30\x6a\x03\x32\x35\x35\x72\x09\x53\x61\x6e\x20\x44\x69\x65\x67\x6f\x7a\x09\x33\x32\x2e\x38\x32\x33\x39\x34\x33\x7a\x0b\x2d\x31\x31\x37\x2e\x30\x38\x31\x33\x32\x37\x82\x01\x09\x33\x2e\x31\x34\x31\x35\x39\x32\x37\x8a\x01\x08\x31\x35\x30\x30\x30\x30\x30\x30\x92\x01\x06\x31\x38\x36\x2e\x37\x35\x9a\x01\x04\x2d\x32\x2e\x31\xa2\x01\x0b\x32\x30\x36\x35\x39\x38\x32\x39\x33\x33\x31\xaa\x01\x18\x0a\x06\x6d\x69\x6e\x75\x74\x65\x0a\x04\x68\x6f\x75\x72\x12\x02\x36\x30\x12\x04\x33\x36\x30\x30\xb2\x01\x08\x0a\x06\x12\x04\x31\x38\x30\x30' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_persons_00825 FORMAT Protobuf SETTINGS format_schema = '$CURDIR/00825_protobuf_format:StrPerson'" -echo -ne '\xdd\x01\x0a\x24\x33\x66\x61\x65\x65\x30\x36\x34\x2d\x63\x34\x66\x37\x2d\x34\x64\x33\x34\x2d\x62\x36\x66\x33\x2d\x38\x64\x38\x31\x63\x32\x62\x36\x61\x31\x35\x64\x12\x04\x4e\x69\x63\x6b\x1a\x0a\x4b\x6f\x6c\x65\x73\x6e\x69\x6b\x6f\x76\x20\x01\x28\xda\x52\x32\x03\x62\x6d\x70\x3a\x0c\x34\x31\x32\x2d\x36\x38\x37\x2d\x35\x30\x30\x37\x40\x01\x4d\x2f\x27\xf2\x5b\x50\x14\x58\x09\x62\x06\x48\x61\x76\x61\x6e\x61\x68\x80\x01\x68\x00\x68\x80\x01\x72\x0a\x50\x69\x74\x74\x73\x62\x75\x72\x67\x68\x7a\x08\x9b\x11\x22\x42\x1f\xe6\x9f\xc2\x81\x01\x28\x2d\x44\x54\xfb\x21\x09\x40\x89\x01\x00\x00\x00\xe8\x76\x48\x27\x42\x95\x01\x00\x00\x43\x44\x9d\x01\x66\x66\x92\x41\xa0\x01\xce\xdf\xb8\xba\x01\xab\x01\x0d\xcd\xcc\xe2\x41\x0d\xcd\xcc\x4c\x3e\x0d\x00\x00\x80\x3f\x12\x05\x6f\x75\x6e\x63\x65\x12\x05\x63\x61\x72\x61\x74\x12\x04\x67\x72\x61\x6d\xac\x01\xb3\x01\x0b\xa2\x06\x05\x0b\x08\x96\x4a\x0c\x0c\xb4\x01' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_persons_00825 FORMAT Protobuf SETTINGS format_schema = '$CURDIR/00825_protobuf_format_syntax2:Syntax2Person'" -echo -ne '\x04\x08\x02\x10\x04\x00\x04\x08\x03\x10\x09' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_squares_00825 FORMAT Protobuf SETTINGS format_schema = '$CURDIR/00825_protobuf_format:NumberAndSquare'" diff --git a/tests/queries/0_stateless/00825_protobuf_format_input.reference b/tests/queries/0_stateless/00825_protobuf_format_input.reference deleted file mode 100644 index 75fef3f8ac3..00000000000 --- a/tests/queries/0_stateless/00825_protobuf_format_input.reference +++ /dev/null @@ -1,18 +0,0 @@ -a7da1aa6-f425-4789-8947-b034786ed374 Vasily Sidorov male 1995-07-28 bmp +442012345678 1 2018-12-30 00:00:00 23 leo ['Sunny'] [250,244,10] Murmansk [68.970680,33.074982] 3.14159265358979 100000000000.00 800 -3.2 154400000 ['pound'] [16] 503 [] -c694ad8a-f714-4ea3-907d-fd54fb25d9b5 Natalia Sokolova female 1992-03-08 jpg \N 0 \N 26 pisces [] [100,200,50] Plymouth [50.403724,-4.142123] 3.14159 \N 0.007 5.4 -20000000000000 [] [] \N [] -aa0e5a06-cab2-4034-a6a2-48e82b91664e Leonid Kirillov male 1983-06-24 \N +74950275864\0 1 2019-02-04 09:45:00 35 cancer ['7 rings','Eastside','Last Hurrah'] [0,0,255] San Diego [32.823943,-117.081327] 3.1415927 15000000.00 186.75 -2.1 20659829331 ['minute','hour'] [60,3600] \N [1800] -20fcd95a-332d-41db-a9ec-161f644d059c Frida Ermakova female 1978-12-12 \N 3124555929\0\0\0 0 2013-03-11 16:30:00 40 sagittarius [] [110,210,74] [42.000000,-88.000000] 3.1410000324249268 311.00 0.5 10.0 8010000009 ['KB','MB'] [1024,1048576] 700 [701] -a7522158-3d41-4b77-ad69-6c598ee55c49 Ivan Petrov male 1980-12-29 png +74951234567\0 1 2019-01-05 18:45:00 38 capricorn ['Yesterday','Flowers'] [255,0,0] Moscow [55.753216,37.622504] 3.14 214.10 0.1 5.8 17060000000 ['meter','centimeter','kilometer'] [1,0.01,1000] 500 [501,502] -3faee064-c4f7-4d34-b6f3-8d81c2b6a15d Nick Kolesnikov male 1998-12-26 bmp 412-687-5007\0 1 2018-11-19 05:59:59 20 capricorn ['Havana'] [128,0,128] Pittsburgh [40.517192,-79.949456] 3.1415926535898 50000000000.00 780 18.3 195500007 ['ounce','carat','gram'] [28.35,0.2,1] 9494 [] -7cfa6856-a54a-4786-b8e5-745159d52278 Isolde Lavrova female 1987-02-09 \N \N 1 \N 32 aquarius [] [255,0,255] [26.000000,-80.000000] 3.1415998935699463 \N 4.5 25.0 -11111111111111 ['Byte','Bit'] [8,1] 702 [] -0 0 -2 4 -3 9 -a7da1aa6-f425-4789-8947-b034786ed374 Vasily Sidorov male 1995-07-28 bmp +442012345678 1 2018-12-30 00:00:00 23 leo ['Sunny'] [250,244,10] Murmansk [68.970680,33.074982] 3.14159265358979 100000000000.00 800 -3.2 154400000 ['pound'] [16] 503 [] -c694ad8a-f714-4ea3-907d-fd54fb25d9b5 Natalia Sokolova female 1992-03-08 jpg \N 0 \N 26 pisces [] [100,200,50] Plymouth [50.403724,-4.142123] 3.14159 \N 0.007 5.4 -20000000000000 [] [] \N [] -a7522158-3d41-4b77-ad69-6c598ee55c49 Ivan Petrov male 1980-12-29 png +74951234567\0 1 2019-01-05 18:45:00 38 capricorn ['Yesterday','Flowers'] [255,0,0] Moscow [55.753216,37.622504] 3.14 214.10 0.1 5.8 17060000000 ['meter','centimeter','kilometer'] [1,0.01,1000] 500 [501,502] -3faee064-c4f7-4d34-b6f3-8d81c2b6a15d Nick Kolesnikov male 1998-12-26 bmp 412-687-5007\0 1 2018-11-19 05:59:59 20 capricorn ['Havana'] [128,0,128] Pittsburgh [40.517192,-79.949456] 3.1415926535898 50000000000.00 780 18.3 195500007 ['ounce','carat','gram'] [28.35,0.2,1] 9494 [] -2 4 -3 9 -ok -ok diff --git a/tests/queries/0_stateless/00825_protobuf_format_input.sh b/tests/queries/0_stateless/00825_protobuf_format_input.sh deleted file mode 100755 index 5a85a852cb1..00000000000 --- a/tests/queries/0_stateless/00825_protobuf_format_input.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash - -CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) -# shellcheck source=../shell_config.sh -. "$CURDIR"/../shell_config.sh - -set -eo pipefail - -# Run the client. -$CLICKHOUSE_CLIENT --multiquery <<'EOF' -DROP TABLE IF EXISTS in_persons_00825; -DROP TABLE IF EXISTS in_squares_00825; - -CREATE TABLE in_persons_00825 (uuid UUID, - name String, - surname String, - gender Enum8('male'=1, 'female'=0), - birthDate Date, - photo Nullable(String), - phoneNumber Nullable(FixedString(13)), - isOnline UInt8, - visitTime Nullable(DateTime), - age UInt8, - zodiacSign Enum16('aries'=321, 'taurus'=420, 'gemini'=521, 'cancer'=621, 'leo'=723, 'virgo'=823, - 'libra'=923, 'scorpius'=1023, 'sagittarius'=1122, 'capricorn'=1222, 'aquarius'=120, - 'pisces'=219), - songs Array(String), - color Array(UInt8), - hometown LowCardinality(String), - location Array(Decimal32(6)), - pi Nullable(Float64), - lotteryWin Nullable(Decimal64(2)), - someRatio Float32, - temperature Decimal32(1), - randomBigNumber Int64, - measureUnits Nested (unit String, coef Float32), - nestiness_a_b_c_d Nullable(UInt32), - `nestiness_a_B.c_E` Array(UInt32) - ) ENGINE = MergeTree ORDER BY tuple(); - -CREATE TABLE in_squares_00825 (number UInt32, square UInt32) ENGINE = MergeTree ORDER BY tuple(); -EOF - -# To generate the file 00825_protobuf_format_input.insh use the following commands: -# ninja ProtobufDelimitedMessagesSerializer -# build/utils/test-data-generator/ProtobufDelimitedMessagesSerializer -# shellcheck source=./00825_protobuf_format_input.insh -source "$CURDIR"/00825_protobuf_format_input.insh - -$CLICKHOUSE_CLIENT --query "SELECT * FROM in_persons_00825 ORDER BY uuid;" -$CLICKHOUSE_CLIENT --query "SELECT * FROM in_squares_00825 ORDER BY number;" - -$CLICKHOUSE_CLIENT --query "TRUNCATE TABLE in_persons_00825;" -$CLICKHOUSE_CLIENT --query "TRUNCATE TABLE in_squares_00825;" - -# shellcheck source=./00825_protobuf_format_input_single.insh -source "$CURDIR"/00825_protobuf_format_input_single.insh - -$CLICKHOUSE_CLIENT --query "SELECT * FROM in_persons_00825 ORDER BY uuid;" -$CLICKHOUSE_CLIENT --query "SELECT * FROM in_squares_00825 ORDER BY number;" - -# Try to input malformed data. -set +eo pipefail -echo -ne '\xe0\x80\x3f\x0b' \ - | $CLICKHOUSE_CLIENT --query="INSERT INTO in_persons_00825 FORMAT Protobuf SETTINGS format_schema = '$CURDIR/00825_protobuf_format:Person'" 2>&1 \ - | grep -qF "Protobuf messages are corrupted" && echo "ok" || echo "fail" -set -eo pipefail - -# Try to input malformed data for ProtobufSingle -set +eo pipefail -echo -ne '\xff\xff\x3f\x0b' \ - | $CLICKHOUSE_CLIENT --query="INSERT INTO in_persons_00825 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:Person'" 2>&1 \ - | grep -qF "Protobuf messages are corrupted" && echo "ok" || echo "fail" -set -eo pipefail - -$CLICKHOUSE_CLIENT --query "DROP TABLE IF EXISTS in_persons_00825;" -$CLICKHOUSE_CLIENT --query "DROP TABLE IF EXISTS in_squares_00825;" diff --git a/tests/queries/0_stateless/00825_protobuf_format_input_single.insh b/tests/queries/0_stateless/00825_protobuf_format_input_single.insh deleted file mode 100644 index 6c4dfec05aa..00000000000 --- a/tests/queries/0_stateless/00825_protobuf_format_input_single.insh +++ /dev/null @@ -1,12 +0,0 @@ -echo -ne '\x0a\x24\x61\x37\x35\x32\x32\x31\x35\x38\x2d\x33\x64\x34\x31\x2d\x34\x62\x37\x37\x2d\x61\x64\x36\x39\x2d\x36\x63\x35\x39\x38\x65\x65\x35\x35\x63\x34\x39\x12\x04\x49\x76\x61\x6e\x1a\x06\x50\x65\x74\x72\x6f\x76\x20\x01\x28\xaf\x1f\x32\x03\x70\x6e\x67\x3a\x0c\x2b\x37\x34\x39\x35\x31\x32\x33\x34\x35\x36\x37\x40\x01\x4d\xfc\xd0\x30\x5c\x50\x26\x58\x09\x62\x09\x59\x65\x73\x74\x65\x72\x64\x61\x79\x62\x07\x46\x6c\x6f\x77\x65\x72\x73\x6a\x04\xff\x01\x00\x00\x72\x06\x4d\x6f\x73\x63\x6f\x77\x7a\x08\x4b\x03\x5f\x42\x72\x7d\x16\x42\x81\x01\x1f\x85\xeb\x51\xb8\x1e\x09\x40\x89\x01\x33\x33\x33\x33\x33\xc3\x6a\x40\x95\x01\xcd\xcc\xcc\x3d\x9d\x01\x9a\x99\xb9\x40\xa0\x01\x80\xc4\xd7\x8d\x7f\xaa\x01\x0c\x0a\x05\x6d\x65\x74\x65\x72\x15\x00\x00\x80\x3f\xaa\x01\x11\x0a\x0a\x63\x65\x6e\x74\x69\x6d\x65\x74\x65\x72\x15\x0a\xd7\x23\x3c\xaa\x01\x10\x0a\x09\x6b\x69\x6c\x6f\x6d\x65\x74\x65\x72\x15\x00\x00\x7a\x44\xb2\x01\x10\x0a\x0e\xa2\x06\x0b\x0a\x09\x08\xf4\x03\x12\x04\xf5\x03\xf6\x03' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_persons_00825 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:Person'" -echo -ne '\x0a\x24\x63\x36\x39\x34\x61\x64\x38\x61\x2d\x66\x37\x31\x34\x2d\x34\x65\x61\x33\x2d\x39\x30\x37\x64\x2d\x66\x64\x35\x34\x66\x62\x32\x35\x64\x39\x62\x35\x12\x07\x4e\x61\x74\x61\x6c\x69\x61\x1a\x08\x53\x6f\x6b\x6f\x6c\x6f\x76\x61\x28\xa6\x3f\x32\x03\x6a\x70\x67\x50\x1a\x58\x0b\x6a\x04\x64\xc8\x01\x32\x72\x08\x50\x6c\x79\x6d\x6f\x75\x74\x68\x7a\x08\x6a\x9d\x49\x42\x46\x8c\x84\xc0\x81\x01\x6e\x86\x1b\xf0\xf9\x21\x09\x40\x95\x01\x42\x60\xe5\x3b\x9d\x01\xcd\xcc\xac\x40\xa0\x01\xff\xff\xa9\xce\x93\x8c\x09' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_persons_00825 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:Person'" -echo -ne '\x0a\x24\x61\x37\x64\x61\x31\x61\x61\x36\x2d\x66\x34\x32\x35\x2d\x34\x37\x38\x39\x2d\x38\x39\x34\x37\x2d\x62\x30\x33\x34\x37\x38\x36\x65\x64\x33\x37\x34\x12\x06\x56\x61\x73\x69\x6c\x79\x1a\x07\x53\x69\x64\x6f\x72\x6f\x76\x20\x01\x28\xfb\x48\x32\x03\x62\x6d\x70\x3a\x0d\x2b\x34\x34\x32\x30\x31\x32\x33\x34\x35\x36\x37\x38\x40\x01\x4d\x50\xe0\x27\x5c\x50\x17\x58\x04\x62\x05\x53\x75\x6e\x6e\x79\x6a\x05\xfa\x01\xf4\x01\x0a\x72\x08\x4d\x75\x72\x6d\x61\x6e\x73\x6b\x7a\x08\xfd\xf0\x89\x42\xc8\x4c\x04\x42\x81\x01\x11\x2d\x44\x54\xfb\x21\x09\x40\x89\x01\x00\x00\x00\xe8\x76\x48\x37\x42\x95\x01\x00\x00\x48\x44\x9d\x01\xcd\xcc\x4c\xc0\xa0\x01\x80\xd4\x9f\x93\x01\xaa\x01\x0c\x0a\x05\x70\x6f\x75\x6e\x64\x15\x00\x00\x80\x41\xb2\x01\x0a\x0a\x08\xa2\x06\x05\x0a\x03\x08\xf7\x03' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_persons_00825 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:Person'" -echo -ne '\x0a\x24\x33\x66\x61\x65\x65\x30\x36\x34\x2d\x63\x34\x66\x37\x2d\x34\x64\x33\x34\x2d\x62\x36\x66\x33\x2d\x38\x64\x38\x31\x63\x32\x62\x36\x61\x31\x35\x64\x12\x04\x4e\x69\x63\x6b\x1a\x0a\x4b\x6f\x6c\x65\x73\x6e\x69\x6b\x6f\x76\x20\x01\x28\xda\x52\x32\x03\x62\x6d\x70\x3a\x0c\x34\x31\x32\x2d\x36\x38\x37\x2d\x35\x30\x30\x37\x40\x01\x4d\x2f\x27\xf2\x5b\x50\x14\x58\x09\x62\x06\x48\x61\x76\x61\x6e\x61\x68\x80\x01\x68\x00\x68\x80\x01\x72\x0a\x50\x69\x74\x74\x73\x62\x75\x72\x67\x68\x7a\x08\x9b\x11\x22\x42\x1f\xe6\x9f\xc2\x81\x01\x28\x2d\x44\x54\xfb\x21\x09\x40\x89\x01\x00\x00\x00\xe8\x76\x48\x27\x42\x95\x01\x00\x00\x43\x44\x9d\x01\x66\x66\x92\x41\xa0\x01\xce\xdf\xb8\xba\x01\xab\x01\x0d\xcd\xcc\xe2\x41\x0d\xcd\xcc\x4c\x3e\x0d\x00\x00\x80\x3f\x12\x05\x6f\x75\x6e\x63\x65\x12\x05\x63\x61\x72\x61\x74\x12\x04\x67\x72\x61\x6d\xac\x01\xb3\x01\x0b\xa2\x06\x05\x0b\x08\x96\x4a\x0c\x0c\xb4\x01' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_persons_00825 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format_syntax2:Syntax2Person'" - -echo -ne '\x08\x02\x10\x04' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_squares_00825 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:NumberAndSquare'" -echo -ne '\x08\x03\x10\x09' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_squares_00825 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:NumberAndSquare'" - -### Actually empty Protobuf message is a valid message (with all values default). -### It will work in Kafka but clickhouse-client forbids that: -### Code: 108. DB::Exception: No data to insert -## echo -ne '' | $CLICKHOUSE_CLIENT --query="INSERT INTO in_squares_00825 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:NumberAndSquare'" \ No newline at end of file diff --git a/tests/queries/0_stateless/00825_protobuf_format_map.reference b/tests/queries/0_stateless/00825_protobuf_format_map.reference new file mode 100644 index 00000000000..e3f17cb1095 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_map.reference @@ -0,0 +1,19 @@ +{'x':5,'y':7} +{'z':11} +{'temp':0} +{'':0} + +Binary representation: +00000000 0e 0a 05 0a 01 78 10 05 0a 05 0a 01 79 10 07 07 |.....x......y...| +00000010 0a 05 0a 01 7a 10 0b 0a 0a 08 0a 04 74 65 6d 70 |....z.......temp| +00000020 10 00 06 0a 04 0a 00 10 00 |.........| +00000029 + +{'x':5,'y':7} +{'z':11} +{'temp':0} +{'':0} +{'x':5,'y':7} +{'z':11} +{'temp':0} +{'':0} diff --git a/tests/queries/0_stateless/00825_protobuf_format_map.sh b/tests/queries/0_stateless/00825_protobuf_format_map.sh new file mode 100755 index 00000000000..877fe73603e --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_map.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +SCHEMADIR=$CURDIR/format_schemas +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +set -eo pipefail + +# Run the client. +$CLICKHOUSE_CLIENT --multiquery < "$BINARY_FILE_PATH" + +# Check the output in the protobuf format +echo +echo "Binary representation:" +hexdump -C $BINARY_FILE_PATH + +# Check the input in the protobuf format (now the table contains the same data twice). +echo +$CLICKHOUSE_CLIENT --query "INSERT INTO map_protobuf_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_map:Message'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM map_protobuf_00825" + +rm "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "DROP TABLE map_protobuf_00825" diff --git a/tests/queries/0_stateless/00825_protobuf_format_nested_in_nested.reference b/tests/queries/0_stateless/00825_protobuf_format_nested_in_nested.reference new file mode 100644 index 00000000000..08fb4696506 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_nested_in_nested.reference @@ -0,0 +1,52 @@ +[[(1),(2)],[(3),(4),(5)]] +[[(6)]] +[[]] +[] + +Binary representation: +00000000 18 0a 08 12 02 18 01 12 02 18 02 0a 0c 12 02 18 |................| +00000010 03 12 02 18 04 12 02 18 05 06 0a 04 12 02 18 06 |................| +00000020 02 0a 00 00 |....| +00000024 + +MESSAGE #1 AT 0x00000001 +x { + y { + z: 1 + } + y { + z: 2 + } +} +x { + y { + z: 3 + } + y { + z: 4 + } + y { + z: 5 + } +} +MESSAGE #2 AT 0x0000001A +x { + y { + z: 6 + } +} +MESSAGE #3 AT 0x00000021 +x { +} +MESSAGE #4 AT 0x00000024 + +Binary representation is as expected + +[[(1),(2)],[(3),(4),(5)]] +[[(6)]] +[[]] +[] +[[(1),(2)],[(3),(4),(5)]] +[[(6)]] +[[]] +[] diff --git a/tests/queries/0_stateless/00825_protobuf_format_nested_in_nested.sh b/tests/queries/0_stateless/00825_protobuf_format_nested_in_nested.sh new file mode 100755 index 00000000000..9d382f8c589 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_nested_in_nested.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# https://github.com/ClickHouse/ClickHouse/issues/11117 + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +SCHEMADIR=$CURDIR/format_schemas +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +set -eo pipefail + +# Run the client. +$CLICKHOUSE_CLIENT --multiquery < "$BINARY_FILE_PATH" + +# Check the output in the protobuf format +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_nested_in_nested:MessageType" --input "$BINARY_FILE_PATH" + +# Check the input in the protobuf format (now the table contains the same data twice). +echo +$CLICKHOUSE_CLIENT --query "INSERT INTO nested_in_nested_protobuf_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_nested_in_nested:MessageType'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM nested_in_nested_protobuf_00825" + +rm "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "DROP TABLE nested_in_nested_protobuf_00825" diff --git a/tests/queries/0_stateless/00825_protobuf_format_nested_optional.reference b/tests/queries/0_stateless/00825_protobuf_format_nested_optional.reference new file mode 100644 index 00000000000..6cdd56a5b7f --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_nested_optional.reference @@ -0,0 +1,25 @@ +['1'] [0] +['1',''] [0,1] + +Binary representation: +00000000 05 0a 03 0a 01 31 09 0a 03 0a 01 31 0a 02 10 01 |.....1.....1....| +00000010 + +MESSAGE #1 AT 0x00000001 +messages { + foo: "1" +} +MESSAGE #2 AT 0x00000007 +messages { + foo: "1" +} +messages { + bar: 1 +} + +Binary representation is as expected + +['1'] [0] +['1',''] [0,1] +['1'] [0] +['1',''] [0,1] diff --git a/tests/queries/0_stateless/00825_protobuf_format_nested_optional.sh b/tests/queries/0_stateless/00825_protobuf_format_nested_optional.sh new file mode 100755 index 00000000000..b33db75b5c9 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_nested_optional.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# https://github.com/ClickHouse/ClickHouse/issues/6497 + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +SCHEMADIR=$CURDIR/format_schemas +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +set -eo pipefail + +# Run the client. +$CLICKHOUSE_CLIENT --multiquery < "$BINARY_FILE_PATH" + +# Check the output in the protobuf format +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_nested_optional:Message" --input "$BINARY_FILE_PATH" + +# Check the input in the protobuf format (now the table contains the same data twice). +echo +$CLICKHOUSE_CLIENT --query "INSERT INTO nested_optional_protobuf_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_nested_optional:Message'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM nested_optional_protobuf_00825" + +rm "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "DROP TABLE nested_optional_protobuf_00825" diff --git a/tests/queries/0_stateless/00825_protobuf_format_no_length_delimiter.reference b/tests/queries/0_stateless/00825_protobuf_format_no_length_delimiter.reference new file mode 100644 index 00000000000..ba84d41eb51 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_no_length_delimiter.reference @@ -0,0 +1,13 @@ +1000 1K +2000 2K +3000 3K + +Binary representation: +00000000 08 e8 07 12 02 31 4b |.....1K| +00000007 + +x: 1000 +str: "1K" + +Roundtrip: +1000 1K diff --git a/tests/queries/0_stateless/00825_protobuf_format_no_length_delimiter.sh b/tests/queries/0_stateless/00825_protobuf_format_no_length_delimiter.sh new file mode 100755 index 00000000000..b95d35e8256 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_no_length_delimiter.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +SCHEMADIR=$CURDIR/format_schemas +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +set -eo pipefail + +# Run the client. +$CLICKHOUSE_CLIENT --multiquery < "$BINARY_FILE_PATH" + +# Check the output in the ProtobufSingle format +echo +echo "Binary representation:" +hexdump -C $BINARY_FILE_PATH + +echo +(cd $SCHEMADIR && protoc --decode Message 00825_protobuf_format_no_length_delimiter.proto) < $BINARY_FILE_PATH + +# Check the input in the ProtobufSingle format. +echo +echo "Roundtrip:" +$CLICKHOUSE_CLIENT --query "CREATE TABLE roundtrip_no_length_delimiter_protobuf_00825 AS no_length_delimiter_protobuf_00825" +$CLICKHOUSE_CLIENT --query "INSERT INTO roundtrip_no_length_delimiter_protobuf_00825 FORMAT ProtobufSingle SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_no_length_delimiter:Message'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM roundtrip_no_length_delimiter_protobuf_00825" +rm "$BINARY_FILE_PATH" + +# The ProtobufSingle format can't be used to write multiple rows because this format doesn't have any row delimiter. +$CLICKHOUSE_CLIENT --multiquery --testmode > /dev/null <'; -SELECT * FROM out_persons_00825 ORDER BY name FORMAT Protobuf SETTINGS format_schema = '$CURDIR/00825_protobuf_format:AltPerson'; -SELECT 'STRINGS->'; -SELECT * FROM out_persons_00825 ORDER BY name FORMAT Protobuf SETTINGS format_schema = '$CURDIR/00825_protobuf_format:StrPerson'; -SELECT 'SYNTAX2->'; -SELECT * FROM out_persons_00825 ORDER BY name FORMAT Protobuf SETTINGS format_schema = '$CURDIR/00825_protobuf_format_syntax2:Syntax2Person'; -SELECT 'SQUARES->'; -SELECT * FROM out_squares_00825 ORDER BY number FORMAT Protobuf SETTINGS format_schema = '$CURDIR/00825_protobuf_format:NumberAndSquare'; - -SELECT '\n\n** ProtobufSingle **\n\n'; - -SELECT * FROM out_persons_00825 ORDER BY name LIMIT 1 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:Person'; -SELECT 'ALTERNATIVE->'; -SELECT * FROM out_persons_00825 ORDER BY name LIMIT 1 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:AltPerson'; -SELECT 'STRINGS->'; -SELECT * FROM out_persons_00825 ORDER BY name LIMIT 1 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:StrPerson'; -SELECT 'SYNTAX2->'; -SELECT * FROM out_persons_00825 ORDER BY name LIMIT 1 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format_syntax2:Syntax2Person'; -SELECT 'SQUARES->'; -SELECT * FROM out_squares_00825 ORDER BY number LIMIT 1 FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:NumberAndSquare'; - --- Code: 546, e.displayText() = DB::Exception: The ProtobufSingle format can't be used to write multiple rows because this format doesn't have any row delimiter. -SELECT * FROM out_persons_00825 ORDER BY name FORMAT ProtobufSingle SETTINGS format_schema = '$CURDIR/00825_protobuf_format:Person'; -- { clientError 546 } - -DROP TABLE IF EXISTS out_persons_00825; -DROP TABLE IF EXISTS out_squares_00825; -EOF diff --git a/tests/queries/0_stateless/00825_protobuf_format_persons.reference b/tests/queries/0_stateless/00825_protobuf_format_persons.reference new file mode 100644 index 00000000000..711980b3592 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_persons.reference @@ -0,0 +1,569 @@ +a7522158-3d41-4b77-ad69-6c598ee55c49 Ivan Petrov male 1980-12-29 png +74951234567\0 1 2019-01-05 18:45:00 38 capricorn ['Yesterday','Flowers'] [255,0,0] Moscow [55.753215,37.622504] 3.14 214.10 0.1 5.8 17060000000 ['meter','centimeter','kilometer'] [1,0.01,1000] 500 [501,502] +c694ad8a-f714-4ea3-907d-fd54fb25d9b5 Natalia Sokolova female 1992-03-08 jpg \N 0 \N 26 pisces [] [100,200,50] Plymouth [50.403724,-4.142123] 3.14159 \N 0.007 5.4 -20000000000000 [] [] \N [] +a7da1aa6-f425-4789-8947-b034786ed374 Vasily Sidorov male 1995-07-28 bmp +442012345678 1 2018-12-30 00:00:00 23 leo ['Sunny'] [250,244,10] Murmansk [68.970682,33.074981] 3.14159265358979 100000000000.00 800 -3.2 154400000 ['pound'] [16] 503 [] + +Schema 00825_protobuf_format_persons:Person + +Binary representation: +00000000 f4 01 0a 24 61 37 35 32 32 31 35 38 2d 33 64 34 |...$a7522158-3d4| +00000010 31 2d 34 62 37 37 2d 61 64 36 39 2d 36 63 35 39 |1-4b77-ad69-6c59| +00000020 38 65 65 35 35 63 34 39 12 04 49 76 61 6e 1a 06 |8ee55c49..Ivan..| +00000030 50 65 74 72 6f 76 20 01 28 af 1f 32 03 70 6e 67 |Petrov .(..2.png| +00000040 3a 0d 2b 37 34 39 35 31 32 33 34 35 36 37 00 40 |:.+74951234567.@| +00000050 01 4d fc d0 30 5c 50 26 58 09 62 09 59 65 73 74 |.M..0\P&X.b.Yest| +00000060 65 72 64 61 79 62 07 46 6c 6f 77 65 72 73 6a 04 |erdayb.Flowersj.| +00000070 ff 01 00 00 72 06 4d 6f 73 63 6f 77 7a 08 4b 03 |....r.Moscowz.K.| +00000080 5f 42 72 7d 16 42 81 01 1f 85 eb 51 b8 1e 09 40 |_Br}.B.....Q...@| +00000090 89 01 33 33 33 33 33 c3 6a 40 95 01 cd cc cc 3d |..33333.j@.....=| +000000a0 9d 01 9a 99 b9 40 a0 01 80 c4 d7 8d 7f aa 01 0c |.....@..........| +000000b0 0a 05 6d 65 74 65 72 15 00 00 80 3f aa 01 11 0a |..meter....?....| +000000c0 0a 63 65 6e 74 69 6d 65 74 65 72 15 0a d7 23 3c |.centimeter...#<| +000000d0 aa 01 10 0a 09 6b 69 6c 6f 6d 65 74 65 72 15 00 |.....kilometer..| +000000e0 00 7a 44 b2 01 10 0a 0e a2 06 0b 0a 09 08 f4 03 |.zD.............| +000000f0 12 04 f5 03 f6 03 7e 0a 24 63 36 39 34 61 64 38 |......~.$c694ad8| +00000100 61 2d 66 37 31 34 2d 34 65 61 33 2d 39 30 37 64 |a-f714-4ea3-907d| +00000110 2d 66 64 35 34 66 62 32 35 64 39 62 35 12 07 4e |-fd54fb25d9b5..N| +00000120 61 74 61 6c 69 61 1a 08 53 6f 6b 6f 6c 6f 76 61 |atalia..Sokolova| +00000130 28 a6 3f 32 03 6a 70 67 50 1a 58 0b 6a 04 64 c8 |(.?2.jpgP.X.j.d.| +00000140 01 32 72 08 50 6c 79 6d 6f 75 74 68 7a 08 6a 9d |.2r.Plymouthz.j.| +00000150 49 42 46 8c 84 c0 81 01 6e 86 1b f0 f9 21 09 40 |IBF.....n....!.@| +00000160 95 01 42 60 e5 3b 9d 01 cd cc ac 40 a0 01 ff ff |..B`.;.....@....| +00000170 a9 ce 93 8c 09 c0 01 0a 24 61 37 64 61 31 61 61 |........$a7da1aa| +00000180 36 2d 66 34 32 35 2d 34 37 38 39 2d 38 39 34 37 |6-f425-4789-8947| +00000190 2d 62 30 33 34 37 38 36 65 64 33 37 34 12 06 56 |-b034786ed374..V| +000001a0 61 73 69 6c 79 1a 07 53 69 64 6f 72 6f 76 20 01 |asily..Sidorov .| +000001b0 28 fb 48 32 03 62 6d 70 3a 0d 2b 34 34 32 30 31 |(.H2.bmp:.+44201| +000001c0 32 33 34 35 36 37 38 40 01 4d 50 e0 27 5c 50 17 |2345678@.MP.'\P.| +000001d0 58 04 62 05 53 75 6e 6e 79 6a 05 fa 01 f4 01 0a |X.b.Sunnyj......| +000001e0 72 08 4d 75 72 6d 61 6e 73 6b 7a 08 fd f0 89 42 |r.Murmanskz....B| +000001f0 c8 4c 04 42 81 01 11 2d 44 54 fb 21 09 40 89 01 |.L.B...-DT.!.@..| +00000200 00 00 00 e8 76 48 37 42 95 01 00 00 48 44 9d 01 |....vH7B....HD..| +00000210 cd cc 4c c0 a0 01 80 d4 9f 93 01 aa 01 0c 0a 05 |..L.............| +00000220 70 6f 75 6e 64 15 00 00 80 41 b2 01 0a 0a 08 a2 |pound....A......| +00000230 06 05 0a 03 08 f7 03 |.......| +00000237 + +MESSAGE #1 AT 0x00000002 +uuid: "a7522158-3d41-4b77-ad69-6c598ee55c49" +name: "Ivan" +surname: "Petrov" +gender: male +birthDate: 4015 +photo: "png" +phoneNumber: "+74951234567\000" +isOnline: true +visitTime: 1546703100 +age: 38 +zodiacSign: capricorn +songs: "Yesterday" +songs: "Flowers" +color: 255 +color: 0 +color: 0 +hometown: "Moscow" +location: 55.7532158 +location: 37.6225052 +pi: 3.14 +lotteryWin: 214.1 +someRatio: 0.1 +temperature: 5.8 +randomBigNumber: 17060000000 +measureUnits { + unit: "meter" + coef: 1 +} +measureUnits { + unit: "centimeter" + coef: 0.01 +} +measureUnits { + unit: "kilometer" + coef: 1000 +} +nestiness { + a { + b { + c { + d: 500 + e: 501 + e: 502 + } + } + } +} +MESSAGE #2 AT 0x000000F7 +uuid: "c694ad8a-f714-4ea3-907d-fd54fb25d9b5" +name: "Natalia" +surname: "Sokolova" +birthDate: 8102 +photo: "jpg" +age: 26 +zodiacSign: pisces +color: 100 +color: 200 +color: 50 +hometown: "Plymouth" +location: 50.4037247 +location: -4.14212322 +pi: 3.14159 +someRatio: 0.007 +temperature: 5.4 +randomBigNumber: -20000000000000 +MESSAGE #3 AT 0x00000177 +uuid: "a7da1aa6-f425-4789-8947-b034786ed374" +name: "Vasily" +surname: "Sidorov" +gender: male +birthDate: 9339 +photo: "bmp" +phoneNumber: "+442012345678" +isOnline: true +visitTime: 1546117200 +age: 23 +zodiacSign: leo +songs: "Sunny" +color: 250 +color: 244 +color: 10 +hometown: "Murmansk" +location: 68.9706802 +location: 33.0749817 +pi: 3.14159265358979 +lotteryWin: 100000000000 +someRatio: 800 +temperature: -3.2 +randomBigNumber: 154400000 +measureUnits { + unit: "pound" + coef: 16 +} +nestiness { + a { + b { + c { + d: 503 + } + } + } +} + +Binary representation is as expected + +Roundtrip: +a7522158-3d41-4b77-ad69-6c598ee55c49 Ivan Petrov male 1980-12-29 png +74951234567\0 1 2019-01-05 18:45:00 38 capricorn ['Yesterday','Flowers'] [255,0,0] Moscow [55.753216,37.622504] 3.14 214.10 0.1 5.8 17060000000 ['meter','centimeter','kilometer'] [1,0.01,1000] 500 [501,502] +c694ad8a-f714-4ea3-907d-fd54fb25d9b5 Natalia Sokolova female 1992-03-08 jpg \N 0 \N 26 pisces [] [100,200,50] Plymouth [50.403724,-4.142123] 3.14159 \N 0.007 5.4 -20000000000000 [] [] \N [] +a7da1aa6-f425-4789-8947-b034786ed374 Vasily Sidorov male 1995-07-28 bmp +442012345678 1 2018-12-30 00:00:00 23 leo ['Sunny'] [250,244,10] Murmansk [68.970680,33.074982] 3.14159265358979 100000000000.00 800 -3.2 154400000 ['pound'] [16] 503 [] + +Schema 00825_protobuf_format_persons:AltPerson + +Binary representation: +00000000 c4 01 08 01 12 04 49 76 61 6e 28 87 a8 c4 9b 97 |......Ivan(.....| +00000010 02 52 06 50 65 74 72 6f 76 72 0c 00 00 7f 43 00 |.R.Petrovr....C.| +00000020 00 00 00 00 00 00 00 79 fc d0 30 5c 00 00 00 00 |.......y..0\....| +00000030 c8 02 0a c2 05 0c 00 00 80 3f 0a d7 23 3c 00 00 |.........?..#<..| +00000040 7a 44 9a 06 05 6d 65 74 65 72 9a 06 0a 63 65 6e |zD...meter...cen| +00000050 74 69 6d 65 74 65 72 9a 06 09 6b 69 6c 6f 6d 65 |timeter...kilome| +00000060 74 65 72 a1 06 00 00 00 a0 99 99 b9 3f a8 06 37 |ter.........?..7| +00000070 a8 06 25 bd 06 c3 f5 48 40 fa 06 02 33 38 90 08 |..%....H@...38..| +00000080 c6 09 e1 08 00 f1 da f8 03 00 00 00 b0 09 af 1f |................| +00000090 d0 0c d6 01 e2 12 24 61 37 35 32 32 31 35 38 2d |......$a7522158-| +000000a0 33 64 34 31 2d 34 62 37 37 2d 61 64 36 39 2d 36 |3d41-4b77-ad69-6| +000000b0 63 35 39 38 65 65 35 35 63 34 39 a0 38 f4 03 aa |c598ee55c49.8...| +000000c0 38 04 f5 03 f6 03 84 01 12 07 4e 61 74 61 6c 69 |8.........Natali| +000000d0 61 52 08 53 6f 6b 6f 6c 6f 76 61 72 0c 00 00 c8 |aR.Sokolovar....| +000000e0 42 00 00 48 43 00 00 48 42 c8 02 0a a1 06 00 00 |B..HC..HB.......| +000000f0 00 40 08 ac 7c 3f a8 06 32 a8 06 fc ff ff ff ff |.@..|?..2.......| +00000100 ff ff ff ff 01 b0 06 01 bd 06 d0 0f 49 40 fa 06 |............I@..| +00000110 02 32 36 90 08 db 01 e1 08 00 c0 1a 63 cf ed ff |.26.........c...| +00000120 ff b0 09 a6 3f e2 12 24 63 36 39 34 61 64 38 61 |....?..$c694ad8a| +00000130 2d 66 37 31 34 2d 34 65 61 33 2d 39 30 37 64 2d |-f714-4ea3-907d-| +00000140 66 64 35 34 66 62 32 35 64 39 62 35 a3 01 08 01 |fd54fb25d9b5....| +00000150 12 06 56 61 73 69 6c 79 28 ce ca f4 cf ee 0c 52 |..Vasily(......R| +00000160 07 53 69 64 6f 72 6f 76 72 0c 00 00 7a 43 00 00 |.Sidorovr...zC..| +00000170 74 43 00 00 20 41 79 50 e0 27 5c 00 00 00 00 c8 |tC.. AyP.'\.....| +00000180 02 05 c2 05 04 00 00 80 41 9a 06 05 70 6f 75 6e |........A...poun| +00000190 64 a1 06 00 00 00 00 00 00 89 40 a8 06 44 a8 06 |d.........@..D..| +000001a0 21 bd 06 db 0f 49 40 fa 06 02 32 33 90 08 d3 05 |!....I@...23....| +000001b0 e1 08 00 f5 33 09 00 00 00 00 b0 09 fb 48 d0 0c |....3........H..| +000001c0 80 d0 db c3 f4 02 e2 12 24 61 37 64 61 31 61 61 |........$a7da1aa| +000001d0 36 2d 66 34 32 35 2d 34 37 38 39 2d 38 39 34 37 |6-f425-4789-8947| +000001e0 2d 62 30 33 34 37 38 36 65 64 33 37 34 a0 38 f7 |-b034786ed374.8.| +000001f0 03 |.| +000001f1 + +MESSAGE #1 AT 0x00000002 +isOnline: online +name: "Ivan" +phoneNumber: 74951234567 +surname: "Petrov" +color: 255 +color: 0 +color: 0 +visitTime: 1546703100 +temperature: 5 +measureUnits_coef: 1 +measureUnits_coef: 0.01 +measureUnits_coef: 1000 +measureUnits_unit: "meter" +measureUnits_unit: "centimeter" +measureUnits_unit: "kilometer" +someRatio: 0.10000000149011612 +location: 55 +location: 37 +pi: 3.14 +age: "38" +zodiacSign: 1222 +randomBigNumber: 17060000000 +birthDate: 4015 +lotteryWin: 214 +uuid: "a7522158-3d41-4b77-ad69-6c598ee55c49" +nestiness_a_b_c_d: 500 +nestiness_a_b_c_e: 501 +nestiness_a_b_c_e: 502 +MESSAGE #2 AT 0x000000C8 +name: "Natalia" +surname: "Sokolova" +color: 100 +color: 200 +color: 50 +temperature: 5 +someRatio: 0.0070000002160668373 +location: 50 +location: -4 +gender: female +pi: 3.14159 +age: "26" +zodiacSign: 219 +randomBigNumber: -20000000000000 +birthDate: 8102 +uuid: "c694ad8a-f714-4ea3-907d-fd54fb25d9b5" +MESSAGE #3 AT 0x0000014E +isOnline: online +name: "Vasily" +phoneNumber: 442012345678 +surname: "Sidorov" +color: 250 +color: 244 +color: 10 +visitTime: 1546117200 +temperature: -3 +measureUnits_coef: 16 +measureUnits_unit: "pound" +someRatio: 800 +location: 68 +location: 33 +pi: 3.14159274 +age: "23" +zodiacSign: 723 +randomBigNumber: 154400000 +birthDate: 9339 +lotteryWin: 100000000000 +uuid: "a7da1aa6-f425-4789-8947-b034786ed374" +nestiness_a_b_c_d: 503 + +Binary representation is as expected + +Roundtrip: +a7522158-3d41-4b77-ad69-6c598ee55c49 Ivan Petrov male 1980-12-29 \N 74951234567\0\0 1 2019-01-05 18:45:00 38 capricorn [] [255,0,0] [55.000000,37.000000] 3.140000104904175 214.00 0.1 5.0 17060000000 ['meter','centimeter','kilometer'] [1,0.01,1000] 500 [501,502] +c694ad8a-f714-4ea3-907d-fd54fb25d9b5 Natalia Sokolova female 1992-03-08 \N \N 0 \N 26 pisces [] [100,200,50] [50.000000,-4.000000] 3.141590118408203 \N 0.007 5.0 -20000000000000 [] [] \N [] +a7da1aa6-f425-4789-8947-b034786ed374 Vasily Sidorov male 1995-07-28 \N 442012345678\0 1 2018-12-30 00:00:00 23 leo [] [250,244,10] [68.000000,33.000000] 3.1415927410125732 100000000000.00 800 -3.0 154400000 ['pound'] [16] 503 [] + +Schema 00825_protobuf_format_persons:StrPerson + +Binary representation: +00000000 a7 02 0a 24 61 37 35 32 32 31 35 38 2d 33 64 34 |...$a7522158-3d4| +00000010 31 2d 34 62 37 37 2d 61 64 36 39 2d 36 63 35 39 |1-4b77-ad69-6c59| +00000020 38 65 65 35 35 63 34 39 12 04 49 76 61 6e 1a 06 |8ee55c49..Ivan..| +00000030 50 65 74 72 6f 76 22 04 6d 61 6c 65 2a 0a 31 39 |Petrov".male*.19| +00000040 38 30 2d 31 32 2d 32 39 3a 0d 2b 37 34 39 35 31 |80-12-29:.+74951| +00000050 32 33 34 35 36 37 00 42 01 31 4a 13 32 30 31 39 |234567.B.1J.2019| +00000060 2d 30 31 2d 30 35 20 31 38 3a 34 35 3a 30 30 52 |-01-05 18:45:00R| +00000070 02 33 38 5a 09 63 61 70 72 69 63 6f 72 6e 62 09 |.38Z.capricornb.| +00000080 59 65 73 74 65 72 64 61 79 62 07 46 6c 6f 77 65 |Yesterdayb.Flowe| +00000090 72 73 6a 03 32 35 35 6a 01 30 6a 01 30 72 06 4d |rsj.255j.0j.0r.M| +000000a0 6f 73 63 6f 77 7a 09 35 35 2e 37 35 33 32 31 35 |oscowz.55.753215| +000000b0 7a 09 33 37 2e 36 32 32 35 30 34 82 01 04 33 2e |z.37.622504...3.| +000000c0 31 34 8a 01 06 32 31 34 2e 31 30 92 01 03 30 2e |14...214.10...0.| +000000d0 31 9a 01 03 35 2e 38 a2 01 0b 31 37 30 36 30 30 |1...5.8...170600| +000000e0 30 30 30 30 30 aa 01 2d 0a 05 6d 65 74 65 72 0a |00000..-..meter.| +000000f0 0a 63 65 6e 74 69 6d 65 74 65 72 0a 09 6b 69 6c |.centimeter..kil| +00000100 6f 6d 65 74 65 72 12 01 31 12 04 30 2e 30 31 12 |ometer..1..0.01.| +00000110 04 31 30 30 30 b2 01 11 0a 0f 0a 03 35 30 30 12 |.1000.......500.| +00000120 03 35 30 31 12 03 35 30 32 b4 01 0a 24 63 36 39 |.501..502...$c69| +00000130 34 61 64 38 61 2d 66 37 31 34 2d 34 65 61 33 2d |4ad8a-f714-4ea3-| +00000140 39 30 37 64 2d 66 64 35 34 66 62 32 35 64 39 62 |907d-fd54fb25d9b| +00000150 35 12 07 4e 61 74 61 6c 69 61 1a 08 53 6f 6b 6f |5..Natalia..Soko| +00000160 6c 6f 76 61 22 06 66 65 6d 61 6c 65 2a 0a 31 39 |lova".female*.19| +00000170 39 32 2d 30 33 2d 30 38 42 01 30 52 02 32 36 5a |92-03-08B.0R.26Z| +00000180 06 70 69 73 63 65 73 6a 03 31 30 30 6a 03 32 30 |.piscesj.100j.20| +00000190 30 6a 02 35 30 72 08 50 6c 79 6d 6f 75 74 68 7a |0j.50r.Plymouthz| +000001a0 09 35 30 2e 34 30 33 37 32 34 7a 09 2d 34 2e 31 |.50.403724z.-4.1| +000001b0 34 32 31 32 33 82 01 07 33 2e 31 34 31 35 39 92 |42123...3.14159.| +000001c0 01 05 30 2e 30 30 37 9a 01 03 35 2e 34 a2 01 0f |..0.007...5.4...| +000001d0 2d 32 30 30 30 30 30 30 30 30 30 30 30 30 30 84 |-20000000000000.| +000001e0 02 0a 24 61 37 64 61 31 61 61 36 2d 66 34 32 35 |..$a7da1aa6-f425| +000001f0 2d 34 37 38 39 2d 38 39 34 37 2d 62 30 33 34 37 |-4789-8947-b0347| +00000200 38 36 65 64 33 37 34 12 06 56 61 73 69 6c 79 1a |86ed374..Vasily.| +00000210 07 53 69 64 6f 72 6f 76 22 04 6d 61 6c 65 2a 0a |.Sidorov".male*.| +00000220 31 39 39 35 2d 30 37 2d 32 38 3a 0d 2b 34 34 32 |1995-07-28:.+442| +00000230 30 31 32 33 34 35 36 37 38 42 01 31 4a 13 32 30 |012345678B.1J.20| +00000240 31 38 2d 31 32 2d 33 30 20 30 30 3a 30 30 3a 30 |18-12-30 00:00:0| +00000250 30 52 02 32 33 5a 03 6c 65 6f 62 05 53 75 6e 6e |0R.23Z.leob.Sunn| +00000260 79 6a 03 32 35 30 6a 03 32 34 34 6a 02 31 30 72 |yj.250j.244j.10r| +00000270 08 4d 75 72 6d 61 6e 73 6b 7a 09 36 38 2e 39 37 |.Murmanskz.68.97| +00000280 30 36 38 32 7a 09 33 33 2e 30 37 34 39 38 31 82 |0682z.33.074981.| +00000290 01 10 33 2e 31 34 31 35 39 32 36 35 33 35 38 39 |..3.141592653589| +000002a0 37 39 8a 01 0f 31 30 30 30 30 30 30 30 30 30 30 |79...10000000000| +000002b0 30 2e 30 30 92 01 03 38 30 30 9a 01 04 2d 33 2e |0.00...800...-3.| +000002c0 32 a2 01 09 31 35 34 34 30 30 30 30 30 aa 01 0b |2...154400000...| +000002d0 0a 05 70 6f 75 6e 64 12 02 31 36 b2 01 07 0a 05 |..pound..16.....| +000002e0 0a 03 35 30 33 |..503| +000002e5 + +MESSAGE #1 AT 0x00000002 +uuid: "a7522158-3d41-4b77-ad69-6c598ee55c49" +name: "Ivan" +surname: "Petrov" +gender: "male" +birthDate: "1980-12-29" +phoneNumber: "+74951234567\000" +isOnline: "1" +visitTime: "2019-01-05 18:45:00" +age: "38" +zodiacSign: "capricorn" +songs: "Yesterday" +songs: "Flowers" +color: "255" +color: "0" +color: "0" +hometown: "Moscow" +location: "55.753215" +location: "37.622504" +pi: "3.14" +lotteryWin: "214.10" +someRatio: "0.1" +temperature: "5.8" +randomBigNumber: "17060000000" +measureUnits { + unit: "meter" + unit: "centimeter" + unit: "kilometer" + coef: "1" + coef: "0.01" + coef: "1000" +} +nestiness_a { + b_c { + d: "500" + e: "501" + e: "502" + } +} +MESSAGE #2 AT 0x0000012B +uuid: "c694ad8a-f714-4ea3-907d-fd54fb25d9b5" +name: "Natalia" +surname: "Sokolova" +gender: "female" +birthDate: "1992-03-08" +isOnline: "0" +age: "26" +zodiacSign: "pisces" +color: "100" +color: "200" +color: "50" +hometown: "Plymouth" +location: "50.403724" +location: "-4.142123" +pi: "3.14159" +someRatio: "0.007" +temperature: "5.4" +randomBigNumber: "-20000000000000" +MESSAGE #3 AT 0x000001E1 +uuid: "a7da1aa6-f425-4789-8947-b034786ed374" +name: "Vasily" +surname: "Sidorov" +gender: "male" +birthDate: "1995-07-28" +phoneNumber: "+442012345678" +isOnline: "1" +visitTime: "2018-12-30 00:00:00" +age: "23" +zodiacSign: "leo" +songs: "Sunny" +color: "250" +color: "244" +color: "10" +hometown: "Murmansk" +location: "68.970682" +location: "33.074981" +pi: "3.14159265358979" +lotteryWin: "100000000000.00" +someRatio: "800" +temperature: "-3.2" +randomBigNumber: "154400000" +measureUnits { + unit: "pound" + coef: "16" +} +nestiness_a { + b_c { + d: "503" + } +} + +Binary representation is as expected + +Roundtrip: +a7522158-3d41-4b77-ad69-6c598ee55c49 Ivan Petrov male 1980-12-29 \N +74951234567\0 1 2019-01-05 18:45:00 38 capricorn ['Yesterday','Flowers'] [255,0,0] Moscow [55.753215,37.622504] 3.14 214.10 0.1 5.8 17060000000 ['meter','centimeter','kilometer'] [1,0.01,1000] 500 [501,502] +c694ad8a-f714-4ea3-907d-fd54fb25d9b5 Natalia Sokolova female 1992-03-08 \N \N 0 \N 26 pisces [] [100,200,50] Plymouth [50.403724,-4.142123] 3.14159 \N 0.007 5.4 -20000000000000 [] [] \N [] +a7da1aa6-f425-4789-8947-b034786ed374 Vasily Sidorov male 1995-07-28 \N +442012345678 1 2018-12-30 00:00:00 23 leo ['Sunny'] [250,244,10] Murmansk [68.970682,33.074981] 3.14159265358979 100000000000.00 800 -3.2 154400000 ['pound'] [16] 503 [] + +Schema 00825_protobuf_format_syntax2:Syntax2Person + +Binary representation: +00000000 f1 01 0a 24 61 37 35 32 32 31 35 38 2d 33 64 34 |...$a7522158-3d4| +00000010 31 2d 34 62 37 37 2d 61 64 36 39 2d 36 63 35 39 |1-4b77-ad69-6c59| +00000020 38 65 65 35 35 63 34 39 12 04 49 76 61 6e 1a 06 |8ee55c49..Ivan..| +00000030 50 65 74 72 6f 76 20 01 28 af 1f 32 03 70 6e 67 |Petrov .(..2.png| +00000040 3a 0d 2b 37 34 39 35 31 32 33 34 35 36 37 00 40 |:.+74951234567.@| +00000050 01 4d fc d0 30 5c 50 26 58 09 62 09 59 65 73 74 |.M..0\P&X.b.Yest| +00000060 65 72 64 61 79 62 07 46 6c 6f 77 65 72 73 68 ff |erdayb.Flowersh.| +00000070 01 68 00 68 00 72 06 4d 6f 73 63 6f 77 7a 08 4b |.h.h.r.Moscowz.K| +00000080 03 5f 42 72 7d 16 42 81 01 1f 85 eb 51 b8 1e 09 |._Br}.B.....Q...| +00000090 40 89 01 33 33 33 33 33 c3 6a 40 95 01 cd cc cc |@..33333.j@.....| +000000a0 3d 9d 01 9a 99 b9 40 a0 01 80 c4 d7 8d 7f ab 01 |=.....@.........| +000000b0 0d 00 00 80 3f 0d 0a d7 23 3c 0d 00 00 7a 44 12 |....?...#<...zD.| +000000c0 05 6d 65 74 65 72 12 0a 63 65 6e 74 69 6d 65 74 |.meter..centimet| +000000d0 65 72 12 09 6b 69 6c 6f 6d 65 74 65 72 ac 01 b3 |er..kilometer...| +000000e0 01 0b a2 06 0b 0b 08 f4 03 10 f5 03 10 f6 03 0c |................| +000000f0 0c b4 01 83 01 0a 24 63 36 39 34 61 64 38 61 2d |......$c694ad8a-| +00000100 66 37 31 34 2d 34 65 61 33 2d 39 30 37 64 2d 66 |f714-4ea3-907d-f| +00000110 64 35 34 66 62 32 35 64 39 62 35 12 07 4e 61 74 |d54fb25d9b5..Nat| +00000120 61 6c 69 61 1a 08 53 6f 6b 6f 6c 6f 76 61 20 00 |alia..Sokolova .| +00000130 28 a6 3f 32 03 6a 70 67 40 00 50 1a 58 0b 68 64 |(.?2.jpg@.P.X.hd| +00000140 68 c8 01 68 32 72 08 50 6c 79 6d 6f 75 74 68 7a |h..h2r.Plymouthz| +00000150 08 6a 9d 49 42 46 8c 84 c0 81 01 6e 86 1b f0 f9 |.j.IBF.....n....| +00000160 21 09 40 95 01 42 60 e5 3b 9d 01 cd cc ac 40 a0 |!.@..B`.;.....@.| +00000170 01 ff ff a9 ce 93 8c 09 c3 01 0a 24 61 37 64 61 |...........$a7da| +00000180 31 61 61 36 2d 66 34 32 35 2d 34 37 38 39 2d 38 |1aa6-f425-4789-8| +00000190 39 34 37 2d 62 30 33 34 37 38 36 65 64 33 37 34 |947-b034786ed374| +000001a0 12 06 56 61 73 69 6c 79 1a 07 53 69 64 6f 72 6f |..Vasily..Sidoro| +000001b0 76 20 01 28 fb 48 32 03 62 6d 70 3a 0d 2b 34 34 |v .(.H2.bmp:.+44| +000001c0 32 30 31 32 33 34 35 36 37 38 40 01 4d 50 e0 27 |2012345678@.MP.'| +000001d0 5c 50 17 58 04 62 05 53 75 6e 6e 79 68 fa 01 68 |\P.X.b.Sunnyh..h| +000001e0 f4 01 68 0a 72 08 4d 75 72 6d 61 6e 73 6b 7a 08 |..h.r.Murmanskz.| +000001f0 fd f0 89 42 c8 4c 04 42 81 01 11 2d 44 54 fb 21 |...B.L.B...-DT.!| +00000200 09 40 89 01 00 00 00 e8 76 48 37 42 95 01 00 00 |.@......vH7B....| +00000210 48 44 9d 01 cd cc 4c c0 a0 01 80 d4 9f 93 01 ab |HD....L.........| +00000220 01 0d 00 00 80 41 12 05 70 6f 75 6e 64 ac 01 b3 |.....A..pound...| +00000230 01 0b a2 06 05 0b 08 f7 03 0c 0c b4 01 |.............| +0000023d + +MESSAGE #1 AT 0x00000002 +uuid: "a7522158-3d41-4b77-ad69-6c598ee55c49" +name: "Ivan" +surname: "Petrov" +gender: male +birthDate: 4015 +photo: "png" +phoneNumber: "+74951234567\000" +isOnline: true +visitTime: 1546703100 +age: 38 +zodiacSign: capricorn +songs: "Yesterday" +songs: "Flowers" +color: 255 +color: 0 +color: 0 +hometown: "Moscow" +location: 55.7532158 +location: 37.6225052 +pi: 3.14 +lotteryWin: 214.1 +someRatio: 0.1 +temperature: 5.8 +randomBigNumber: 17060000000 +MeasureUnits { + coef: 1 + coef: 0.01 + coef: 1000 + unit: "meter" + unit: "centimeter" + unit: "kilometer" +} +Nestiness { + A { + b { + C { + d: 500 + e: 501 + e: 502 + } + } + } +} +MESSAGE #2 AT 0x000000F5 +uuid: "c694ad8a-f714-4ea3-907d-fd54fb25d9b5" +name: "Natalia" +surname: "Sokolova" +gender: female +birthDate: 8102 +photo: "jpg" +isOnline: false +age: 26 +zodiacSign: pisces +color: 100 +color: 200 +color: 50 +hometown: "Plymouth" +location: 50.4037247 +location: -4.14212322 +pi: 3.14159 +someRatio: 0.007 +temperature: 5.4 +randomBigNumber: -20000000000000 +MESSAGE #3 AT 0x0000017A +uuid: "a7da1aa6-f425-4789-8947-b034786ed374" +name: "Vasily" +surname: "Sidorov" +gender: male +birthDate: 9339 +photo: "bmp" +phoneNumber: "+442012345678" +isOnline: true +visitTime: 1546117200 +age: 23 +zodiacSign: leo +songs: "Sunny" +color: 250 +color: 244 +color: 10 +hometown: "Murmansk" +location: 68.9706802 +location: 33.0749817 +pi: 3.14159265358979 +lotteryWin: 100000000000 +someRatio: 800 +temperature: -3.2 +randomBigNumber: 154400000 +MeasureUnits { + coef: 16 + unit: "pound" +} +Nestiness { + A { + b { + C { + d: 503 + } + } + } +} + +Binary representation is as expected + +Roundtrip: +a7522158-3d41-4b77-ad69-6c598ee55c49 Ivan Petrov male 1980-12-29 png +74951234567\0 1 2019-01-05 18:45:00 38 capricorn ['Yesterday','Flowers'] [255,0,0] Moscow [55.753216,37.622504] 3.14 214.10 0.1 5.8 17060000000 ['meter','centimeter','kilometer'] [1,0.01,1000] 500 [501,502] +c694ad8a-f714-4ea3-907d-fd54fb25d9b5 Natalia Sokolova female 1992-03-08 jpg \N 0 \N 26 pisces [] [100,200,50] Plymouth [50.403724,-4.142123] 3.14159 \N 0.007 5.4 -20000000000000 [] [] \N [] +a7da1aa6-f425-4789-8947-b034786ed374 Vasily Sidorov male 1995-07-28 bmp +442012345678 1 2018-12-30 00:00:00 23 leo ['Sunny'] [250,244,10] Murmansk [68.970680,33.074982] 3.14159265358979 100000000000.00 800 -3.2 154400000 ['pound'] [16] 503 [] diff --git a/tests/queries/0_stateless/00825_protobuf_format_persons.sh b/tests/queries/0_stateless/00825_protobuf_format_persons.sh new file mode 100755 index 00000000000..957ed738d99 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_persons.sh @@ -0,0 +1,118 @@ +#!/usr/bin/env bash + +# To generate reference file for this test use the following commands: +# ninja ProtobufDelimitedMessagesSerializer +# build/utils/test-data-generator/ProtobufDelimitedMessagesSerializer + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +SCHEMADIR=$CURDIR/format_schemas +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +set -eo pipefail + +# Run the client. +$CLICKHOUSE_CLIENT --multiquery < $BINARY_FILE_PATH +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_persons:Person" --input "$BINARY_FILE_PATH" +echo +echo "Roundtrip:" +$CLICKHOUSE_CLIENT --query "CREATE TABLE roundtrip_persons_00825 AS persons_00825" +$CLICKHOUSE_CLIENT --query "INSERT INTO roundtrip_persons_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_persons:Person'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM roundtrip_persons_00825 ORDER BY name" +rm "$BINARY_FILE_PATH" + +# Use schema 00825_protobuf_format_persons:AltPerson +echo +echo "Schema 00825_protobuf_format_persons:AltPerson" +BINARY_FILE_PATH=$(mktemp "$CURDIR/00825_protobuf_format_persons.XXXXXX.binary") +$CLICKHOUSE_CLIENT --query "SELECT * FROM persons_00825 ORDER BY name FORMAT Protobuf SETTINGS format_schema = '$SCHEMADIR/00825_protobuf_format_persons:AltPerson'" > $BINARY_FILE_PATH +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_persons:AltPerson" --input "$BINARY_FILE_PATH" +echo +echo "Roundtrip:" +$CLICKHOUSE_CLIENT --query "CREATE TABLE alt_persons_00825 AS persons_00825" +$CLICKHOUSE_CLIENT --query "INSERT INTO alt_persons_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_persons:AltPerson'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM alt_persons_00825 ORDER BY name" +rm "$BINARY_FILE_PATH" + +# Use schema 00825_protobuf_format_persons:StrPerson +echo +echo "Schema 00825_protobuf_format_persons:StrPerson" +BINARY_FILE_PATH=$(mktemp "$CURDIR/00825_protobuf_format_persons.XXXXXX.binary") +$CLICKHOUSE_CLIENT --query "SELECT * FROM persons_00825 ORDER BY name FORMAT Protobuf SETTINGS format_schema = '$SCHEMADIR/00825_protobuf_format_persons:StrPerson'" > $BINARY_FILE_PATH +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_persons:StrPerson" --input "$BINARY_FILE_PATH" +echo +echo "Roundtrip:" +$CLICKHOUSE_CLIENT --query "CREATE TABLE str_persons_00825 AS persons_00825" +$CLICKHOUSE_CLIENT --query "INSERT INTO str_persons_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_persons:StrPerson'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM str_persons_00825 ORDER BY name" +rm "$BINARY_FILE_PATH" + +# Use schema 00825_protobuf_format_syntax2:Syntax2Person +echo +echo "Schema 00825_protobuf_format_syntax2:Syntax2Person" +BINARY_FILE_PATH=$(mktemp "$CURDIR/00825_protobuf_format_persons.XXXXXX.binary") +$CLICKHOUSE_CLIENT --query "SELECT * FROM persons_00825 ORDER BY name FORMAT Protobuf SETTINGS format_schema = '$SCHEMADIR/00825_protobuf_format_persons_syntax2:Syntax2Person'" > $BINARY_FILE_PATH +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_persons_syntax2:Syntax2Person" --input "$BINARY_FILE_PATH" +echo +echo "Roundtrip:" +$CLICKHOUSE_CLIENT --query "CREATE TABLE syntax2_persons_00825 AS persons_00825" +$CLICKHOUSE_CLIENT --query "INSERT INTO syntax2_persons_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_persons_syntax2:Syntax2Person'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM syntax2_persons_00825 ORDER BY name" +rm "$BINARY_FILE_PATH" + +$CLICKHOUSE_CLIENT --multiquery < "$BINARY_FILE_PATH" + +# Check the output in the protobuf format +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_squares:NumberAndSquare" --input "$BINARY_FILE_PATH" + +# Check the input in the protobuf format (now the table contains the same data twice). +echo +$CLICKHOUSE_CLIENT --query "INSERT INTO squares_protobuf_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_squares:NumberAndSquare'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM squares_protobuf_00825" + +rm "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "DROP TABLE squares_protobuf_00825" diff --git a/tests/queries/0_stateless/00825_protobuf_format_table_default.reference b/tests/queries/0_stateless/00825_protobuf_format_table_default.reference new file mode 100644 index 00000000000..5472f3bfa14 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_table_default.reference @@ -0,0 +1,37 @@ +0 0 0 +2 4 8 +3 9 27 +5 25 125 +101 102 103 + +Binary representation: +00000000 00 04 08 04 10 10 04 08 06 10 36 05 08 0a 10 fa |..........6.....| +00000010 01 06 08 ca 01 10 ce 01 |........| +00000018 + +MESSAGE #1 AT 0x00000001 +MESSAGE #2 AT 0x00000002 +x: 2 +z: 8 +MESSAGE #3 AT 0x00000007 +x: 3 +z: 27 +MESSAGE #4 AT 0x0000000C +x: 5 +z: 125 +MESSAGE #5 AT 0x00000012 +x: 101 +z: 103 + +Binary representation is as expected + +0 0 0 +0 0 0 +2 4 8 +2 4 8 +3 9 27 +3 9 27 +5 25 125 +5 25 125 +101 102 103 +101 10201 103 diff --git a/tests/queries/0_stateless/00825_protobuf_format_table_default.sh b/tests/queries/0_stateless/00825_protobuf_format_table_default.sh new file mode 100755 index 00000000000..96664ca7f20 --- /dev/null +++ b/tests/queries/0_stateless/00825_protobuf_format_table_default.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +SCHEMADIR=$CURDIR/format_schemas +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +set -eo pipefail + +# Run the client. +$CLICKHOUSE_CLIENT --multiquery < "$BINARY_FILE_PATH" + +# Check the output in the protobuf format +echo +$CURDIR/helpers/protobuf_length_delimited_encoder.py --decode_and_check --format_schema "$SCHEMADIR/00825_protobuf_format_table_default:Message" --input "$BINARY_FILE_PATH" + +# Check the input in the protobuf format (now the table contains the same data twice). +echo +$CLICKHOUSE_CLIENT --query "INSERT INTO table_default_protobuf_00825 FORMAT Protobuf SETTINGS format_schema='$SCHEMADIR/00825_protobuf_format_table_default:Message'" < "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "SELECT * FROM table_default_protobuf_00825 ORDER BY x,y,z" + +rm "$BINARY_FILE_PATH" +$CLICKHOUSE_CLIENT --query "DROP TABLE table_default_protobuf_00825" diff --git a/tests/queries/0_stateless/00826_cross_to_inner_join.reference b/tests/queries/0_stateless/00826_cross_to_inner_join.reference index e7c8d6b1ea9..9b630d0d391 100644 --- a/tests/queries/0_stateless/00826_cross_to_inner_join.reference +++ b/tests/queries/0_stateless/00826_cross_to_inner_join.reference @@ -1,18 +1,18 @@ 0 0 -cross +--- cross --- 1 1 1 1 1 1 1 2 2 2 2 \N -cross nullable +--- cross nullable --- 1 1 1 1 2 2 1 2 -cross nullable vs not nullable +--- cross nullable vs not nullable --- 1 1 1 1 2 2 1 2 -cross self +--- cross self --- 1 1 1 1 2 2 2 2 -cross one table expr +--- cross one table expr --- 1 1 1 1 1 1 1 2 1 1 2 \N @@ -21,20 +21,34 @@ cross one table expr 2 2 1 2 2 2 2 \N 2 2 3 \N -cross multiple ands +--- cross multiple ands --- 1 1 1 1 -cross and inside and +--- cross and inside and --- 1 1 1 1 -cross split conjunction +--- cross split conjunction --- 1 1 1 1 -comma +--- and or --- +1 1 1 1 +--- arithmetic expr --- +2 2 1 2 +--- is null or --- +1 1 1 2 +2 2 2 \N +--- do not rewrite alias --- +1 +1 +2 +--- comma --- 1 1 1 1 1 1 1 2 2 2 2 \N -comma nullable +--- comma nullable --- 1 1 1 1 2 2 1 2 -cross +--- comma and or --- +1 1 1 1 +2 2 2 \N +--- cross --- SELECT a, b, @@ -43,7 +57,7 @@ SELECT FROM t1_00826 ALL INNER JOIN t2_00826 ON a = t2_00826.a WHERE a = t2_00826.a -cross nullable +--- cross nullable --- SELECT a, b, @@ -52,7 +66,7 @@ SELECT FROM t1_00826 ALL INNER JOIN t2_00826 ON a = t2_00826.a WHERE a = t2_00826.a -cross nullable vs not nullable +--- cross nullable vs not nullable --- SELECT a, b, @@ -61,7 +75,7 @@ SELECT FROM t1_00826 ALL INNER JOIN t2_00826 ON a = t2_00826.b WHERE a = t2_00826.b -cross self +--- cross self --- SELECT a, b, @@ -70,7 +84,7 @@ SELECT FROM t1_00826 AS x ALL INNER JOIN t1_00826 AS y ON (a = y.a) AND (b = y.b) WHERE (a = y.a) AND (b = y.b) -cross one table expr +--- cross one table expr --- SELECT a, b, @@ -79,7 +93,7 @@ SELECT FROM t1_00826 CROSS JOIN t2_00826 WHERE a = b -cross multiple ands +--- cross multiple ands --- SELECT a, b, @@ -88,16 +102,16 @@ SELECT FROM t1_00826 ALL INNER JOIN t2_00826 ON (a = t2_00826.a) AND (b = t2_00826.b) WHERE (a = t2_00826.a) AND (b = t2_00826.b) -cross and inside and +--- cross and inside and --- SELECT a, b, t2_00826.a, t2_00826.b FROM t1_00826 -ALL INNER JOIN t2_00826 ON (a = t2_00826.a) AND (a = t2_00826.a) AND (a = t2_00826.a) AND (b = t2_00826.b) +ALL INNER JOIN t2_00826 ON (((a = t2_00826.a) AND (a = t2_00826.a)) AND (a = t2_00826.a)) AND (b = t2_00826.b) WHERE (a = t2_00826.a) AND ((a = t2_00826.a) AND ((a = t2_00826.a) AND (b = t2_00826.b))) -cross split conjunction +--- cross split conjunction --- SELECT a, b, @@ -106,3 +120,62 @@ SELECT FROM t1_00826 ALL INNER JOIN t2_00826 ON (a = t2_00826.a) AND (b = t2_00826.b) WHERE (a = t2_00826.a) AND (b = t2_00826.b) AND (a >= 1) AND (t2_00826.b > 0) +--- and or --- +SELECT + a, + b, + t2_00826.a, + t2_00826.b +FROM t1_00826 +ALL INNER JOIN t2_00826 ON (a = t2_00826.a) AND (b = t2_00826.b) +WHERE (a = t2_00826.a) AND (b = t2_00826.b) AND ((a >= 1) OR (t2_00826.b = 1)) +--- arithmetic expr --- +SELECT + a, + b, + t2_00826.a, + t2_00826.b +FROM t1_00826 +ALL INNER JOIN t2_00826 ON (a + 1) = (t2_00826.a + t2_00826.b) +WHERE ((a + 1) = (t2_00826.a + t2_00826.b)) AND ((((a + b) + t2_00826.a) + t2_00826.b) > 5) +--- is null or --- +SELECT + a, + b, + t2_00826.a, + t2_00826.b +FROM t1_00826 +ALL INNER JOIN t2_00826 ON b = t2_00826.a +WHERE (b = t2_00826.a) AND (isNull(t2_00826.b) OR (t2_00826.b > t2_00826.a)) +--- do not rewrite alias --- +SELECT a AS b +FROM t1_00826 +CROSS JOIN t2_00826 +WHERE (b = t2_00826.a) AND (b > 0) +--- comma --- +SELECT + a, + b, + t2_00826.a, + t2_00826.b +FROM t1_00826 +ALL INNER JOIN t2_00826 ON a = t2_00826.a +WHERE a = t2_00826.a +--- comma nullable --- +SELECT + a, + b, + t2_00826.a, + t2_00826.b +FROM t1_00826 +ALL INNER JOIN t2_00826 ON b = t2_00826.b +WHERE b = t2_00826.b +--- comma and or --- +SELECT + a, + b, + t2_00826.a, + t2_00826.b +FROM t1_00826 +ALL INNER JOIN t2_00826 ON a = t2_00826.a +WHERE (a = t2_00826.a) AND (isNull(t2_00826.b) OR (t2_00826.b < 2)) diff --git a/tests/queries/0_stateless/00826_cross_to_inner_join.sql b/tests/queries/0_stateless/00826_cross_to_inner_join.sql index 67471864686..392ade02ab7 100644 --- a/tests/queries/0_stateless/00826_cross_to_inner_join.sql +++ b/tests/queries/0_stateless/00826_cross_to_inner_join.sql @@ -12,46 +12,79 @@ INSERT INTO t1_00826 values (1,1), (2,2); INSERT INTO t2_00826 values (1,1), (1,2); INSERT INTO t2_00826 (a) values (2), (3); -SELECT 'cross'; +SELECT '--- cross ---'; SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a; -SELECT 'cross nullable'; +SELECT '--- cross nullable ---'; SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.b = t2_00826.b; -SELECT 'cross nullable vs not nullable'; +SELECT '--- cross nullable vs not nullable ---'; SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.b; -SELECT 'cross self'; +SELECT '--- cross self ---'; SELECT * FROM t1_00826 x cross join t1_00826 y where x.a = y.a and x.b = y.b; -SELECT 'cross one table expr'; +SELECT '--- cross one table expr ---'; SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t1_00826.b order by (t1_00826.a, t2_00826.a, t2_00826.b); -SELECT 'cross multiple ands'; +SELECT '--- cross multiple ands ---'; SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b; -SELECT 'cross and inside and'; +SELECT '--- cross and inside and ---'; SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and (t1_00826.b = t2_00826.b and 1); -SELECT 'cross split conjunction'; +SELECT '--- cross split conjunction ---'; SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b and t1_00826.a >= 1 and t2_00826.b = 1; -SELECT 'comma'; +SELECT '--- and or ---'; +SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b and (t1_00826.a >= 1 OR t2_00826.b = 1); + +SELECT '--- arithmetic expr ---'; +SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a + 1 = t2_00826.a + t2_00826.b AND (t1_00826.a + t1_00826.b + t2_00826.a + t2_00826.b > 5); + +SELECT '--- is null or ---'; +SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.b = t2_00826.a AND (t2_00826.b IS NULL OR t2_00826.b > t2_00826.a); + +SELECT '--- do not rewrite alias ---'; +SELECT a as b FROM t1_00826 cross join t2_00826 where t1_00826.b = t2_00826.a AND b > 0; + +SELECT '--- comma ---'; SELECT * FROM t1_00826, t2_00826 where t1_00826.a = t2_00826.a; -SELECT 'comma nullable'; +SELECT '--- comma nullable ---'; SELECT * FROM t1_00826, t2_00826 where t1_00826.b = t2_00826.b; +SELECT '--- comma and or ---'; +SELECT * FROM t1_00826, t2_00826 where t1_00826.a = t2_00826.a AND (t2_00826.b IS NULL OR t2_00826.b < 2); -SELECT 'cross'; +SELECT '--- cross ---'; EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a; -SELECT 'cross nullable'; +SELECT '--- cross nullable ---'; EXPLAIN SYNTAX SELECT * FROM t1_00826, t2_00826 where t1_00826.a = t2_00826.a; -SELECT 'cross nullable vs not nullable'; +SELECT '--- cross nullable vs not nullable ---'; EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.b; -SELECT 'cross self'; +SELECT '--- cross self ---'; EXPLAIN SYNTAX SELECT * FROM t1_00826 x cross join t1_00826 y where x.a = y.a and x.b = y.b; -SELECT 'cross one table expr'; +SELECT '--- cross one table expr ---'; EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t1_00826.b; -SELECT 'cross multiple ands'; +SELECT '--- cross multiple ands ---'; EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b; -SELECT 'cross and inside and'; +SELECT '--- cross and inside and ---'; EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and (t1_00826.a = t2_00826.a and (t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b)); -SELECT 'cross split conjunction'; +SELECT '--- cross split conjunction ---'; EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b and t1_00826.a >= 1 and t2_00826.b > 0; +SELECT '--- and or ---'; +EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b and (t1_00826.a >= 1 OR t2_00826.b = 1); + +SELECT '--- arithmetic expr ---'; +EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a + 1 = t2_00826.a + t2_00826.b AND (t1_00826.a + t1_00826.b + t2_00826.a + t2_00826.b > 5); + +SELECT '--- is null or ---'; +EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.b = t2_00826.a AND (t2_00826.b IS NULL OR t2_00826.b > t2_00826.a); + +SELECT '--- do not rewrite alias ---'; +EXPLAIN SYNTAX SELECT a as b FROM t1_00826 cross join t2_00826 where t1_00826.b = t2_00826.a AND b > 0; + +SELECT '--- comma ---'; +EXPLAIN SYNTAX SELECT * FROM t1_00826, t2_00826 where t1_00826.a = t2_00826.a; +SELECT '--- comma nullable ---'; +EXPLAIN SYNTAX SELECT * FROM t1_00826, t2_00826 where t1_00826.b = t2_00826.b; +SELECT '--- comma and or ---'; +EXPLAIN SYNTAX SELECT * FROM t1_00826, t2_00826 where t1_00826.a = t2_00826.a AND (t2_00826.b IS NULL OR t2_00826.b < 2); + DROP TABLE t1_00826; DROP TABLE t2_00826; diff --git a/tests/queries/0_stateless/00849_multiple_comma_join_2.reference b/tests/queries/0_stateless/00849_multiple_comma_join_2.reference index fc39ef13935..4db65b0b795 100644 --- a/tests/queries/0_stateless/00849_multiple_comma_join_2.reference +++ b/tests/queries/0_stateless/00849_multiple_comma_join_2.reference @@ -127,7 +127,7 @@ FROM ) AS `--.s` CROSS JOIN t3 ) AS `--.s` -ALL INNER JOIN t4 ON (a = `--t1.a`) AND (a = `--t2.a`) AND (a = `--t3.a`) +ALL INNER JOIN t4 ON ((a = `--t1.a`) AND (a = `--t2.a`)) AND (a = `--t3.a`) WHERE (a = `--t1.a`) AND (a = `--t2.a`) AND (a = `--t3.a`) SELECT `--t1.a` AS `t1.a` FROM diff --git a/tests/queries/0_stateless/00878_join_unexpected_results.reference b/tests/queries/0_stateless/00878_join_unexpected_results.reference index a389cb47a96..65fcbc257ca 100644 --- a/tests/queries/0_stateless/00878_join_unexpected_results.reference +++ b/tests/queries/0_stateless/00878_join_unexpected_results.reference @@ -23,6 +23,8 @@ join_use_nulls = 1 - \N \N - +1 1 \N \N +2 2 \N \N - 1 1 1 1 2 2 \N \N @@ -49,6 +51,8 @@ join_use_nulls = 0 - - - +1 1 0 0 +2 2 0 0 - 1 1 1 1 2 2 0 0 diff --git a/tests/queries/0_stateless/00878_join_unexpected_results.sql b/tests/queries/0_stateless/00878_join_unexpected_results.sql index 0aef5208b26..6f6cd6e6479 100644 --- a/tests/queries/0_stateless/00878_join_unexpected_results.sql +++ b/tests/queries/0_stateless/00878_join_unexpected_results.sql @@ -30,11 +30,11 @@ select * from t left outer join s on (t.a=s.a and t.b=s.b) where s.a is null; select '-'; select s.* from t left outer join s on (t.a=s.a and t.b=s.b) where s.a is null; select '-'; -select t.*, s.* from t left join s on (s.a=t.a and t.b=s.b and t.a=toInt64(2)) order by t.a; -- {serverError 403 } +select t.*, s.* from t left join s on (s.a=t.a and t.b=s.b and t.a=toInt64(2)) order by t.a; select '-'; select t.*, s.* from t left join s on (s.a=t.a) order by t.a; select '-'; -select t.*, s.* from t left join s on (t.b=toInt64(2) and s.a=t.a) where s.b=2; -- {serverError 403 } +select t.*, s.* from t left join s on (t.b=toInt64(2) and s.a=t.a) where s.b=2; select 'join_use_nulls = 0'; set join_use_nulls = 0; @@ -58,11 +58,11 @@ select '-'; select '-'; -- select s.* from t left outer join s on (t.a=s.a and t.b=s.b) where s.a is null; -- TODO select '-'; -select t.*, s.* from t left join s on (s.a=t.a and t.b=s.b and t.a=toInt64(2)) order by t.a; -- {serverError 403 } +select t.*, s.* from t left join s on (s.a=t.a and t.b=s.b and t.a=toInt64(2)) order by t.a; select '-'; select t.*, s.* from t left join s on (s.a=t.a) order by t.a; select '-'; -select t.*, s.* from t left join s on (t.b=toInt64(2) and s.a=t.a) where s.b=2; -- {serverError 403 } +select t.*, s.* from t left join s on (t.b=toInt64(2) and s.a=t.a) where s.b=2; drop table t; drop table s; diff --git a/tests/queries/0_stateless/00950_dict_get.reference b/tests/queries/0_stateless/00950_dict_get.reference index 3010a2989c0..c1b502bf773 100644 --- a/tests/queries/0_stateless/00950_dict_get.reference +++ b/tests/queries/0_stateless/00950_dict_get.reference @@ -1,48 +1,48 @@ -dictGet flat_ints 1 1 1 1 1 1 1 1 1 -dictGetOrDefault flat_ints 1 1 1 1 1 1 1 1 1 -dictGetOrDefault flat_ints 0 42 42 42 42 42 42 42 42 -dictGet hashed_ints 1 1 1 1 1 1 1 1 1 -dictGetOrDefault hashed_ints 1 1 1 1 1 1 1 1 1 -dictGetOrDefault hashed_ints 0 42 42 42 42 42 42 42 42 -dictGet hashed_sparse_ints 1 1 1 1 1 1 1 1 1 -dictGetOrDefault hashed_sparse_ints 1 1 1 1 1 1 1 1 1 -dictGetOrDefault hashed_sparse_ints 0 42 42 42 42 42 42 42 42 -dictGet cache_ints 1 1 1 1 1 1 1 1 1 -dictGetOrDefault cache_ints 1 1 1 1 1 1 1 1 1 -dictGetOrDefault cache_ints 0 42 42 42 42 42 42 42 42 -dictGet complex_hashed_ints (1) 1 1 1 1 1 1 1 1 -dictGetOrDefault complex_hashed_ints (1) 1 1 1 1 1 1 1 1 -dictGetOrDefault complex_hashed_ints (0) 42 42 42 42 42 42 42 42 -dictGet complex_cache_ints (1) 1 1 1 1 1 1 1 1 -dictGetOrDefault complex_cache_ints (1) 1 1 1 1 1 1 1 1 -dictGetOrDefault complex_cache_ints (0) 42 42 42 42 42 42 42 42 -dictGet flat_strings 1 1 -dictGetOrDefault flat_strings 1 1 -dictGetOrDefault flat_strings 0 * -dictGet hashed_strings 1 1 -dictGetOrDefault hashed_strings 1 1 -dictGetOrDefault hashed_strings 0 * -dictGet cache_strings 1 1 -dictGetOrDefault cache_strings 1 1 -dictGetOrDefault cache_strings 0 * -dictGet complex_hashed_strings 1 1 -dictGetOrDefault complex_hashed_strings 1 1 -dictGetOrDefault complex_hashed_strings 0 * -dictGet complex_cache_strings 1 1 -dictGetOrDefault complex_cache_strings 1 1 -dictGetOrDefault complex_cache_strings 0 * -dictGet flat_decimals 1 1.0000 1.000000 1.0 -dictGetOrDefault flat_decimals 1 1.0000 1.000000 1.0 -dictGetOrDefault flat_decimals 0 42.0000 42.000000 42.0 -dictGet hashed_decimals 1 1.0000 1.000000 1.0 -dictGetOrDefault hashed_decimals 1 1.0000 1.000000 1.0 -dictGetOrDefault hashed_decimals 0 42.0000 42.000000 42.0 -dictGet cache_decimals 1 1.0000 1.000000 1.0 -dictGetOrDefault cache_decimals 1 1.0000 1.000000 1.0 -dictGetOrDefault cache_decimals 0 42.0000 42.000000 42.0 -dictGet complex_hashed_decimals (1) 1.0000 1.000000 1.0 -dictGetOrDefault complex_hashed_decimals (1) 1.0000 1.000000 1.0 -dictGetOrDefault complex_hashed_decimals (0) 42.0000 42.000000 42.0 -dictGet complex_cache_decimals (1) 1.0000 1.000000 1.0 -dictGetOrDefault complex_cache_decimals (1) 1.0000 1.000000 1.0 -dictGetOrDefault complex_cache_decimals (0) 42.0000 42.000000 42.0 +dictGet flat_ints 1 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault flat_ints 1 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault flat_ints 0 42 42 42 42 42 42 42 42 (42,42,42) +dictGet hashed_ints 1 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault hashed_ints 1 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault hashed_ints 0 42 42 42 42 42 42 42 (42,42,42) +dictGet hashed_sparse_ints 1 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault hashed_sparse_ints 1 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault hashed_sparse_ints 0 42 42 42 42 42 42 42 42 (42,42,42) +dictGet cache_ints 1 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault cache_ints 1 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault cache_ints 0 42 42 42 42 42 42 42 42 (42,42,42) +dictGet complex_hashed_ints (1) 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault complex_hashed_ints (1) 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault complex_hashed_ints (0) 42 42 42 42 42 42 42 42 (42,42,42) +dictGet complex_cache_ints (1) 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault complex_cache_ints (1) 1 1 1 1 1 1 1 1 (1,1,1) +dictGetOrDefault complex_cache_ints (0) 42 42 42 42 42 42 42 42 (42,42,42) +dictGet flat_strings 1 1 1 +dictGetOrDefault flat_strings 1 1 1 +dictGetOrDefault flat_strings 0 * * +dictGet hashed_strings 1 1 1 +dictGetOrDefault hashed_strings 1 1 1 +dictGetOrDefault hashed_strings 0 * * +dictGet cache_strings 1 1 1 +dictGetOrDefault cache_strings 1 1 1 +dictGetOrDefault cache_strings 0 * * +dictGet complex_hashed_strings 1 1 1 +dictGetOrDefault complex_hashed_strings 1 1 1 +dictGetOrDefault complex_hashed_strings 0 * * +dictGet complex_cache_strings 1 1 1 +dictGetOrDefault complex_cache_strings 1 1 1 +dictGetOrDefault complex_cache_strings 0 * * +dictGet flat_decimals 1 1.0000 1.000000 1.0 (1.0000,1.000000,1.0) +dictGetOrDefault flat_decimals 1 1.0000 1.000000 1.0 (1.0000,1.000000,1.0) +dictGetOrDefault flat_decimals 0 42.0000 42.000000 42.0 (42.0000,42.000000,42.0) +dictGet hashed_decimals 1 1.0000 1.000000 1.0 (1.0000,1.000000,1.0) +dictGetOrDefault hashed_decimals 1 1.0000 1.000000 1.0 (1.0000,1.000000,1.0) +dictGetOrDefault hashed_decimals 0 42.0000 42.000000 42.0 (42.0000,42.000000,42.0) +dictGet cache_decimals 1 1.0000 1.000000 1.0 (1.0000,1.000000,1.0) +dictGetOrDefault cache_decimals 1 1.0000 1.000000 1.0 (1.0000,1.000000,1.0) +dictGetOrDefault cache_decimals 0 42.0000 42.000000 42.0 (42.0000,42.000000,42.0) +dictGet complex_hashed_decimals (1) 1.0000 1.000000 1.0 (1.0000,1.000000,1.0) +dictGetOrDefault complex_hashed_decimals (1) 1.0000 1.000000 1.0 (1.0000,1.000000,1.0) +dictGetOrDefault complex_hashed_decimals (0) 42.0000 42.000000 42.0 (42.0000,42.000000,42.0) +dictGet complex_cache_decimals (1) 1.0000 1.000000 1.0 (1.0000,1.000000,1.0) +dictGetOrDefault complex_cache_decimals (1) 1.0000 1.000000 1.0 (1.0000,1.000000,1.0) +dictGetOrDefault complex_cache_decimals (0) 42.0000 42.000000 42.0 (42.0000,42.000000,42.0) diff --git a/tests/queries/0_stateless/00950_dict_get.sql b/tests/queries/0_stateless/00950_dict_get.sql index 93bb8f9b813..e49e05fbd27 100644 --- a/tests/queries/0_stateless/00950_dict_get.sql +++ b/tests/queries/0_stateless/00950_dict_get.sql @@ -20,7 +20,8 @@ select 'dictGet', 'flat_ints' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'u8', k), dictGet(dict_name, 'u16', k), dictGet(dict_name, 'u32', k), - dictGet(dict_name, 'u64', k); + dictGet(dict_name, 'u64', k), + dictGet(dict_name, ('i8', 'i16', 'i32'), k); select 'dictGetOrDefault', 'flat_ints' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -29,7 +30,8 @@ select 'dictGetOrDefault', 'flat_ints' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGetOrDefault', 'flat_ints' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -38,7 +40,8 @@ select 'dictGetOrDefault', 'flat_ints' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGet', 'hashed_ints' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'i8', k), @@ -48,7 +51,8 @@ select 'dictGet', 'hashed_ints' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'u8', k), dictGet(dict_name, 'u16', k), dictGet(dict_name, 'u32', k), - dictGet(dict_name, 'u64', k); + dictGet(dict_name, 'u64', k), + dictGet(dict_name, ('i8', 'i16', 'i32'), k); select 'dictGetOrDefault', 'hashed_ints' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -57,7 +61,8 @@ select 'dictGetOrDefault', 'hashed_ints' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGetOrDefault', 'hashed_ints' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -66,7 +71,7 @@ select 'dictGetOrDefault', 'hashed_ints' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGet', 'hashed_sparse_ints' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'i8', k), @@ -76,7 +81,8 @@ select 'dictGet', 'hashed_sparse_ints' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'u8', k), dictGet(dict_name, 'u16', k), dictGet(dict_name, 'u32', k), - dictGet(dict_name, 'u64', k); + dictGet(dict_name, 'u64', k), + dictGet(dict_name, ('i8', 'i16', 'i32'), k); select 'dictGetOrDefault', 'hashed_sparse_ints' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -85,7 +91,8 @@ select 'dictGetOrDefault', 'hashed_sparse_ints' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGetOrDefault', 'hashed_sparse_ints' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -94,7 +101,8 @@ select 'dictGetOrDefault', 'hashed_sparse_ints' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGet', 'cache_ints' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'i8', k), @@ -104,7 +112,8 @@ select 'dictGet', 'cache_ints' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'u8', k), dictGet(dict_name, 'u16', k), dictGet(dict_name, 'u32', k), - dictGet(dict_name, 'u64', k); + dictGet(dict_name, 'u64', k), + dictGet(dict_name, ('i8', 'i16', 'i32'), k); select 'dictGetOrDefault', 'cache_ints' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -113,7 +122,8 @@ select 'dictGetOrDefault', 'cache_ints' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGetOrDefault', 'cache_ints' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -122,7 +132,8 @@ select 'dictGetOrDefault', 'cache_ints' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGet', 'complex_hashed_ints' as dict_name, tuple(toUInt64(1)) as k, dictGet(dict_name, 'i8', k), @@ -132,7 +143,8 @@ select 'dictGet', 'complex_hashed_ints' as dict_name, tuple(toUInt64(1)) as k, dictGet(dict_name, 'u8', k), dictGet(dict_name, 'u16', k), dictGet(dict_name, 'u32', k), - dictGet(dict_name, 'u64', k); + dictGet(dict_name, 'u64', k), + dictGet(dict_name, ('i8', 'i16', 'i32'), k); select 'dictGetOrDefault', 'complex_hashed_ints' as dict_name, tuple(toUInt64(1)) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -141,7 +153,8 @@ select 'dictGetOrDefault', 'complex_hashed_ints' as dict_name, tuple(toUInt64(1) dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGetOrDefault', 'complex_hashed_ints' as dict_name, tuple(toUInt64(0)) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -150,7 +163,8 @@ select 'dictGetOrDefault', 'complex_hashed_ints' as dict_name, tuple(toUInt64(0) dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGet', 'complex_cache_ints' as dict_name, tuple(toUInt64(1)) as k, dictGet(dict_name, 'i8', k), @@ -160,7 +174,8 @@ select 'dictGet', 'complex_cache_ints' as dict_name, tuple(toUInt64(1)) as k, dictGet(dict_name, 'u8', k), dictGet(dict_name, 'u16', k), dictGet(dict_name, 'u32', k), - dictGet(dict_name, 'u64', k); + dictGet(dict_name, 'u64', k), + dictGet(dict_name, ('i8', 'i16', 'i32'), k);; select 'dictGetOrDefault', 'complex_cache_ints' as dict_name, tuple(toUInt64(1)) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -169,7 +184,8 @@ select 'dictGetOrDefault', 'complex_cache_ints' as dict_name, tuple(toUInt64(1)) dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); select 'dictGetOrDefault', 'complex_cache_ints' as dict_name, tuple(toUInt64(0)) as k, dictGetOrDefault(dict_name, 'i8', k, toInt8(42)), dictGetOrDefault(dict_name, 'i16', k, toInt16(42)), @@ -178,96 +194,112 @@ select 'dictGetOrDefault', 'complex_cache_ints' as dict_name, tuple(toUInt64(0)) dictGetOrDefault(dict_name, 'u8', k, toUInt8(42)), dictGetOrDefault(dict_name, 'u16', k, toUInt16(42)), dictGetOrDefault(dict_name, 'u32', k, toUInt32(42)), - dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)); + dictGetOrDefault(dict_name, 'u64', k, toUInt64(42)), + dictGetOrDefault(dict_name, ('i8', 'i16', 'i32'), k, (toInt8(42), toInt16(42), toInt32(42))); -- -select 'dictGet', 'flat_strings' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'str', k); -select 'dictGetOrDefault', 'flat_strings' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'str', k, '*'); -select 'dictGetOrDefault', 'flat_strings' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'str', k, '*'); +select 'dictGet', 'flat_strings' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'str', k), dictGet(dict_name, ('str'), k); +select 'dictGetOrDefault', 'flat_strings' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'str', k, '*'), dictGetOrDefault(dict_name, ('str'), k, ('*')); +select 'dictGetOrDefault', 'flat_strings' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'str', k, '*'), dictGetOrDefault(dict_name, ('str'), k, ('*')); -select 'dictGet', 'hashed_strings' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'str', k); -select 'dictGetOrDefault', 'hashed_strings' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'str', k, '*'); -select 'dictGetOrDefault', 'hashed_strings' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'str', k, '*'); +select 'dictGet', 'hashed_strings' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'str', k), dictGet(dict_name, ('str'), k); +select 'dictGetOrDefault', 'hashed_strings' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'str', k, '*'), dictGetOrDefault(dict_name, ('str'), k, ('*')); +select 'dictGetOrDefault', 'hashed_strings' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'str', k, '*'), dictGetOrDefault(dict_name, ('str'), k, ('*')); -select 'dictGet', 'cache_strings' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'str', k); -select 'dictGetOrDefault', 'cache_strings' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'str', k, '*'); -select 'dictGetOrDefault', 'cache_strings' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'str', k, '*'); +select 'dictGet', 'cache_strings' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'str', k), dictGet(dict_name, ('str'), k); +select 'dictGetOrDefault', 'cache_strings' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'str', k, '*'), dictGetOrDefault(dict_name, ('str'), k, ('*')); +select 'dictGetOrDefault', 'cache_strings' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'str', k, '*'), dictGetOrDefault(dict_name, ('str'), k, ('*')); -select 'dictGet', 'complex_hashed_strings' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'str', tuple(k)); -select 'dictGetOrDefault', 'complex_hashed_strings' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'str', tuple(k), '*'); -select 'dictGetOrDefault', 'complex_hashed_strings' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'str', tuple(k), '*'); +select 'dictGet', 'complex_hashed_strings' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'str', tuple(k)), dictGet(dict_name, ('str'), tuple(k)); +select 'dictGetOrDefault', 'complex_hashed_strings' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'str', tuple(k), '*'), dictGetOrDefault(dict_name, ('str'), tuple(k), ('*')); +select 'dictGetOrDefault', 'complex_hashed_strings' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'str', tuple(k), '*'), dictGetOrDefault(dict_name, ('str'), tuple(k), ('*')); -select 'dictGet', 'complex_cache_strings' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'str', tuple(k)); -select 'dictGetOrDefault', 'complex_cache_strings' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'str', tuple(k), '*'); -select 'dictGetOrDefault', 'complex_cache_strings' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'str', tuple(k), '*'); +select 'dictGet', 'complex_cache_strings' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'str', tuple(k)), dictGet(dict_name, ('str'), tuple(k)); +select 'dictGetOrDefault', 'complex_cache_strings' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'str', tuple(k), '*'), dictGetOrDefault(dict_name, ('str'), tuple(k), ('*')); +select 'dictGetOrDefault', 'complex_cache_strings' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'str', tuple(k), '*'), dictGetOrDefault(dict_name, ('str'), tuple(k), ('*')); -- select 'dictGet', 'flat_decimals' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'd32', k), dictGet(dict_name, 'd64', k), - dictGet(dict_name, 'd128', k); + dictGet(dict_name, 'd128', k), + dictGet(dict_name, ('d32', 'd64', 'd128'), k); select 'dictGetOrDefault', 'flat_decimals' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'd32', k, toDecimal32(42, 4)), dictGetOrDefault(dict_name, 'd64', k, toDecimal64(42, 6)), - dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)); + dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)), + dictGetOrDefault(dict_name, ('d32', 'd64', 'd128'), k, (toDecimal32(42, 4), toDecimal64(42, 6), toDecimal128(42, 1))); select 'dictGetOrDefault', 'flat_decimals' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'd32', k, toDecimal32(42, 4)), dictGetOrDefault(dict_name, 'd64', k, toDecimal64(42, 6)), - dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)); + dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)), + dictGetOrDefault(dict_name, ('d32', 'd64', 'd128'), k, (toDecimal32(42, 4), toDecimal64(42, 6), toDecimal128(42, 1))); select 'dictGet', 'hashed_decimals' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'd32', k), dictGet(dict_name, 'd64', k), - dictGet(dict_name, 'd128', k); + dictGet(dict_name, 'd128', k), + dictGet(dict_name, ('d32', 'd64', 'd128'), k); select 'dictGetOrDefault', 'hashed_decimals' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'd32', k, toDecimal32(42, 4)), dictGetOrDefault(dict_name, 'd64', k, toDecimal64(42, 6)), - dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)); + dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)), + dictGetOrDefault(dict_name, ('d32', 'd64', 'd128'), k, (toDecimal32(42, 4), toDecimal64(42, 6), toDecimal128(42, 1))); select 'dictGetOrDefault', 'hashed_decimals' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'd32', k, toDecimal32(42, 4)), dictGetOrDefault(dict_name, 'd64', k, toDecimal64(42, 6)), - dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)); + dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)), + dictGetOrDefault(dict_name, ('d32', 'd64', 'd128'), k, (toDecimal32(42, 4), toDecimal64(42, 6), toDecimal128(42, 1))); select 'dictGet', 'cache_decimals' as dict_name, toUInt64(1) as k, dictGet(dict_name, 'd32', k), dictGet(dict_name, 'd64', k), - dictGet(dict_name, 'd128', k); + dictGet(dict_name, 'd128', k), + dictGet(dict_name, ('d32', 'd64', 'd128'), k); select 'dictGetOrDefault', 'cache_decimals' as dict_name, toUInt64(1) as k, dictGetOrDefault(dict_name, 'd32', k, toDecimal32(42, 4)), dictGetOrDefault(dict_name, 'd64', k, toDecimal64(42, 6)), - dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)); + dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)), + dictGetOrDefault(dict_name, ('d32', 'd64', 'd128'), k, (toDecimal32(42, 4), toDecimal64(42, 6), toDecimal128(42, 1))); select 'dictGetOrDefault', 'cache_decimals' as dict_name, toUInt64(0) as k, dictGetOrDefault(dict_name, 'd32', k, toDecimal32(42, 4)), dictGetOrDefault(dict_name, 'd64', k, toDecimal64(42, 6)), - dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)); + dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)), + dictGetOrDefault(dict_name, ('d32', 'd64', 'd128'), k, (toDecimal32(42, 4), toDecimal64(42, 6), toDecimal128(42, 1))); select 'dictGet', 'complex_hashed_decimals' as dict_name, tuple(toUInt64(1)) as k, dictGet(dict_name, 'd32', k), dictGet(dict_name, 'd64', k), - dictGet(dict_name, 'd128', k); + dictGet(dict_name, 'd128', k), + dictGet(dict_name, ('d32', 'd64', 'd128'), k); select 'dictGetOrDefault', 'complex_hashed_decimals' as dict_name, tuple(toUInt64(1)) as k, dictGetOrDefault(dict_name, 'd32', k, toDecimal32(42, 4)), dictGetOrDefault(dict_name, 'd64', k, toDecimal64(42, 6)), - dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)); + dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)), + dictGetOrDefault(dict_name, ('d32', 'd64', 'd128'), k, (toDecimal32(42, 4), toDecimal64(42, 6), toDecimal128(42, 1))); select 'dictGetOrDefault', 'complex_hashed_decimals' as dict_name, tuple(toUInt64(0)) as k, dictGetOrDefault(dict_name, 'd32', k, toDecimal32(42, 4)), dictGetOrDefault(dict_name, 'd64', k, toDecimal64(42, 6)), - dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)); + dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)), + dictGetOrDefault(dict_name, ('d32', 'd64', 'd128'), k, (toDecimal32(42, 4), toDecimal64(42, 6), toDecimal128(42, 1))); select 'dictGet', 'complex_cache_decimals' as dict_name, tuple(toUInt64(1)) as k, dictGet(dict_name, 'd32', k), dictGet(dict_name, 'd64', k), - dictGet(dict_name, 'd128', k); + dictGet(dict_name, 'd128', k), + dictGet(dict_name, ('d32', 'd64', 'd128'), k); select 'dictGetOrDefault', 'complex_cache_decimals' as dict_name, tuple(toUInt64(1)) as k, dictGetOrDefault(dict_name, 'd32', k, toDecimal32(42, 4)), dictGetOrDefault(dict_name, 'd64', k, toDecimal64(42, 6)), - dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)); + dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)), + dictGetOrDefault(dict_name, ('d32', 'd64', 'd128'), k, (toDecimal32(42, 4), toDecimal64(42, 6), toDecimal128(42, 1))); select 'dictGetOrDefault', 'complex_cache_decimals' as dict_name, tuple(toUInt64(0)) as k, dictGetOrDefault(dict_name, 'd32', k, toDecimal32(42, 4)), dictGetOrDefault(dict_name, 'd64', k, toDecimal64(42, 6)), - dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)); + dictGetOrDefault(dict_name, 'd128', k, toDecimal128(42, 1)), + dictGetOrDefault(dict_name, ('d32', 'd64', 'd128'), k, (toDecimal32(42, 4), toDecimal64(42, 6), toDecimal128(42, 1))); -- -- Keep the tables, so that the dictionaries can be reloaded correctly and diff --git a/tests/queries/0_stateless/00966_live_view_watch_events_http.py b/tests/queries/0_stateless/00966_live_view_watch_events_http.py index 3d407ec5602..1c00a5d1236 100755 --- a/tests/queries/0_stateless/00966_live_view_watch_events_http.py +++ b/tests/queries/0_stateless/00966_live_view_watch_events_http.py @@ -28,13 +28,14 @@ with client(name='client1>', log=log) as client1: client1.expect(prompt) - with http_client({'method':'GET', 'url': '/?allow_experimental_live_view=1&query=WATCH%20test.lv%20EVENTS'}, name='client2>', log=log) as client2: - client2.expect('.*1\n') - client1.send('INSERT INTO test.mt VALUES (1),(2),(3)') + try: + with http_client({'method':'GET', 'url': '/?allow_experimental_live_view=1&query=WATCH%20test.lv%20EVENTS'}, name='client2>', log=log) as client2: + client2.expect('.*1\n') + client1.send('INSERT INTO test.mt VALUES (1),(2),(3)') + client1.expect(prompt) + client2.expect('.*2\n') + finally: + client1.send('DROP TABLE test.lv') + client1.expect(prompt) + client1.send('DROP TABLE test.mt') client1.expect(prompt) - client2.expect('.*2\n') - - client1.send('DROP TABLE test.lv') - client1.expect(prompt) - client1.send('DROP TABLE test.mt') - client1.expect(prompt) diff --git a/tests/queries/0_stateless/00967_live_view_watch_http.py b/tests/queries/0_stateless/00967_live_view_watch_http.py index d26bb5402e7..c41b9f0c861 100755 --- a/tests/queries/0_stateless/00967_live_view_watch_http.py +++ b/tests/queries/0_stateless/00967_live_view_watch_http.py @@ -27,14 +27,14 @@ with client(name='client1>', log=log) as client1: client1.send('CREATE LIVE VIEW test.lv AS SELECT sum(a) FROM test.mt') client1.expect(prompt) - - with http_client({'method':'GET', 'url':'/?allow_experimental_live_view=1&query=WATCH%20test.lv'}, name='client2>', log=log) as client2: - client2.expect('.*0\t1\n') - client1.send('INSERT INTO test.mt VALUES (1),(2),(3)') + try: + with http_client({'method':'GET', 'url':'/?allow_experimental_live_view=1&query=WATCH%20test.lv'}, name='client2>', log=log) as client2: + client2.expect('.*0\t1\n') + client1.send('INSERT INTO test.mt VALUES (1),(2),(3)') + client1.expect(prompt) + client2.expect('.*6\t2\n') + finally: + client1.send('DROP TABLE test.lv') + client1.expect(prompt) + client1.send('DROP TABLE test.mt') client1.expect(prompt) - client2.expect('.*6\t2\n') - - client1.send('DROP TABLE test.lv') - client1.expect(prompt) - client1.send('DROP TABLE test.mt') - client1.expect(prompt) diff --git a/tests/queries/0_stateless/00974_distributed_join_on.sql b/tests/queries/0_stateless/00974_distributed_join_on.sql index 10f8763fa33..355d9f81e82 100644 --- a/tests/queries/0_stateless/00974_distributed_join_on.sql +++ b/tests/queries/0_stateless/00974_distributed_join_on.sql @@ -1,7 +1,3 @@ --- Avoid "Connection failed at try №1" messages. -SET send_logs_level = 'none'; -SET connect_timeout_with_failover_ms = 5000; - DROP TABLE IF EXISTS source_table1; DROP TABLE IF EXISTS source_table2; DROP TABLE IF EXISTS distributed_table1; diff --git a/tests/queries/0_stateless/01018_ddl_dictionaries_concurrent_requrests.sh b/tests/queries/0_stateless/01018_ddl_dictionaries_concurrent_requrests.sh index bc13e44934a..025fe51e2a9 100755 --- a/tests/queries/0_stateless/01018_ddl_dictionaries_concurrent_requrests.sh +++ b/tests/queries/0_stateless/01018_ddl_dictionaries_concurrent_requrests.sh @@ -113,8 +113,8 @@ timeout $TIMEOUT bash -c thread7 2> /dev/null & wait $CLICKHOUSE_CLIENT -q "SELECT 'Still alive'" -$CLICKHOUSE_CLIENT -q "ATTACH DICTIONARY database_for_dict.dict1" -$CLICKHOUSE_CLIENT -q "ATTACH DICTIONARY database_for_dict.dict2" +$CLICKHOUSE_CLIENT -q "ATTACH DICTIONARY IF NOT EXISTS database_for_dict.dict1" +$CLICKHOUSE_CLIENT -q "ATTACH DICTIONARY IF NOT EXISTS database_for_dict.dict2" $CLICKHOUSE_CLIENT -n -q " DROP TABLE table_for_dict1; diff --git a/tests/queries/0_stateless/01018_ip_dictionary.reference b/tests/queries/0_stateless/01018_ip_dictionary_long.reference similarity index 100% rename from tests/queries/0_stateless/01018_ip_dictionary.reference rename to tests/queries/0_stateless/01018_ip_dictionary_long.reference diff --git a/tests/queries/0_stateless/01018_ip_dictionary.sql b/tests/queries/0_stateless/01018_ip_dictionary_long.sql similarity index 99% rename from tests/queries/0_stateless/01018_ip_dictionary.sql rename to tests/queries/0_stateless/01018_ip_dictionary_long.sql index 5df1afcd559..2abd51cc9fe 100644 --- a/tests/queries/0_stateless/01018_ip_dictionary.sql +++ b/tests/queries/0_stateless/01018_ip_dictionary_long.sql @@ -41,6 +41,9 @@ SOURCE(CLICKHOUSE(host 'localhost' port 9000 user 'default' db 'database_for_dic LAYOUT(IP_TRIE()) LIFETIME(MIN 10 MAX 100); +-- fuzzer +SELECT '127.0.0.0/24' = dictGetString('database_for_dict.dict_ipv4_trie', 'prefixprefixprefixprefix', tuple(IPv4StringToNum('127.0.0.0127.0.0.0'))); -- { serverError 36 } + SELECT 0 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'asn', tuple(IPv4StringToNum('0.0.0.0'))); SELECT 1 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'asn', tuple(IPv4StringToNum('128.0.0.0'))); SELECT 2 == dictGetUInt32('database_for_dict.dict_ipv4_trie', 'asn', tuple(IPv4StringToNum('192.0.0.0'))); diff --git a/tests/queries/0_stateless/01029_early_constant_folding.reference b/tests/queries/0_stateless/01029_early_constant_folding.reference index 7e2f6c7ce76..8a2d7e6c61a 100644 --- a/tests/queries/0_stateless/01029_early_constant_folding.reference +++ b/tests/queries/0_stateless/01029_early_constant_folding.reference @@ -2,7 +2,7 @@ SELECT 1 WHERE 0 SELECT 1 SELECT 1 -WHERE 0 +WHERE (1 IN (0, 2)) AND (2 = (identity(CAST(2, \'UInt8\')) AS subquery)) SELECT 1 WHERE 1 IN ( ( diff --git a/tests/queries/0_stateless/01029_early_constant_folding.sql b/tests/queries/0_stateless/01029_early_constant_folding.sql index 428c3625295..6336b62e080 100644 --- a/tests/queries/0_stateless/01029_early_constant_folding.sql +++ b/tests/queries/0_stateless/01029_early_constant_folding.sql @@ -4,7 +4,7 @@ EXPLAIN SYNTAX SELECT 1 WHERE 1 = 0; EXPLAIN SYNTAX SELECT 1 WHERE 1 IN (0, 1, 2); -EXPLAIN SYNTAX SELECT 1 WHERE 1 IN (0, 2) AND 2 = (SELECT 2); +EXPLAIN SYNTAX SELECT 1 WHERE 1 IN (0, 2) AND 2 = ((SELECT 2) AS subquery); -- no constant folding diff --git a/tests/queries/0_stateless/01035_lc_empty_part_bug.sh b/tests/queries/0_stateless/01035_lc_empty_part_bug.sh index b65cf87d1ca..185c4ef4a4e 100755 --- a/tests/queries/0_stateless/01035_lc_empty_part_bug.sh +++ b/tests/queries/0_stateless/01035_lc_empty_part_bug.sh @@ -8,7 +8,7 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ${CLICKHOUSE_CLIENT} --multiquery --query=" DROP TABLE IF EXISTS lc_empty_part_bug; - create table lc_empty_part_bug (id UInt64, s String) Engine=MergeTree ORDER BY id; + create table lc_empty_part_bug (id UInt64, s String) Engine=MergeTree ORDER BY id SETTINGS number_of_free_entries_in_pool_to_execute_mutation=0; insert into lc_empty_part_bug select number as id, toString(rand()) from numbers(100); alter table lc_empty_part_bug delete where id < 100; " --mutations_sync=1 diff --git a/tests/queries/0_stateless/01053_ssd_dictionary.sql b/tests/queries/0_stateless/01053_ssd_dictionary.sql index cd4ce95802f..a23ae7e5e96 100644 --- a/tests/queries/0_stateless/01053_ssd_dictionary.sql +++ b/tests/queries/0_stateless/01053_ssd_dictionary.sql @@ -1,12 +1,12 @@ SET send_logs_level = 'none'; -DROP DATABASE IF EXISTS database_for_dict; +DROP DATABASE IF EXISTS 01053_db; -CREATE DATABASE database_for_dict Engine = Ordinary; +CREATE DATABASE 01053_db Engine = Ordinary; -DROP TABLE IF EXISTS database_for_dict.table_for_dict; +DROP TABLE IF EXISTS 01053_db.table_for_dict; -CREATE TABLE database_for_dict.table_for_dict +CREATE TABLE 01053_db.table_for_dict ( id UInt64, a UInt64, @@ -16,16 +16,16 @@ CREATE TABLE database_for_dict.table_for_dict ENGINE = MergeTree() ORDER BY id; -INSERT INTO database_for_dict.table_for_dict VALUES (1, 100, -100, 'clickhouse'), (2, 3, 4, 'database'), (5, 6, 7, 'columns'), (10, 9, 8, ''); -INSERT INTO database_for_dict.table_for_dict SELECT number, 0, -1, 'a' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 370; -INSERT INTO database_for_dict.table_for_dict SELECT number, 0, -1, 'b' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 370, 370; -INSERT INTO database_for_dict.table_for_dict SELECT number, 0, -1, 'c' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 700, 370; +INSERT INTO 01053_db.table_for_dict VALUES (1, 100, -100, 'clickhouse'), (2, 3, 4, 'database'), (5, 6, 7, 'columns'), (10, 9, 8, ''); +INSERT INTO 01053_db.table_for_dict SELECT number, 0, -1, 'a' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 370; +INSERT INTO 01053_db.table_for_dict SELECT number, 0, -1, 'b' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 370, 370; +INSERT INTO 01053_db.table_for_dict SELECT number, 0, -1, 'c' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 700, 370; -DROP DICTIONARY IF EXISTS database_for_dict.ssd_dict; +DROP DICTIONARY IF EXISTS 01053_db.ssd_dict; -- FIXME filesystem error: in create_directory: Permission denied [/var/lib/clickhouse] -- Probably we need rewrite it to integration test -CREATE DICTIONARY database_for_dict.ssd_dict +CREATE DICTIONARY 01053_db.ssd_dict ( id UInt64, a UInt64 DEFAULT 0, @@ -33,40 +33,40 @@ CREATE DICTIONARY database_for_dict.ssd_dict c String DEFAULT 'none' ) PRIMARY KEY id -SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_for_dict' PASSWORD '' DB 'database_for_dict')) +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_for_dict' PASSWORD '' DB '01053_db')) LIFETIME(MIN 1000 MAX 2000) LAYOUT(SSD_CACHE(FILE_SIZE 8192 PATH '/var/lib/clickhouse/clickhouse_dicts/0d')); SELECT 'TEST_SMALL'; -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', toUInt64(1)); -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', toUInt64(4)); -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', toUInt64(5)); -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', toUInt64(6)); -SELECT dictGetString('database_for_dict.ssd_dict', 'c', toUInt64(2)); -SELECT dictGetString('database_for_dict.ssd_dict', 'c', toUInt64(3)); +SELECT dictGetInt32('01053_db.ssd_dict', 'b', toUInt64(1)); +SELECT dictGetInt32('01053_db.ssd_dict', 'b', toUInt64(4)); +SELECT dictGetUInt64('01053_db.ssd_dict', 'a', toUInt64(5)); +SELECT dictGetUInt64('01053_db.ssd_dict', 'a', toUInt64(6)); +SELECT dictGetString('01053_db.ssd_dict', 'c', toUInt64(2)); +SELECT dictGetString('01053_db.ssd_dict', 'c', toUInt64(3)); -SELECT * FROM database_for_dict.ssd_dict ORDER BY id; -DROP DICTIONARY database_for_dict.ssd_dict; +SELECT * FROM 01053_db.ssd_dict ORDER BY id; +DROP DICTIONARY 01053_db.ssd_dict; -DROP TABLE IF EXISTS database_for_dict.keys_table; +DROP TABLE IF EXISTS 01053_db.keys_table; -CREATE TABLE database_for_dict.keys_table +CREATE TABLE 01053_db.keys_table ( id UInt64 ) ENGINE = StripeLog(); -INSERT INTO database_for_dict.keys_table VALUES (1); -INSERT INTO database_for_dict.keys_table SELECT 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 370; -INSERT INTO database_for_dict.keys_table VALUES (2); -INSERT INTO database_for_dict.keys_table SELECT 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 370, 370; -INSERT INTO database_for_dict.keys_table VALUES (5); -INSERT INTO database_for_dict.keys_table SELECT 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 700, 370; -INSERT INTO database_for_dict.keys_table VALUES (10); +INSERT INTO 01053_db.keys_table VALUES (1); +INSERT INTO 01053_db.keys_table SELECT 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 370; +INSERT INTO 01053_db.keys_table VALUES (2); +INSERT INTO 01053_db.keys_table SELECT 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 370, 370; +INSERT INTO 01053_db.keys_table VALUES (5); +INSERT INTO 01053_db.keys_table SELECT 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 700, 370; +INSERT INTO 01053_db.keys_table VALUES (10); -DROP DICTIONARY IF EXISTS database_for_dict.ssd_dict; +DROP DICTIONARY IF EXISTS 01053_db.ssd_dict; -CREATE DICTIONARY database_for_dict.ssd_dict +CREATE DICTIONARY 01053_db.ssd_dict ( id UInt64, a UInt64 DEFAULT 0, @@ -74,86 +74,86 @@ CREATE DICTIONARY database_for_dict.ssd_dict c String DEFAULT 'none' ) PRIMARY KEY id -SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_for_dict' PASSWORD '' DB 'database_for_dict')) +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_for_dict' PASSWORD '' DB '01053_db')) LIFETIME(MIN 1000 MAX 2000) LAYOUT(SSD_CACHE(FILE_SIZE 8192 PATH '/var/lib/clickhouse/clickhouse_dicts/1d' BLOCK_SIZE 512 WRITE_BUFFER_SIZE 4096 MAX_STORED_KEYS 1000000)); SELECT 'UPDATE DICTIONARY'; -- 118 -SELECT sum(dictGetUInt64('database_for_dict.ssd_dict', 'a', toUInt64(id))) FROM database_for_dict.keys_table; +SELECT sum(dictGetUInt64('01053_db.ssd_dict', 'a', toUInt64(id))) FROM 01053_db.keys_table; SELECT 'VALUE FROM DISK'; -- -100 -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', toUInt64(1)); +SELECT dictGetInt32('01053_db.ssd_dict', 'b', toUInt64(1)); -- 'clickhouse' -SELECT dictGetString('database_for_dict.ssd_dict', 'c', toUInt64(1)); +SELECT dictGetString('01053_db.ssd_dict', 'c', toUInt64(1)); SELECT 'VALUE FROM RAM BUFFER'; -- 8 -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', toUInt64(10)); +SELECT dictGetInt32('01053_db.ssd_dict', 'b', toUInt64(10)); -- '' -SELECT dictGetString('database_for_dict.ssd_dict', 'c', toUInt64(10)); +SELECT dictGetString('01053_db.ssd_dict', 'c', toUInt64(10)); SELECT 'VALUES FROM DISK AND RAM BUFFER'; -- 118 -SELECT sum(dictGetUInt64('database_for_dict.ssd_dict', 'a', toUInt64(id))) FROM database_for_dict.keys_table; +SELECT sum(dictGetUInt64('01053_db.ssd_dict', 'a', toUInt64(id))) FROM 01053_db.keys_table; SELECT 'HAS'; -- 1006 -SELECT count() FROM database_for_dict.keys_table WHERE dictHas('database_for_dict.ssd_dict', toUInt64(id)); +SELECT count() FROM 01053_db.keys_table WHERE dictHas('01053_db.ssd_dict', toUInt64(id)); SELECT 'VALUES NOT FROM TABLE'; -- 0 -1 none -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', toUInt64(1000000)), dictGetInt32('database_for_dict.ssd_dict', 'b', toUInt64(1000000)), dictGetString('database_for_dict.ssd_dict', 'c', toUInt64(1000000)); -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', toUInt64(1000000)), dictGetInt32('database_for_dict.ssd_dict', 'b', toUInt64(1000000)), dictGetString('database_for_dict.ssd_dict', 'c', toUInt64(1000000)); +SELECT dictGetUInt64('01053_db.ssd_dict', 'a', toUInt64(1000000)), dictGetInt32('01053_db.ssd_dict', 'b', toUInt64(1000000)), dictGetString('01053_db.ssd_dict', 'c', toUInt64(1000000)); +SELECT dictGetUInt64('01053_db.ssd_dict', 'a', toUInt64(1000000)), dictGetInt32('01053_db.ssd_dict', 'b', toUInt64(1000000)), dictGetString('01053_db.ssd_dict', 'c', toUInt64(1000000)); SELECT 'DUPLICATE KEYS'; -SELECT arrayJoin([1, 2, 3, 3, 2, 1]) AS id, dictGetInt32('database_for_dict.ssd_dict', 'b', toUInt64(id)); +SELECT arrayJoin([1, 2, 3, 3, 2, 1]) AS id, dictGetInt32('01053_db.ssd_dict', 'b', toUInt64(id)); --SELECT -DROP DICTIONARY IF EXISTS database_for_dict.ssd_dict; +DROP DICTIONARY IF EXISTS 01053_db.ssd_dict; -DROP TABLE IF EXISTS database_for_dict.keys_table; +DROP TABLE IF EXISTS 01053_db.keys_table; -CREATE TABLE database_for_dict.keys_table +CREATE TABLE 01053_db.keys_table ( id UInt64 ) ENGINE = MergeTree() ORDER BY id; -INSERT INTO database_for_dict.keys_table VALUES (1); -INSERT INTO database_for_dict.keys_table SELECT intHash64(number) FROM system.numbers LIMIT 370; -INSERT INTO database_for_dict.keys_table VALUES (2); -INSERT INTO database_for_dict.keys_table SELECT intHash64(number) FROM system.numbers LIMIT 370, 370; -INSERT INTO database_for_dict.keys_table VALUES (5); -INSERT INTO database_for_dict.keys_table SELECT intHash64(number) FROM system.numbers LIMIT 700, 370; -INSERT INTO database_for_dict.keys_table VALUES (10); +INSERT INTO 01053_db.keys_table VALUES (1); +INSERT INTO 01053_db.keys_table SELECT intHash64(number) FROM system.numbers LIMIT 370; +INSERT INTO 01053_db.keys_table VALUES (2); +INSERT INTO 01053_db.keys_table SELECT intHash64(number) FROM system.numbers LIMIT 370, 370; +INSERT INTO 01053_db.keys_table VALUES (5); +INSERT INTO 01053_db.keys_table SELECT intHash64(number) FROM system.numbers LIMIT 700, 370; +INSERT INTO 01053_db.keys_table VALUES (10); -OPTIMIZE TABLE database_for_dict.keys_table; +OPTIMIZE TABLE 01053_db.keys_table; -CREATE DICTIONARY database_for_dict.ssd_dict +CREATE DICTIONARY 01053_db.ssd_dict ( id UInt64, a UInt64 DEFAULT 0, b Int32 DEFAULT -1 ) PRIMARY KEY id -SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_for_dict' PASSWORD '' DB 'database_for_dict')) +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_for_dict' PASSWORD '' DB '01053_db')) LIFETIME(MIN 1000 MAX 2000) LAYOUT(SSD_CACHE(FILE_SIZE 8192 PATH '/var/lib/clickhouse/clickhouse_dicts/2d' BLOCK_SIZE 512 WRITE_BUFFER_SIZE 1024 MAX_STORED_KEYS 10)); SELECT 'UPDATE DICTIONARY (MT)'; -- 118 -SELECT sum(dictGetUInt64('database_for_dict.ssd_dict', 'a', toUInt64(id))) FROM database_for_dict.keys_table; +SELECT sum(dictGetUInt64('01053_db.ssd_dict', 'a', toUInt64(id))) FROM 01053_db.keys_table; SELECT 'VALUES FROM DISK AND RAM BUFFER (MT)'; -- 118 -SELECT sum(dictGetUInt64('database_for_dict.ssd_dict', 'a', toUInt64(id))) FROM database_for_dict.keys_table; +SELECT sum(dictGetUInt64('01053_db.ssd_dict', 'a', toUInt64(id))) FROM 01053_db.keys_table; -DROP DICTIONARY IF EXISTS database_for_dict.ssd_dict; +DROP DICTIONARY IF EXISTS 01053_db.ssd_dict; -DROP TABLE IF EXISTS database_for_dict.table_for_dict; +DROP TABLE IF EXISTS 01053_db.table_for_dict; -DROP DATABASE IF EXISTS database_for_dict; +DROP DATABASE IF EXISTS 01053_db; diff --git a/tests/queries/0_stateless/01057_http_compression_prefer_brotli.sh b/tests/queries/0_stateless/01057_http_compression_prefer_brotli.sh index e5f4d12ee18..22ab745d7c0 100755 --- a/tests/queries/0_stateless/01057_http_compression_prefer_brotli.sh +++ b/tests/queries/0_stateless/01057_http_compression_prefer_brotli.sh @@ -11,3 +11,4 @@ ${CLICKHOUSE_CURL} -sS -H 'Accept-Encoding: gzip,deflate,br' "${CLICKHOUSE_URL}& ${CLICKHOUSE_CURL} -sS -H 'Accept-Encoding: gzip,deflate' "${CLICKHOUSE_URL}&enable_http_compression=1" -d 'SELECT 1' | gzip -d ${CLICKHOUSE_CURL} -sS -H 'Accept-Encoding: gzip' "${CLICKHOUSE_URL}&enable_http_compression=1" -d 'SELECT number FROM numbers(1000000)' | gzip -d | tail -n3 ${CLICKHOUSE_CURL} -sS -H 'Accept-Encoding: br' "${CLICKHOUSE_URL}&enable_http_compression=1" -d 'SELECT number FROM numbers(1000000)' | brotli -d | tail -n3 + diff --git a/tests/queries/0_stateless/01176_mysql_client_interactive.expect b/tests/queries/0_stateless/01176_mysql_client_interactive.expect new file mode 100755 index 00000000000..d592bbe1ce2 --- /dev/null +++ b/tests/queries/0_stateless/01176_mysql_client_interactive.expect @@ -0,0 +1,26 @@ +#!/usr/bin/expect -f + +log_user 0 +set timeout 5 +match_max 100000 +# A default timeout action is to do nothing, change it to fail +expect_after { + timeout { + exit 1 + } +} + +set basedir [file dirname $argv0] +spawn bash -c "source $basedir/../shell_config.sh ; \$MYSQL_CLIENT_BINARY \$MYSQL_CLIENT_OPT" +expect "mysql> " + +send -- "USE system;\r" +expect "Database changed" + +send -- "SELECT * FROM one;\r" +expect "| dummy |" +expect "| 0 |" +expect "1 row in set" + +send -- "quit;\r" +expect eof diff --git a/tests/queries/0_stateless/01176_mysql_client_interactive.reference b/tests/queries/0_stateless/01176_mysql_client_interactive.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01177_group_array_moving.reference b/tests/queries/0_stateless/01177_group_array_moving.reference new file mode 100644 index 00000000000..d74c84bb94f --- /dev/null +++ b/tests/queries/0_stateless/01177_group_array_moving.reference @@ -0,0 +1,2 @@ +[-9223372036854775808,0,-9223372036854775808,0,-9223372036854775808,0] [18446744073709551615,18446744073709551614,18446744073709551613,18446744073709551612,18446744073709551611,18446744073709551610] [0,9223372036854775807,9223372036854775805,9223372036854775805,18446744073709551612,18446744073709551610] +[-35888607147294850,-71777214294589700,-107665821441884540,-143554428589179400,-179443035736474240,-215331642883769100] [17592202821648,35184405643296,52776608464944,70368811286592,87961014108240,105553216929888] [0,1,3,3,4,6] diff --git a/tests/queries/0_stateless/01177_group_array_moving.sql b/tests/queries/0_stateless/01177_group_array_moving.sql new file mode 100644 index 00000000000..5689cd95f75 --- /dev/null +++ b/tests/queries/0_stateless/01177_group_array_moving.sql @@ -0,0 +1,4 @@ +SELECT groupArrayMovingSum(257)(-9223372036854775808), groupArrayMovingSum(1048575)(18446744073709551615), groupArrayMovingSum(9223372036854775807)(number * 9223372036854775807) FROM remote('127.0.0.{1..2}', numbers(3)); +SELECT groupArrayMovingAvg(257)(-9223372036854775808), groupArrayMovingAvg(1048575)(18446744073709551615), groupArrayMovingAvg(9223372036854775807)(number * 9223372036854775807) FROM remote('127.0.0.{1..2}', numbers(3)); + +SELECT groupArrayMovingSum(257)(-9223372036854775808), groupArrayMovingSum(1)(10.000100135803223, [NULL, NULL], NULL), groupArrayMovingSum(NULL)(NULL) FROM numbers(1023) FORMAT Null; diff --git a/tests/queries/0_stateless/01178_int_field_to_decimal.reference b/tests/queries/0_stateless/01178_int_field_to_decimal.reference new file mode 100644 index 00000000000..6c256ba2032 --- /dev/null +++ b/tests/queries/0_stateless/01178_int_field_to_decimal.reference @@ -0,0 +1,2 @@ +9.00000000 +10.00000000 diff --git a/tests/queries/0_stateless/01178_int_field_to_decimal.sql b/tests/queries/0_stateless/01178_int_field_to_decimal.sql new file mode 100644 index 00000000000..bbd72e57d70 --- /dev/null +++ b/tests/queries/0_stateless/01178_int_field_to_decimal.sql @@ -0,0 +1,10 @@ +select d from values('d Decimal(8, 8)', 0, 1) where d not in (-1, 0); -- { serverError 69 } +select d from values('d Decimal(8, 8)', 0, 2) where d not in (1, 0); -- { serverError 69 } +select d from values('d Decimal(9, 8)', 0, 3) where d not in (-9223372036854775808, 0); -- { serverError 69 } +select d from values('d Decimal(9, 8)', 0, 4) where d not in (18446744073709551615, 0); -- { serverError 69 } +select d from values('d Decimal(18, 8)', 0, 5) where d not in (-9223372036854775808, 0); -- { serverError 69 } +select d from values('d Decimal(18, 8)', 0, 6) where d not in (18446744073709551615, 0); -- { serverError 69 } +select d from values('d Decimal(26, 8)', 0, 7) where d not in (-9223372036854775808, 0); -- { serverError 69 } +select d from values('d Decimal(27, 8)', 0, 8) where d not in (18446744073709551615, 0); -- { serverError 69 } +select d from values('d Decimal(27, 8)', 0, 9) where d not in (-9223372036854775808, 0); +select d from values('d Decimal(28, 8)', 0, 10) where d not in (18446744073709551615, 0); diff --git a/tests/queries/0_stateless/01238_http_memory_tracking.sh b/tests/queries/0_stateless/01238_http_memory_tracking.sh index 90a7611c7c7..8c900e4c208 100755 --- a/tests/queries/0_stateless/01238_http_memory_tracking.sh +++ b/tests/queries/0_stateless/01238_http_memory_tracking.sh @@ -18,3 +18,6 @@ yes 'SELECT 1' 2>/dev/null | { } | grep -x -c 1 wait + +# Reset max_memory_usage_for_user, so it will not affect other tests +${CLICKHOUSE_CLIENT} --max_memory_usage_for_user=0 -q "SELECT 1 FORMAT Null" diff --git a/tests/queries/0_stateless/01244_optimize_distributed_group_by_sharding_key.sql b/tests/queries/0_stateless/01244_optimize_distributed_group_by_sharding_key.sql index d152326091b..2f77155cc54 100644 --- a/tests/queries/0_stateless/01244_optimize_distributed_group_by_sharding_key.sql +++ b/tests/queries/0_stateless/01244_optimize_distributed_group_by_sharding_key.sql @@ -1,9 +1,5 @@ -- TODO: correct testing with real unique shards --- Avoid "Connection failed at try №1" messages. -SET send_logs_level = 'fatal'; -SET connect_timeout_with_failover_ms = 5000; - set optimize_distributed_group_by_sharding_key=1; drop table if exists dist_01247; diff --git a/tests/queries/0_stateless/01247_optimize_distributed_group_by_sharding_key_dist_on_dist.sql b/tests/queries/0_stateless/01247_optimize_distributed_group_by_sharding_key_dist_on_dist.sql index 1000e956583..73dc916e463 100644 --- a/tests/queries/0_stateless/01247_optimize_distributed_group_by_sharding_key_dist_on_dist.sql +++ b/tests/queries/0_stateless/01247_optimize_distributed_group_by_sharding_key_dist_on_dist.sql @@ -1,9 +1,5 @@ -- TODO: correct testing with real unique shards --- Avoid "Connection failed at try №1" messages. -SET send_logs_level = 'fatal'; -SET connect_timeout_with_failover_ms = 5000; - set optimize_distributed_group_by_sharding_key=1; drop table if exists dist_01247; diff --git a/tests/queries/0_stateless/01259_combinator_distinct_distributed.reference b/tests/queries/0_stateless/01259_combinator_distinct_distributed.reference index 096d5703292..72a41ac1d84 100644 --- a/tests/queries/0_stateless/01259_combinator_distinct_distributed.reference +++ b/tests/queries/0_stateless/01259_combinator_distinct_distributed.reference @@ -2,3 +2,7 @@ [0,1,2,3,4,5,6,7,8,9,10,11,12] 20 0.49237 +78 +[0,1,2,3,4,5,6,7,8,9,10,11,12] +20 +0.49237 diff --git a/tests/queries/0_stateless/01259_combinator_distinct_distributed.sql b/tests/queries/0_stateless/01259_combinator_distinct_distributed.sql index f851e64dbcb..f95d2d87b8e 100644 --- a/tests/queries/0_stateless/01259_combinator_distinct_distributed.sql +++ b/tests/queries/0_stateless/01259_combinator_distinct_distributed.sql @@ -1,3 +1,12 @@ +SET distributed_aggregation_memory_efficient = 1; + +SELECT sum(DISTINCT number % 13) FROM remote('127.0.0.{1,2}', numbers_mt(100000)); +SELECT arraySort(groupArray(DISTINCT number % 13)) FROM remote('127.0.0.{1,2}', numbers_mt(100000)); +SELECT finalizeAggregation(countState(DISTINCT toString(number % 20))) FROM remote('127.0.0.{1,2}', numbers_mt(100000)); +SELECT round(corrStable(DISTINCT x, y), 5) FROM (SELECT number % 10 AS x, number % 5 AS y FROM remote('127.0.0.{1,2}', numbers(1000))); + +SET distributed_aggregation_memory_efficient = 0; + SELECT sum(DISTINCT number % 13) FROM remote('127.0.0.{1,2}', numbers_mt(100000)); SELECT arraySort(groupArray(DISTINCT number % 13)) FROM remote('127.0.0.{1,2}', numbers_mt(100000)); SELECT finalizeAggregation(countState(DISTINCT toString(number % 20))) FROM remote('127.0.0.{1,2}', numbers_mt(100000)); diff --git a/tests/queries/0_stateless/01272_totals_and_filter_bug.reference b/tests/queries/0_stateless/01272_totals_and_filter_bug.reference index 0db840561fd..5b407738cb8 100644 --- a/tests/queries/0_stateless/01272_totals_and_filter_bug.reference +++ b/tests/queries/0_stateless/01272_totals_and_filter_bug.reference @@ -1,6 +1,6 @@ 1 1 -0 2 +0 1 - test1 10 0 diff --git a/tests/queries/0_stateless/01280_ssd_complex_key_dictionary.sql b/tests/queries/0_stateless/01280_ssd_complex_key_dictionary.sql index 70e1d2bed29..50b34c4b18f 100644 --- a/tests/queries/0_stateless/01280_ssd_complex_key_dictionary.sql +++ b/tests/queries/0_stateless/01280_ssd_complex_key_dictionary.sql @@ -1,12 +1,12 @@ SET send_logs_level = 'none'; -DROP DATABASE IF EXISTS database_for_dict; +DROP DATABASE IF EXISTS 01280_db; -CREATE DATABASE database_for_dict Engine = Ordinary; +CREATE DATABASE 01280_db Engine = Ordinary; -DROP TABLE IF EXISTS database_for_dict.table_for_dict; +DROP TABLE IF EXISTS 01280_db.table_for_dict; -CREATE TABLE database_for_dict.table_for_dict +CREATE TABLE 01280_db.table_for_dict ( k1 String, k2 Int32, @@ -17,16 +17,16 @@ CREATE TABLE database_for_dict.table_for_dict ENGINE = MergeTree() ORDER BY (k1, k2); -INSERT INTO database_for_dict.table_for_dict VALUES (toString(1), 3, 100, -100, 'clickhouse'), (toString(2), -1, 3, 4, 'database'), (toString(5), -3, 6, 7, 'columns'), (toString(10), -20, 9, 8, ''); -INSERT INTO database_for_dict.table_for_dict SELECT toString(number), number + 1, 0, -1, 'a' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 370; -INSERT INTO database_for_dict.table_for_dict SELECT toString(number), number + 10, 0, -1, 'b' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 370, 370; -INSERT INTO database_for_dict.table_for_dict SELECT toString(number), number + 100, 0, -1, 'c' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 700, 370; +INSERT INTO 01280_db.table_for_dict VALUES (toString(1), 3, 100, -100, 'clickhouse'), (toString(2), -1, 3, 4, 'database'), (toString(5), -3, 6, 7, 'columns'), (toString(10), -20, 9, 8, ''); +INSERT INTO 01280_db.table_for_dict SELECT toString(number), number + 1, 0, -1, 'a' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 370; +INSERT INTO 01280_db.table_for_dict SELECT toString(number), number + 10, 0, -1, 'b' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 370, 370; +INSERT INTO 01280_db.table_for_dict SELECT toString(number), number + 100, 0, -1, 'c' FROM system.numbers WHERE number NOT IN (1, 2, 5, 10) LIMIT 700, 370; -DROP DICTIONARY IF EXISTS database_for_dict.ssd_dict; +DROP DICTIONARY IF EXISTS 01280_db.ssd_dict; -- FIXME filesystem error: in create_directory: Permission denied [/var/lib/clickhouse] -- Probably we need rewrite it to integration test -CREATE DICTIONARY database_for_dict.ssd_dict +CREATE DICTIONARY 01280_db.ssd_dict ( k1 String, k2 Int32, @@ -35,60 +35,59 @@ CREATE DICTIONARY database_for_dict.ssd_dict c String DEFAULT 'none' ) PRIMARY KEY k1, k2 -SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_for_dict' PASSWORD '' DB 'database_for_dict')) +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_for_dict' PASSWORD '' DB '01280_db')) LIFETIME(MIN 1000 MAX 2000) LAYOUT(COMPLEX_KEY_SSD_CACHE(FILE_SIZE 8192 PATH '/var/lib/clickhouse/clickhouse_dicts/0d')); SELECT 'TEST_SMALL'; SELECT 'VALUE FROM RAM BUFFER'; --- NUMBER_OF_ARGUMENTS_DOESNT_MATCH -SELECT dictHas('database_for_dict.ssd_dict', 'a', tuple('1')); -- { serverError 42 } +SELECT dictHas('01280_db.ssd_dict', 'a', tuple('1')); -- { serverError 43 } -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', tuple('1', toInt32(3))); -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', tuple('1', toInt32(3))); -SELECT dictGetString('database_for_dict.ssd_dict', 'c', tuple('1', toInt32(3))); +SELECT dictGetUInt64('01280_db.ssd_dict', 'a', tuple('1', toInt32(3))); +SELECT dictGetInt32('01280_db.ssd_dict', 'b', tuple('1', toInt32(3))); +SELECT dictGetString('01280_db.ssd_dict', 'c', tuple('1', toInt32(3))); -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', tuple('1', toInt32(3))); -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', tuple('1', toInt32(3))); -SELECT dictGetString('database_for_dict.ssd_dict', 'c', tuple('1', toInt32(3))); +SELECT dictGetUInt64('01280_db.ssd_dict', 'a', tuple('1', toInt32(3))); +SELECT dictGetInt32('01280_db.ssd_dict', 'b', tuple('1', toInt32(3))); +SELECT dictGetString('01280_db.ssd_dict', 'c', tuple('1', toInt32(3))); -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', tuple('2', toInt32(-1))); -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', tuple('2', toInt32(-1))); -SELECT dictGetString('database_for_dict.ssd_dict', 'c', tuple('2', toInt32(-1))); +SELECT dictGetUInt64('01280_db.ssd_dict', 'a', tuple('2', toInt32(-1))); +SELECT dictGetInt32('01280_db.ssd_dict', 'b', tuple('2', toInt32(-1))); +SELECT dictGetString('01280_db.ssd_dict', 'c', tuple('2', toInt32(-1))); -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', tuple('5', toInt32(-3))); -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', tuple('5', toInt32(-3))); -SELECT dictGetString('database_for_dict.ssd_dict', 'c', tuple('5', toInt32(-3))); +SELECT dictGetUInt64('01280_db.ssd_dict', 'a', tuple('5', toInt32(-3))); +SELECT dictGetInt32('01280_db.ssd_dict', 'b', tuple('5', toInt32(-3))); +SELECT dictGetString('01280_db.ssd_dict', 'c', tuple('5', toInt32(-3))); -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', tuple('10', toInt32(-20))); -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', tuple('10', toInt32(-20))); -SELECT dictGetString('database_for_dict.ssd_dict', 'c', tuple('10', toInt32(-20))); +SELECT dictGetUInt64('01280_db.ssd_dict', 'a', tuple('10', toInt32(-20))); +SELECT dictGetInt32('01280_db.ssd_dict', 'b', tuple('10', toInt32(-20))); +SELECT dictGetString('01280_db.ssd_dict', 'c', tuple('10', toInt32(-20))); -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', tuple(toInt32(3))); --{serverError 53} +SELECT dictGetUInt64('01280_db.ssd_dict', 'a', tuple(toInt32(3))); --{serverError 53} -DROP DICTIONARY database_for_dict.ssd_dict; +DROP DICTIONARY 01280_db.ssd_dict; -DROP TABLE IF EXISTS database_for_dict.keys_table; +DROP TABLE IF EXISTS 01280_db.keys_table; -CREATE TABLE database_for_dict.keys_table +CREATE TABLE 01280_db.keys_table ( k1 String, k2 Int32 ) ENGINE = StripeLog(); -INSERT INTO database_for_dict.keys_table VALUES ('1', 3); -INSERT INTO database_for_dict.keys_table SELECT toString(intHash64(number + 1) % 1200), 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 370; -INSERT INTO database_for_dict.keys_table VALUES ('2', -1); -INSERT INTO database_for_dict.keys_table SELECT toString(intHash64(number + 1) % 1200), 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 370, 370; -INSERT INTO database_for_dict.keys_table VALUES ('5', -3); -INSERT INTO database_for_dict.keys_table SELECT toString(intHash64(number + 1) % 1200), 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 700, 370; -INSERT INTO database_for_dict.keys_table VALUES ('10', -20); +INSERT INTO 01280_db.keys_table VALUES ('1', 3); +INSERT INTO 01280_db.keys_table SELECT toString(intHash64(number + 1) % 1200), 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 370; +INSERT INTO 01280_db.keys_table VALUES ('2', -1); +INSERT INTO 01280_db.keys_table SELECT toString(intHash64(number + 1) % 1200), 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 370, 370; +INSERT INTO 01280_db.keys_table VALUES ('5', -3); +INSERT INTO 01280_db.keys_table SELECT toString(intHash64(number + 1) % 1200), 11 + intHash64(number) % 1200 FROM system.numbers LIMIT 700, 370; +INSERT INTO 01280_db.keys_table VALUES ('10', -20); -DROP DICTIONARY IF EXISTS database_for_dict.ssd_dict; +DROP DICTIONARY IF EXISTS 01280_db.ssd_dict; -CREATE DICTIONARY database_for_dict.ssd_dict +CREATE DICTIONARY 01280_db.ssd_dict ( k1 String, k2 Int32, @@ -97,43 +96,43 @@ CREATE DICTIONARY database_for_dict.ssd_dict c String DEFAULT 'none' ) PRIMARY KEY k1, k2 -SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_for_dict' PASSWORD '' DB 'database_for_dict')) +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_for_dict' PASSWORD '' DB '01280_db')) LIFETIME(MIN 1000 MAX 2000) LAYOUT(COMPLEX_KEY_SSD_CACHE(FILE_SIZE 8192 PATH '/var/lib/clickhouse/clickhouse_dicts/1d' BLOCK_SIZE 512 WRITE_BUFFER_SIZE 4096 MAX_STORED_KEYS 1000000)); SELECT 'UPDATE DICTIONARY'; -- 118 -SELECT sum(dictGetUInt64('database_for_dict.ssd_dict', 'a', (k1, k2))) FROM database_for_dict.keys_table; +SELECT sum(dictGetUInt64('01280_db.ssd_dict', 'a', (k1, k2))) FROM 01280_db.keys_table; SELECT 'VALUE FROM DISK'; -- -100 -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', ('1', toInt32(3))); +SELECT dictGetInt32('01280_db.ssd_dict', 'b', ('1', toInt32(3))); -- 'clickhouse' -SELECT dictGetString('database_for_dict.ssd_dict', 'c', ('1', toInt32(3))); +SELECT dictGetString('01280_db.ssd_dict', 'c', ('1', toInt32(3))); SELECT 'VALUE FROM RAM BUFFER'; -- 8 -SELECT dictGetInt32('database_for_dict.ssd_dict', 'b', ('10', toInt32(-20))); +SELECT dictGetInt32('01280_db.ssd_dict', 'b', ('10', toInt32(-20))); -- '' -SELECT dictGetString('database_for_dict.ssd_dict', 'c', ('10', toInt32(-20))); +SELECT dictGetString('01280_db.ssd_dict', 'c', ('10', toInt32(-20))); SELECT 'VALUES FROM DISK AND RAM BUFFER'; -- 118 -SELECT sum(dictGetUInt64('database_for_dict.ssd_dict', 'a', (k1, k2))) FROM database_for_dict.keys_table; +SELECT sum(dictGetUInt64('01280_db.ssd_dict', 'a', (k1, k2))) FROM 01280_db.keys_table; SELECT 'HAS'; -- 6 -SELECT count() FROM database_for_dict.keys_table WHERE dictHas('database_for_dict.ssd_dict', (k1, k2)); +SELECT count() FROM 01280_db.keys_table WHERE dictHas('01280_db.ssd_dict', (k1, k2)); SELECT 'VALUES NOT FROM TABLE'; -- 0 -1 none -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', ('unknown', toInt32(0))), dictGetInt32('database_for_dict.ssd_dict', 'b', ('unknown', toInt32(0))), dictGetString('database_for_dict.ssd_dict', 'c', ('unknown', toInt32(0))); -SELECT dictGetUInt64('database_for_dict.ssd_dict', 'a', ('unknown', toInt32(0))), dictGetInt32('database_for_dict.ssd_dict', 'b', ('unknown', toInt32(0))), dictGetString('database_for_dict.ssd_dict', 'c', ('unknown', toInt32(0))); +SELECT dictGetUInt64('01280_db.ssd_dict', 'a', ('unknown', toInt32(0))), dictGetInt32('01280_db.ssd_dict', 'b', ('unknown', toInt32(0))), dictGetString('01280_db.ssd_dict', 'c', ('unknown', toInt32(0))); +SELECT dictGetUInt64('01280_db.ssd_dict', 'a', ('unknown', toInt32(0))), dictGetInt32('01280_db.ssd_dict', 'b', ('unknown', toInt32(0))), dictGetString('01280_db.ssd_dict', 'c', ('unknown', toInt32(0))); SELECT 'DUPLICATE KEYS'; -SELECT arrayJoin([('1', toInt32(3)), ('2', toInt32(-1)), ('', toInt32(0)), ('', toInt32(0)), ('2', toInt32(-1)), ('1', toInt32(3))]) AS keys, dictGetInt32('database_for_dict.ssd_dict', 'b', keys); +SELECT arrayJoin([('1', toInt32(3)), ('2', toInt32(-1)), ('', toInt32(0)), ('', toInt32(0)), ('2', toInt32(-1)), ('1', toInt32(3))]) AS keys, dictGetInt32('01280_db.ssd_dict', 'b', keys); DROP DICTIONARY IF EXISTS database_for_dict.ssd_dict; diff --git a/tests/queries/0_stateless/01281_group_by_limit_memory_tracking.sh b/tests/queries/0_stateless/01281_group_by_limit_memory_tracking.sh index 9909d9b566d..4667c76cb60 100755 --- a/tests/queries/0_stateless/01281_group_by_limit_memory_tracking.sh +++ b/tests/queries/0_stateless/01281_group_by_limit_memory_tracking.sh @@ -42,3 +42,6 @@ execute_group_by # if memory accounting will be incorrect, the second query will be failed with MEMORY_LIMIT_EXCEEDED execute_group_by wait + +# Reset max_memory_usage_for_user, so it will not affect other tests +${CLICKHOUSE_CLIENT} --max_memory_usage_for_user=0 -q "SELECT 1 FORMAT Null" diff --git a/tests/queries/0_stateless/01291_aggregation_in_order.sql b/tests/queries/0_stateless/01291_aggregation_in_order.sql index 753075f2757..c4357811520 100644 --- a/tests/queries/0_stateless/01291_aggregation_in_order.sql +++ b/tests/queries/0_stateless/01291_aggregation_in_order.sql @@ -9,12 +9,12 @@ INSERT INTO pk_order(a, b, c, d) VALUES (2, 2, 107, 2), (2, 3, 108, 2), (2, 4, 1 -- Order after group by in order is determined -SELECT a, b FROM pk_order GROUP BY a, b; -SELECT a FROM pk_order GROUP BY a; +SELECT a, b FROM pk_order GROUP BY a, b ORDER BY a, b; +SELECT a FROM pk_order GROUP BY a ORDER BY a; -SELECT a, b, sum(c), avg(d) FROM pk_order GROUP BY a, b; -SELECT a, sum(c), avg(d) FROM pk_order GROUP BY a; -SELECT a, sum(c), avg(d) FROM pk_order GROUP BY -a; +SELECT a, b, sum(c), avg(d) FROM pk_order GROUP BY a, b ORDER BY a, b; +SELECT a, sum(c), avg(d) FROM pk_order GROUP BY a ORDER BY a; +SELECT a, sum(c), avg(d) FROM pk_order GROUP BY -a ORDER BY a; DROP TABLE IF EXISTS pk_order; @@ -26,8 +26,8 @@ INSERT INTO pk_order set max_block_size = 1; -SELECT d, max(b) FROM pk_order GROUP BY d, a LIMIT 5; -SELECT d, avg(a) FROM pk_order GROUP BY toString(d) LIMIT 5; -SELECT toStartOfHour(d) as d1, min(a), max(b) FROM pk_order GROUP BY d1 LIMIT 5; +SELECT d, max(b) FROM pk_order GROUP BY d, a ORDER BY d, a LIMIT 5; +SELECT d, avg(a) FROM pk_order GROUP BY toString(d) ORDER BY toString(d) LIMIT 5; +SELECT toStartOfHour(d) as d1, min(a), max(b) FROM pk_order GROUP BY d1 ORDER BY d1 LIMIT 5; DROP TABLE pk_order; diff --git a/tests/queries/0_stateless/01293_show_clusters.reference b/tests/queries/0_stateless/01293_show_clusters.reference index 590ca348458..ad790cc8b4f 100644 --- a/tests/queries/0_stateless/01293_show_clusters.reference +++ b/tests/queries/0_stateless/01293_show_clusters.reference @@ -1,2 +1,2 @@ test_shard_localhost -test_shard_localhost 1 1 1 localhost ::1 9000 1 default 0 0 +test_shard_localhost 1 1 1 localhost ::1 9000 1 default 0 0 0 diff --git a/tests/queries/0_stateless/01293_show_settings.reference b/tests/queries/0_stateless/01293_show_settings.reference index feebc9e473d..6fcbf194614 100644 --- a/tests/queries/0_stateless/01293_show_settings.reference +++ b/tests/queries/0_stateless/01293_show_settings.reference @@ -1,5 +1,5 @@ send_timeout Seconds 300 connect_timeout Seconds 10 -connect_timeout_with_failover_ms Milliseconds 50 -connect_timeout_with_failover_secure_ms Milliseconds 100 +connect_timeout_with_failover_ms Milliseconds 2000 +connect_timeout_with_failover_secure_ms Milliseconds 3000 max_memory_usage UInt64 10000000000 diff --git a/tests/queries/0_stateless/01293_system_distribution_queue.sql b/tests/queries/0_stateless/01293_system_distribution_queue.sql index 8f84bbac41f..dc63dece960 100644 --- a/tests/queries/0_stateless/01293_system_distribution_queue.sql +++ b/tests/queries/0_stateless/01293_system_distribution_queue.sql @@ -10,20 +10,15 @@ select * from system.distribution_queue; select 'INSERT'; system stop distributed sends dist_01293; insert into dist_01293 select * from numbers(10); --- metrics updated only after distributed_directory_monitor_sleep_time_ms -set distributed_directory_monitor_sleep_time_ms=10; --- 1 second should guarantee metrics update --- XXX: but this is kind of quirk, way more better will be account this metrics without any delays. -select sleep(1) format Null; -select is_blocked, error_count, data_files, data_compressed_bytes>100 from system.distribution_queue; +select is_blocked, error_count, data_files, data_compressed_bytes>100 from system.distribution_queue where database = currentDatabase(); system flush distributed dist_01293; select 'FLUSH'; -select is_blocked, error_count, data_files, data_compressed_bytes from system.distribution_queue; +select is_blocked, error_count, data_files, data_compressed_bytes from system.distribution_queue where database = currentDatabase(); select 'UNBLOCK'; system start distributed sends dist_01293; -select is_blocked, error_count, data_files, data_compressed_bytes from system.distribution_queue; +select is_blocked, error_count, data_files, data_compressed_bytes from system.distribution_queue where database = currentDatabase(); drop table null_01293; drop table dist_01293; diff --git a/tests/queries/0_stateless/01294_lazy_database_concurrent_recreate_reattach_and_show_tables.reference b/tests/queries/0_stateless/01294_lazy_database_concurrent_recreate_reattach_and_show_tables_long.reference similarity index 100% rename from tests/queries/0_stateless/01294_lazy_database_concurrent_recreate_reattach_and_show_tables.reference rename to tests/queries/0_stateless/01294_lazy_database_concurrent_recreate_reattach_and_show_tables_long.reference diff --git a/tests/queries/0_stateless/01294_lazy_database_concurrent_recreate_reattach_and_show_tables.sh b/tests/queries/0_stateless/01294_lazy_database_concurrent_recreate_reattach_and_show_tables_long.sh similarity index 94% rename from tests/queries/0_stateless/01294_lazy_database_concurrent_recreate_reattach_and_show_tables.sh rename to tests/queries/0_stateless/01294_lazy_database_concurrent_recreate_reattach_and_show_tables_long.sh index d8f72c7837d..f5a4a1adac0 100755 --- a/tests/queries/0_stateless/01294_lazy_database_concurrent_recreate_reattach_and_show_tables.sh +++ b/tests/queries/0_stateless/01294_lazy_database_concurrent_recreate_reattach_and_show_tables_long.sh @@ -70,8 +70,10 @@ function recreate_lazy_func4() function test_func() { while true; do - $CLICKHOUSE_CLIENT -q "SYSTEM STOP TTL MERGES"; + for table in log tlog slog tlog2; do + $CLICKHOUSE_CLIENT -q "SYSTEM STOP TTL MERGES $CURR_DATABASE.$table" >& /dev/null done + done } diff --git a/tests/queries/0_stateless/01300_polygon_convex_hull.reference b/tests/queries/0_stateless/01300_polygon_convex_hull.reference new file mode 100644 index 00000000000..47be3068b5c --- /dev/null +++ b/tests/queries/0_stateless/01300_polygon_convex_hull.reference @@ -0,0 +1 @@ +[[(0,0),(0,5),(5,5),(5,0),(0,0)]] diff --git a/tests/queries/0_stateless/01300_polygon_convex_hull.sql b/tests/queries/0_stateless/01300_polygon_convex_hull.sql new file mode 100644 index 00000000000..4a4aa66bbfb --- /dev/null +++ b/tests/queries/0_stateless/01300_polygon_convex_hull.sql @@ -0,0 +1 @@ +select polygonConvexHullCartesian([[[(0., 0.), (0., 5.), (5., 5.), (5., 0.), (2., 3.)]]]); diff --git a/tests/queries/0_stateless/01300_read_wkt.reference b/tests/queries/0_stateless/01300_read_wkt.reference new file mode 100644 index 00000000000..acee1c8f14b --- /dev/null +++ b/tests/queries/0_stateless/01300_read_wkt.reference @@ -0,0 +1,16 @@ +(0,0) +[[(1,0),(10,0),(10,10),(0,10),(1,0)]] +[[(0,0),(10,0),(10,10),(0,10),(0,0)],[(4,4),(5,4),(5,5),(4,5),(4,4)]] +[[[(2,0),(10,0),(10,10),(0,10),(2,0)],[(4,4),(5,4),(5,5),(4,5),(4,4)]],[[(-10,-10),(-10,-9),(-9,10),(-10,-10)]]] +(0,0) +(1,0) +(2,0) +[[(1,0),(10,0),(10,10),(0,10),(1,0)]] +[[(0,0),(10,0),(10,10),(0,10),(0,0)]] +[[(2,0),(10,0),(10,10),(0,10),(2,0)]] +[[(0,0),(10,0),(10,10),(0,10),(0,0)],[(4,4),(5,4),(5,5),(4,5),(4,4)]] +[[(2,0),(10,0),(10,10),(0,10),(2,0)],[(4,4),(5,4),(5,5),(4,5),(4,4)]] +[[(1,0),(10,0),(10,10),(0,10),(1,0)],[(4,4),(5,4),(5,5),(4,5),(4,4)]] +[[[(1,0),(10,0),(10,10),(0,10),(1,0)],[(4,4),(5,4),(5,5),(4,5),(4,4)]],[[(-10,-10),(-10,-9),(-9,10),(-10,-10)]]] +[[[(0,0),(10,0),(10,10),(0,10),(0,0)],[(4,4),(5,4),(5,5),(4,5),(4,4)]],[[(-10,-10),(-10,-9),(-9,10),(-10,-10)]]] +[[[(2,0),(10,0),(10,10),(0,10),(2,0)],[(4,4),(5,4),(5,5),(4,5),(4,4)]],[[(-10,-10),(-10,-9),(-9,10),(-10,-10)]]] diff --git a/tests/queries/0_stateless/01300_read_wkt.sql b/tests/queries/0_stateless/01300_read_wkt.sql new file mode 100644 index 00000000000..590305fddae --- /dev/null +++ b/tests/queries/0_stateless/01300_read_wkt.sql @@ -0,0 +1,28 @@ +SELECT readWktPoint('POINT(0 0)'); +SELECT readWktPolygon('POLYGON((1 0,10 0,10 10,0 10,1 0))'); +SELECT readWktPolygon('POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,5 4,5 5,4 5,4 4))'); +SELECT readWktMultiPolygon('MULTIPOLYGON(((2 0,10 0,10 10,0 10,2 0),(4 4,5 4,5 5,4 5,4 4)),((-10 -10,-10 -9,-9 10,-10 -10)))'); + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (s String, id Int) engine=Memory(); +INSERT INTO geo VALUES ('POINT(0 0)', 1); +INSERT INTO geo VALUES ('POINT(1 0)', 2); +INSERT INTO geo VALUES ('POINT(2 0)', 3); +SELECT readWktPoint(s) FROM geo ORDER BY id; + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (s String, id Int) engine=Memory(); +INSERT INTO geo VALUES ('POLYGON((1 0,10 0,10 10,0 10,1 0))', 1); +INSERT INTO geo VALUES ('POLYGON((0 0,10 0,10 10,0 10,0 0))', 2); +INSERT INTO geo VALUES ('POLYGON((2 0,10 0,10 10,0 10,2 0))', 3); +INSERT INTO geo VALUES ('POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,5 4,5 5,4 5,4 4))', 4); +INSERT INTO geo VALUES ('POLYGON((2 0,10 0,10 10,0 10,2 0),(4 4,5 4,5 5,4 5,4 4))', 5); +INSERT INTO geo VALUES ('POLYGON((1 0,10 0,10 10,0 10,1 0),(4 4,5 4,5 5,4 5,4 4))', 6); +SELECT readWktPolygon(s) FROM geo ORDER BY id; + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (s String, id Int) engine=Memory(); +INSERT INTO geo VALUES ('MULTIPOLYGON(((1 0,10 0,10 10,0 10,1 0),(4 4,5 4,5 5,4 5,4 4)),((-10 -10,-10 -9,-9 10,-10 -10)))', 1); +INSERT INTO geo VALUES ('MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(4 4,5 4,5 5,4 5,4 4)),((-10 -10,-10 -9,-9 10,-10 -10)))', 2); +INSERT INTO geo VALUES ('MULTIPOLYGON(((2 0,10 0,10 10,0 10,2 0),(4 4,5 4,5 5,4 5,4 4)),((-10 -10,-10 -9,-9 10,-10 -10)))', 3); +SELECT readWktMultiPolygon(s) FROM geo ORDER BY id; diff --git a/tests/queries/0_stateless/01300_svg.reference b/tests/queries/0_stateless/01300_svg.reference new file mode 100644 index 00000000000..d39d67ff273 --- /dev/null +++ b/tests/queries/0_stateless/01300_svg.reference @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/queries/0_stateless/01300_svg.sql b/tests/queries/0_stateless/01300_svg.sql new file mode 100644 index 00000000000..3e70182023b --- /dev/null +++ b/tests/queries/0_stateless/01300_svg.sql @@ -0,0 +1,48 @@ +SELECT svg((0., 0.)); +SELECT svg([(0., 0.), (10, 0), (10, 10), (0, 10)]); +SELECT svg([[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]]); +SELECT svg([[[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]]); +SELECT svg((0., 0.), 'b'); +SELECT svg([(0., 0.), (10, 0), (10, 10), (0, 10)], 'b'); +SELECT svg([[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], 'b'); +SELECT svg([[[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]], 'b'); + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (p Tuple(Float64, Float64), s String, id Int) engine=Memory(); +INSERT INTO geo VALUES ((0., 0.), 'b', 1); +INSERT INTO geo VALUES ((1., 0.), 'c', 2); +INSERT INTO geo VALUES ((2., 0.), 'd', 3); +SELECT svg(p) FROM geo ORDER BY id; +SELECT svg(p, 'b') FROM geo ORDER BY id; +SELECT svg((0., 0.), s) FROM geo ORDER BY id; +SELECT svg(p, s) FROM geo ORDER BY id; + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (p Array(Tuple(Float64, Float64)), s String, id Int) engine=Memory(); +INSERT INTO geo VALUES ([(0., 0.), (10, 0), (10, 10), (0, 10)], 'b', 1); +INSERT INTO geo VALUES ([(1., 0.), (10, 0), (10, 10), (0, 10)], 'c', 2); +INSERT INTO geo VALUES ([(2., 0.), (10, 0), (10, 10), (0, 10)], 'd', 3); +SELECT svg(p) FROM geo ORDER BY id; +SELECT svg(p, 'b') FROM geo ORDER BY id; +SELECT svg([(0., 0.), (10, 0), (10, 10), (0, 10)], s) FROM geo ORDER BY id; +SELECT svg(p, s) FROM geo ORDER BY id; + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (p Array(Array(Tuple(Float64, Float64))), s String, id Int) engine=Memory(); +INSERT INTO geo VALUES ([[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 'b', 1); +INSERT INTO geo VALUES ([[(1., 0.), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 'c', 2); +INSERT INTO geo VALUES ([[(2., 0.), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 'd', 3); +SELECT svg(p) FROM geo ORDER BY id; +SELECT svg(p, 'b') FROM geo ORDER BY id; +SELECT svg([[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], s) FROM geo ORDER BY id; +SELECT svg(p, s) FROM geo ORDER BY id; + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (p Array(Array(Array(Tuple(Float64, Float64)))), s String, id Int) engine=Memory(); +INSERT INTO geo VALUES ([[[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]], 'b', 1); +INSERT INTO geo VALUES ([[[(1., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]], 'c', 2); +INSERT INTO geo VALUES ([[[(2., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]], 'd', 3); +SELECT svg(p) FROM geo ORDER BY id; +SELECT svg(p, 'b') FROM geo ORDER BY id; +SELECT svg([[[(0., 0.), (10, 0), (10, 10), (0, 10)], [(4., 4.), (5, 4), (5, 5), (4, 5)]], [[(-10., -10.), (-10, -9), (-9, 10)]]], s) FROM geo ORDER BY id; +SELECT svg(p, s) FROM geo ORDER BY id; diff --git a/tests/queries/0_stateless/01300_wkt.reference b/tests/queries/0_stateless/01300_wkt.reference new file mode 100644 index 00000000000..0079e9f32df --- /dev/null +++ b/tests/queries/0_stateless/01300_wkt.reference @@ -0,0 +1,16 @@ +POINT(0 0) +POLYGON((0 0,10 0,10 10,0 10)) +POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,5 4,5 5,4 5,4 4)) +MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(4 4,5 4,5 5,4 5,4 4)),((-10 -10,-10 -9,-9 10,-10 -10))) +POINT(0 0) +POINT(1 0) +POINT(2 0) +POLYGON((0 0,10 0,10 10,0 10)) +POLYGON((1 0,10 0,10 10,0 10)) +POLYGON((2 0,10 0,10 10,0 10)) +POLYGON((0 0,10 0,10 10,0 10,0 0),(4 4,5 4,5 5,4 5,4 4)) +POLYGON((1 0,10 0,10 10,0 10,1 0),(4 4,5 4,5 5,4 5,4 4)) +POLYGON((2 0,10 0,10 10,0 10,2 0),(4 4,5 4,5 5,4 5,4 4)) +MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(4 4,5 4,5 5,4 5,4 4)),((-10 -10,-10 -9,-9 10,-10 -10))) +MULTIPOLYGON(((1 0,10 0,10 10,0 10,1 0),(4 4,5 4,5 5,4 5,4 4)),((-10 -10,-10 -9,-9 10,-10 -10))) +MULTIPOLYGON(((2 0,10 0,10 10,0 10,2 0),(4 4,5 4,5 5,4 5,4 4)),((-10 -10,-10 -9,-9 10,-10 -10))) diff --git a/tests/queries/0_stateless/01300_wkt.sql b/tests/queries/0_stateless/01300_wkt.sql new file mode 100644 index 00000000000..7047bb698bb --- /dev/null +++ b/tests/queries/0_stateless/01300_wkt.sql @@ -0,0 +1,32 @@ +SELECT wkt((0., 0.)); +SELECT wkt([(0., 0.), (10., 0.), (10., 10.), (0., 10.)]); +SELECT wkt([[(0., 0.), (10., 0.), (10., 10.), (0., 10.)], [(4., 4.), (5., 4.), (5., 5.), (4., 5.)]]); +SELECT wkt([[[(0., 0.), (10., 0.), (10., 10.), (0., 10.)], [(4., 4.), (5., 4.), (5., 5.), (4., 5.)]], [[(-10., -10.), (-10., -9.), (-9., 10.)]]]); + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (p Tuple(Float64, Float64), id Int) engine=Memory(); +INSERT INTO geo VALUES ((0, 0), 1); +INSERT INTO geo VALUES ((1, 0), 2); +INSERT INTO geo VALUES ((2, 0), 3); +SELECT wkt(p) FROM geo ORDER BY id; + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (p Array(Tuple(Float64, Float64)), id Int) engine=Memory(); +INSERT INTO geo VALUES ([(0, 0), (10, 0), (10, 10), (0, 10)], 1); +INSERT INTO geo VALUES ([(1, 0), (10, 0), (10, 10), (0, 10)], 2); +INSERT INTO geo VALUES ([(2, 0), (10, 0), (10, 10), (0, 10)], 3); +SELECT wkt(p) FROM geo ORDER BY id; + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (p Array(Array(Tuple(Float64, Float64))), id Int) engine=Memory(); +INSERT INTO geo VALUES ([[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 1); +INSERT INTO geo VALUES ([[(1, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 2); +INSERT INTO geo VALUES ([[(2, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], 3); +SELECT wkt(p) FROM geo ORDER BY id; + +DROP TABLE IF EXISTS geo; +CREATE TABLE geo (p Array(Array(Array(Tuple(Float64, Float64)))), id Int) engine=Memory(); +INSERT INTO geo VALUES ([[[(0, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], [[(-10, -10), (-10, -9), (-9, 10)]]], 1); +INSERT INTO geo VALUES ([[[(1, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], [[(-10, -10), (-10, -9), (-9, 10)]]], 2); +INSERT INTO geo VALUES ([[[(2, 0), (10, 0), (10, 10), (0, 10)], [(4, 4), (5, 4), (5, 5), (4, 5)]], [[(-10, -10), (-10, -9), (-9, 10)]]], 3); +SELECT wkt(p) FROM geo ORDER BY id; diff --git a/tests/queries/0_stateless/01301_polygons_within.reference b/tests/queries/0_stateless/01301_polygons_within.reference new file mode 100644 index 00000000000..ee14f826295 --- /dev/null +++ b/tests/queries/0_stateless/01301_polygons_within.reference @@ -0,0 +1,10 @@ +0 +1 +0 +1 +-------- MultiPolygon with Polygon +0 +-------- MultiPolygon with Polygon with Holes +0 +-------- Polygon with Polygon with Holes +0 diff --git a/tests/queries/0_stateless/01301_polygons_within.sql b/tests/queries/0_stateless/01301_polygons_within.sql new file mode 100644 index 00000000000..901c7909af7 --- /dev/null +++ b/tests/queries/0_stateless/01301_polygons_within.sql @@ -0,0 +1,15 @@ +select polygonsWithinCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); +select polygonsWithinCartesian([[[(2., 2.), (2., 3.), (3., 3.), (3., 2.)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); + +select polygonsWithinSpherical([[[(4.3613577, 50.8651821), (4.349556, 50.8535879), (4.3602419, 50.8435626), (4.3830299, 50.8428851), (4.3904543, 50.8564867), (4.3613148, 50.8651279)]]], [[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]); +select polygonsWithinSpherical([[[(4.3501568, 50.8518269), (4.3444920, 50.8439961), (4.3565941, 50.8443213), (4.3501568, 50.8518269)]]], [[[(4.3679450, 50.8524550),(4.3466930, 50.8583060),(4.3380740, 50.8486770),(4.3449610, 50.8332640),(4.3662270, 50.8408090),(4.3679450, 50.8524550)]]]); + +select '-------- MultiPolygon with Polygon'; +select polygonsWithinSpherical([[(29.453587685533865,59.779570356240356),(29.393139070478895,52.276266797422124),(40.636581470703206,59.38168915000267),(41.21084331372543,59.103467777099866),(29.786055068336193,52.146627480315004),(31.23682182965546,52.16517054781818),(41.69443223416517,58.85424941916091),(42.51048853740727,58.47703162291134),(32.59691566839227,52.22075341251539),(34.289476889931414,52.22075341251539),(43.02430176537451,58.07974369546071),(43.02430176537451,57.25537683364851),(35.468224883503325,52.2022335126388),(37.16078610504247,52.23926559241349),(43.02430176537451,56.26136189644947),(43.02430176537451,55.326904361850836),(38.33953409861437,52.16517054781818),(40.09254393520848,52.16517054781818),(44.4146199116388,55.3097062225408),(44.47506852669377,59.80998197603594),(39.72985224487867,59.931351417569715),(30.23941968124846,53.67744677450975),(30.20919537372098,54.63314259659509),(38.73245009647167,59.94649146557819),(37.2816833351524,59.97675082987618),(30.23941968124846,55.2752875586599),(30.33009260383092,56.19415599955667),(36.28428118674541,59.96162460231375),(34.863738732953635,59.97675082987618),(30.178971066193498,56.97640788219866),(30.178971066193498,57.91957806959033),(33.65476643185424,59.94649146557819),(32.32489690064491,59.94649146557819),(30.481214141468342,58.85424941916091),(30.571887064050795,59.99187015036608),(29.453587685533865,59.779570356240356)]], [[[(33.473420586689336,58.85424941916091),(32.23422397806246,58.492830557036),(32.173775363007486,58.03176922751564),(31.508840597402823,57.499784781503735),(31.750635057622702,56.86092686957355),(31.508840597402823,55.941082594334574),(32.20399967053497,55.515591939372456),(31.84130798020516,54.998862226280465),(31.418167674820367,54.422670886434275),(32.47601843828233,53.83826377018255),(32.08310244042503,53.408048308050866),(33.171177511414484,52.82758702113742),(34.77306581037117,52.91880107773494),(34.77306581037117,53.784726518357985),(34.108131044766516,54.17574726780569),(35.07530888564602,54.59813930694554),(34.25925258240394,54.96417435716029),(35.01486027059106,55.361278263643584),(33.50364489421682,55.37845402950552),(32.7480372060297,55.90721384574556),(35.67979503619571,55.68634475630185),(32.83871012861215,56.311688992608396),(34.591719965206266,56.29492065473883),(35.7100193437232,56.311688992608396),(33.83611227701915,56.695333481003644),(32.95960735872209,56.9434497616887),(36.072711034053015,57.091531913901434),(33.171177511414484,57.33702717078384),(36.193608264162954,57.499784781503735),(33.23162612646945,57.77481561306047),(36.43540272438284,58.04776787540811),(33.62454212432676,58.27099811968307),(36.344729801800376,58.54018474404165),(33.83611227701915,58.68186423448108),(34.74284150284369,59.565911441555244),(33.473420586689336,58.85424941916091)]], [[(34.65216858026123,58.91672306881671),(37.19101041256995,58.68186423448108),(36.01226241899805,58.28688958537609),(37.16078610504247,58.04776787540811),(35.74024365125068,57.79092907387934),(37.009664567405046,57.499784781503735),(35.77046795877817,57.25537683364851),(36.979440259877556,57.07510745541089),(34.22902827487645,56.794777197297435),(36.7074214921302,56.210968525786996),(34.712617195316206,56.10998276812964),(36.55629995449277,55.63519693782703),(35.13575750070099,55.53270067649592),(36.43540272438284,55.34409504165558),(34.83351442542614,55.01619492319591),(35.61934642114075,54.49294870011772),(34.89396304048112,54.12264226523038),(35.37755196092087,53.046178687628185),(37.43280487278982,52.95523300597458),(35.92158949641559,53.80257986695776),(36.91899164482259,53.856094327816805),(36.01226241899805,54.75541714463799),(37.765272255592166,55.189110239786885),(36.828318722240134,55.44708256557195),(38.03729102333953,55.652253637168315),(36.64697287707522,55.941082594334574),(38.21863686850443,56.05939028508024),(36.37495410932787,56.64551287174558),(38.30930979108689,56.992876013526654),(37.16078610504247,57.25537683364851),(38.127963945921984,57.516020773674256),(37.43280487278982,57.710289827306724),(38.33953409861437,57.935626886818994),(37.40258056526235,58.31865112960426),(38.58132855883426,58.744648733419496),(37.31190764267989,59.02578062465136),(34.65216858026123,58.91672306881671)]], [[(38.52087994377928,59.11898412389468),(39.54850639971376,58.713270635642914),(38.369758406141855,58.28688958537609),(38.85334732658162,58.06375936407028),(38.33953409861437,57.710289827306724),(38.73245009647167,57.48354156434209),(38.21863686850443,57.271721400459285),(38.97424455669155,56.87744603722649),(37.463029180317314,56.5623320541159),(38.94402024916407,56.05939028508024),(38.18841256097694,55.856355210835915),(38.490655636251795,55.53270067649592),(37.795496563119656,55.39562234093384),(38.30930979108689,55.154587013355666),(36.7074214921302,54.65063295250911),(37.31190764267989,53.92734063371401),(36.979440259877556,53.58783775557231),(37.855945178174615,52.91880107773497),(39.57873070724124,52.69956490610895),(38.33953409861437,53.281741738901104),(40.00187101262603,53.35396273604752),(39.54850639971376,53.58783775557231),(40.24366547284591,53.58783775557231),(39.97164670509855,53.98069568468355),(40.60635716317572,54.03398248547225),(40.39478701048334,54.44025165268903),(39.54850639971376,54.56310590284329),(39.54850639971376,54.87732350170489),(40.39478701048334,54.87732350170489),(40.39478701048334,55.24083903654295),(39.82052516746112,55.2752875586599),(39.760076552406154,55.75443792473942),(40.57613285564824,55.78844000174894),(40.425011318010824,56.19415599955667),(39.82052516746112,56.07626182891758),(39.79030085993364,56.41214455508424),(40.48545993306579,56.495655446714636),(40.33433839542836,56.95993246553937),(39.79030085993364,56.992876013526654),(39.72985224487867,57.46729112028032),(40.33433839542836,57.46729112028032),(40.24366547284591,58.04776787540811),(39.63917932229622,58.04776787540811),(39.63917932229622,58.382088724871295),(40.33433839542836,58.382088724871295),(40.45523562553831,58.9011152358548),(38.52087994377928,59.11898412389468)]]]) format TSV; + +select '-------- MultiPolygon with Polygon with Holes'; +select polygonsWithinSpherical([[[(33.473420586689336,58.85424941916091),(32.23422397806246,58.492830557036),(32.173775363007486,58.03176922751564),(31.508840597402823,57.499784781503735),(31.750635057622702,56.86092686957355),(31.508840597402823,55.941082594334574),(32.20399967053497,55.515591939372456),(31.84130798020516,54.998862226280465),(31.418167674820367,54.422670886434275),(32.47601843828233,53.83826377018255),(32.08310244042503,53.408048308050866),(33.171177511414484,52.82758702113742),(34.77306581037117,52.91880107773494),(34.77306581037117,53.784726518357985),(34.108131044766516,54.17574726780569),(35.07530888564602,54.59813930694554),(34.25925258240394,54.96417435716029),(35.01486027059106,55.361278263643584),(33.50364489421682,55.37845402950552),(32.7480372060297,55.90721384574556),(35.67979503619571,55.68634475630185),(32.83871012861215,56.311688992608396),(34.591719965206266,56.29492065473883),(35.7100193437232,56.311688992608396),(33.83611227701915,56.695333481003644),(32.95960735872209,56.9434497616887),(36.072711034053015,57.091531913901434),(33.171177511414484,57.33702717078384),(36.193608264162954,57.499784781503735),(33.23162612646945,57.77481561306047),(36.43540272438284,58.04776787540811),(33.62454212432676,58.27099811968307),(36.344729801800376,58.54018474404165),(33.83611227701915,58.68186423448108),(34.74284150284369,59.565911441555244),(33.473420586689336,58.85424941916091)]], [[(34.65216858026123,58.91672306881671),(37.19101041256995,58.68186423448108),(36.01226241899805,58.28688958537609),(37.16078610504247,58.04776787540811),(35.74024365125068,57.79092907387934),(37.009664567405046,57.499784781503735),(35.77046795877817,57.25537683364851),(36.979440259877556,57.07510745541089),(34.22902827487645,56.794777197297435),(36.7074214921302,56.210968525786996),(34.712617195316206,56.10998276812964),(36.55629995449277,55.63519693782703),(35.13575750070099,55.53270067649592),(36.43540272438284,55.34409504165558),(34.83351442542614,55.01619492319591),(35.61934642114075,54.49294870011772),(34.89396304048112,54.12264226523038),(35.37755196092087,53.046178687628185),(37.43280487278982,52.95523300597458),(35.92158949641559,53.80257986695776),(36.91899164482259,53.856094327816805),(36.01226241899805,54.75541714463799),(37.765272255592166,55.189110239786885),(36.828318722240134,55.44708256557195),(38.03729102333953,55.652253637168315),(36.64697287707522,55.941082594334574),(38.21863686850443,56.05939028508024),(36.37495410932787,56.64551287174558),(38.30930979108689,56.992876013526654),(37.16078610504247,57.25537683364851),(38.127963945921984,57.516020773674256),(37.43280487278982,57.710289827306724),(38.33953409861437,57.935626886818994),(37.40258056526235,58.31865112960426),(38.58132855883426,58.744648733419496),(37.31190764267989,59.02578062465136),(34.65216858026123,58.91672306881671)]], [[(38.52087994377928,59.11898412389468),(39.54850639971376,58.713270635642914),(38.369758406141855,58.28688958537609),(38.85334732658162,58.06375936407028),(38.33953409861437,57.710289827306724),(38.73245009647167,57.48354156434209),(38.21863686850443,57.271721400459285),(38.97424455669155,56.87744603722649),(37.463029180317314,56.5623320541159),(38.94402024916407,56.05939028508024),(38.18841256097694,55.856355210835915),(38.490655636251795,55.53270067649592),(37.795496563119656,55.39562234093384),(38.30930979108689,55.154587013355666),(36.7074214921302,54.65063295250911),(37.31190764267989,53.92734063371401),(36.979440259877556,53.58783775557231),(37.855945178174615,52.91880107773497),(39.57873070724124,52.69956490610895),(38.33953409861437,53.281741738901104),(40.00187101262603,53.35396273604752),(39.54850639971376,53.58783775557231),(40.24366547284591,53.58783775557231),(39.97164670509855,53.98069568468355),(40.60635716317572,54.03398248547225),(40.39478701048334,54.44025165268903),(39.54850639971376,54.56310590284329),(39.54850639971376,54.87732350170489),(40.39478701048334,54.87732350170489),(40.39478701048334,55.24083903654295),(39.82052516746112,55.2752875586599),(39.760076552406154,55.75443792473942),(40.57613285564824,55.78844000174894),(40.425011318010824,56.19415599955667),(39.82052516746112,56.07626182891758),(39.79030085993364,56.41214455508424),(40.48545993306579,56.495655446714636),(40.33433839542836,56.95993246553937),(39.79030085993364,56.992876013526654),(39.72985224487867,57.46729112028032),(40.33433839542836,57.46729112028032),(40.24366547284591,58.04776787540811),(39.63917932229622,58.04776787540811),(39.63917932229622,58.382088724871295),(40.33433839542836,58.382088724871295),(40.45523562553831,58.9011152358548),(38.52087994377928,59.11898412389468)]]], [[(24.367675781249993,61.45977057029751),(19.577636718749993,58.67693767258692),(19.577636718749993,57.492213666700735),(19.445800781249996,55.87531083569678),(19.445800781249996,54.085173420886775),(17.468261718749996,53.014783245859235),(20.017089843749993,51.563412328675895),(21.203613281249993,50.205033264943324),(26.125488281249993,50.40151532278236),(27.22412109374999,48.980216985374994),(32.80517578124999,49.525208341974405),(35.26611328124999,48.74894534343292),(36.93603515624999,49.66762782262194),(42.56103515625,48.77791275550183),(43.92333984374999,49.8096315635631),(47.17529296875,49.152969656170455),(49.28466796875,50.54136296522162),(48.05419921875,51.17934297928929),(51.39404296875,52.48278022207825),(50.64697265625,53.014783245859235),(52.88818359375,53.93021986394004),(51.65771484374999,54.29088164657006),(52.66845703125,55.825973254619015),(50.25146484375,56.145549500679095),(51.92138671875,57.914847767009206),(49.15283203125,58.17070248348605),(49.59228515625,60.086762746260064),(47.043457031249986,59.88893689676584),(43.57177734375,61.37567331572748),(42.64892578125,60.630101766266705),(36.89208984374999,62.000904713685856),(36.01318359374999,61.143235250840576),(31.398925781249993,62.02152819100766),(30.563964843749996,61.05828537037917),(26.872558593749993,61.71070595883174),(26.652832031249993,61.10078883158897),(24.367675781249993,61.45977057029751)], [(24.455566406249993,59.42272750081452),(21.203613281249993,58.49369382056807),(21.335449218749993,56.89700392127261),(21.599121093749993,55.92458580482949),(25.202636718749993,55.998380955359636),(28.850097656249993,57.06463027327854),(27.09228515625,57.844750992890994),(28.806152343749996,59.17592824927138),(26.257324218749993,59.17592824927138),(24.455566406249993,59.42272750081452)], [(35.13427734375,59.84481485969107),(31.970214843749993,58.97266715450152),(33.20068359374999,56.776808316568406),(36.67236328125,56.41390137600675),(39.08935546874999,57.25528054528888),(42.69287109374999,58.03137242177638),(40.89111328124999,59.26588062825809),(37.28759765625,58.722598828043374),(37.11181640624999,59.66774058164964),(35.13427734375,59.84481485969107)], [(29.157714843749993,55.75184939173528),(22.565917968749993,55.128649068488784),(22.565917968749993,53.54030739150019),(22.038574218749996,51.48138289610097),(26.257324218749993,51.42661449707484),(30.124511718749993,50.54136296522162),(32.18994140624999,51.17934297928929),(30.124511718749993,53.173119202640635),(35.09033203124999,53.173119202640635),(33.11279296875,54.085173420886775),(29.597167968749993,55.50374985927513),(29.157714843749993,55.75184939173528)], [(42.82470703125,56.58369172128337),(36.584472656249986,55.329144408405085),(37.99072265625,53.592504809039355),(34.95849609374999,51.48138289610097),(36.54052734374999,50.40151532278236),(39.66064453124999,50.289339253291786),(39.79248046875,52.13348804077148),(41.77001953125,50.68079714532166),(44.49462890624999,51.97134580885171),(47.30712890624999,52.509534770327264),(44.05517578125,53.54030739150019),(46.60400390625,53.696706475303245),(47.61474609375,55.40406982700608),(45.37353515625,55.40406982700608),(42.82470703125,56.58369172128337)]]) format TSV; + +select '-------- Polygon with Polygon with Holes'; +select polygonsWithinSpherical([[(29.453587685533865,59.779570356240356),(29.393139070478895,52.276266797422124),(40.636581470703206,59.38168915000267),(41.21084331372543,59.103467777099866),(29.786055068336193,52.146627480315004),(31.23682182965546,52.16517054781818),(41.69443223416517,58.85424941916091),(42.51048853740727,58.47703162291134),(32.59691566839227,52.22075341251539),(34.289476889931414,52.22075341251539),(43.02430176537451,58.07974369546071),(43.02430176537451,57.25537683364851),(35.468224883503325,52.2022335126388),(37.16078610504247,52.23926559241349),(43.02430176537451,56.26136189644947),(43.02430176537451,55.326904361850836),(38.33953409861437,52.16517054781818),(40.09254393520848,52.16517054781818),(44.4146199116388,55.3097062225408),(44.47506852669377,59.80998197603594),(39.72985224487867,59.931351417569715),(30.23941968124846,53.67744677450975),(30.20919537372098,54.63314259659509),(38.73245009647167,59.94649146557819),(37.2816833351524,59.97675082987618),(30.23941968124846,55.2752875586599),(30.33009260383092,56.19415599955667),(36.28428118674541,59.96162460231375),(34.863738732953635,59.97675082987618),(30.178971066193498,56.97640788219866),(30.178971066193498,57.91957806959033),(33.65476643185424,59.94649146557819),(32.32489690064491,59.94649146557819),(30.481214141468342,58.85424941916091),(30.571887064050795,59.99187015036608),(29.453587685533865,59.779570356240356)]], [[(24.367675781249993,61.45977057029751),(19.577636718749993,58.67693767258692),(19.577636718749993,57.492213666700735),(19.445800781249996,55.87531083569678),(19.445800781249996,54.085173420886775),(17.468261718749996,53.014783245859235),(20.017089843749993,51.563412328675895),(21.203613281249993,50.205033264943324),(26.125488281249993,50.40151532278236),(27.22412109374999,48.980216985374994),(32.80517578124999,49.525208341974405),(35.26611328124999,48.74894534343292),(36.93603515624999,49.66762782262194),(42.56103515625,48.77791275550183),(43.92333984374999,49.8096315635631),(47.17529296875,49.152969656170455),(49.28466796875,50.54136296522162),(48.05419921875,51.17934297928929),(51.39404296875,52.48278022207825),(50.64697265625,53.014783245859235),(52.88818359375,53.93021986394004),(51.65771484374999,54.29088164657006),(52.66845703125,55.825973254619015),(50.25146484375,56.145549500679095),(51.92138671875,57.914847767009206),(49.15283203125,58.17070248348605),(49.59228515625,60.086762746260064),(47.043457031249986,59.88893689676584),(43.57177734375,61.37567331572748),(42.64892578125,60.630101766266705),(36.89208984374999,62.000904713685856),(36.01318359374999,61.143235250840576),(31.398925781249993,62.02152819100766),(30.563964843749996,61.05828537037917),(26.872558593749993,61.71070595883174),(26.652832031249993,61.10078883158897),(24.367675781249993,61.45977057029751)], [(24.455566406249993,59.42272750081452),(21.203613281249993,58.49369382056807),(21.335449218749993,56.89700392127261),(21.599121093749993,55.92458580482949),(25.202636718749993,55.998380955359636),(28.850097656249993,57.06463027327854),(27.09228515625,57.844750992890994),(28.806152343749996,59.17592824927138),(26.257324218749993,59.17592824927138),(24.455566406249993,59.42272750081452)], [(35.13427734375,59.84481485969107),(31.970214843749993,58.97266715450152),(33.20068359374999,56.776808316568406),(36.67236328125,56.41390137600675),(39.08935546874999,57.25528054528888),(42.69287109374999,58.03137242177638),(40.89111328124999,59.26588062825809),(37.28759765625,58.722598828043374),(37.11181640624999,59.66774058164964),(35.13427734375,59.84481485969107)], [(29.157714843749993,55.75184939173528),(22.565917968749993,55.128649068488784),(22.565917968749993,53.54030739150019),(22.038574218749996,51.48138289610097),(26.257324218749993,51.42661449707484),(30.124511718749993,50.54136296522162),(32.18994140624999,51.17934297928929),(30.124511718749993,53.173119202640635),(35.09033203124999,53.173119202640635),(33.11279296875,54.085173420886775),(29.597167968749993,55.50374985927513),(29.157714843749993,55.75184939173528)], [(42.82470703125,56.58369172128337),(36.584472656249986,55.329144408405085),(37.99072265625,53.592504809039355),(34.95849609374999,51.48138289610097),(36.54052734374999,50.40151532278236),(39.66064453124999,50.289339253291786),(39.79248046875,52.13348804077148),(41.77001953125,50.68079714532166),(44.49462890624999,51.97134580885171),(47.30712890624999,52.509534770327264),(44.05517578125,53.54030739150019),(46.60400390625,53.696706475303245),(47.61474609375,55.40406982700608),(45.37353515625,55.40406982700608),(42.82470703125,56.58369172128337)]]) format TSV; + diff --git a/tests/queries/0_stateless/01302_polygons_distance.reference b/tests/queries/0_stateless/01302_polygons_distance.reference new file mode 100644 index 00000000000..f5f59e30710 --- /dev/null +++ b/tests/queries/0_stateless/01302_polygons_distance.reference @@ -0,0 +1,4 @@ +0 +1.2727922061357855 +0.3274195462417724 +0.3274195462417724 diff --git a/tests/queries/0_stateless/01302_polygons_distance.sql b/tests/queries/0_stateless/01302_polygons_distance.sql new file mode 100644 index 00000000000..fdbd0254983 --- /dev/null +++ b/tests/queries/0_stateless/01302_polygons_distance.sql @@ -0,0 +1,8 @@ +select polygonsDistanceCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); +select polygonsDistanceCartesian([[[(0, 0), (0, 0.1), (0.1, 0.1), (0.1, 0)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); +select polygonsDistanceSpherical([[[(23.725750, 37.971536)]]], [[[(4.3826169, 50.8119483)]]]); + +drop table if exists polygon_01302; +create table polygon_01302 (x Array(Array(Array(Tuple(Float64, Float64)))), y Array(Array(Array(Tuple(Float64, Float64))))) engine=Memory(); +insert into polygon_01302 values ([[[(23.725750, 37.971536)]]], [[[(4.3826169, 50.8119483)]]]); +select polygonsDistanceSpherical(x, y) from polygon_01302; diff --git a/tests/queries/0_stateless/01303_polygons_equals.reference b/tests/queries/0_stateless/01303_polygons_equals.reference new file mode 100644 index 00000000000..0d66ea1aee9 --- /dev/null +++ b/tests/queries/0_stateless/01303_polygons_equals.reference @@ -0,0 +1,2 @@ +0 +1 diff --git a/tests/queries/0_stateless/01303_polygons_equals.sql b/tests/queries/0_stateless/01303_polygons_equals.sql new file mode 100644 index 00000000000..42f1bd4693c --- /dev/null +++ b/tests/queries/0_stateless/01303_polygons_equals.sql @@ -0,0 +1,2 @@ +select polygonsEqualsCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); +select polygonsEqualsCartesian([[[(1., 1.),(1., 4.),(4., 4.),(4., 1.)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); diff --git a/tests/queries/0_stateless/01304_polygons_sym_difference.reference b/tests/queries/0_stateless/01304_polygons_sym_difference.reference new file mode 100644 index 00000000000..7d16848ac2e --- /dev/null +++ b/tests/queries/0_stateless/01304_polygons_sym_difference.reference @@ -0,0 +1,7 @@ +[[[(1,2.9),(1,1),(2.9,1),(3,0),(0,0),(0,3),(1,2.9)]],[[(1,2.9),(1,4),(4,4),(4,1),(2.9,1),(2.6,2),(2,2.6),(1,2.9)]]] +-------- MultiPolygon with Polygon +MULTIPOLYGON(((36.9725 59.0149,35.5408 58.9593,37.2817 59.9768,38.7325 59.9465,36.9725 59.0149)),((36.9725 59.0149,37.3119 59.0258,37.8553 58.9075,36.5949 58.1673,36.0123 58.2869,37.191 58.6819,36.4989 58.7512,36.9725 59.0149)),((36.151 54.791,37.7653 55.1891,37.06 55.3843,37.2824 55.5258,38.0373 55.6523,37.6238 55.7402,38.1319 56.0534,38.2186 56.0594,38.1688 56.0758,38.4339 56.2361,38.944 56.0594,38.1884 55.8564,38.4907 55.5327,37.7955 55.3956,38.2609 55.1775,38.1601 55.1091,36.7074 54.6506,37.0035 54.2999,36.6985 54.0791,36.0472 54.7217,36.151 54.791)),((36.151 54.791,36.0123 54.7554,36.0472 54.7217,34.9611 53.9765,34.894 54.1226,35.6193 54.4929,34.9706 54.9262,35.2275 55.0993,36.4354 55.3441,35.7505 55.4454,35.9817 55.5958,36.5563 55.6352,36.193 55.7319,37.2281 56.3799,38.1688 56.0758,38.1319 56.0534,36.647 55.9411,37.6238 55.7402,37.2824 55.5258,36.8283 55.4471,37.06 55.3843,36.151 54.791)),((36.5334 56.6753,38.2312 56.9795,37.565 56.5843,37.463 56.5623,37.5054 56.5484,37.2281 56.3799,36.4446 56.6242,36.5334 56.6753)),((36.5334 56.6753,36.375 56.6455,36.4446 56.6242,36.0233 56.3789,35.4083 56.5254,36.1999 57.0022,36.9794 57.0751,36.4587 57.1544,38.0535 58.0542,38.3395 57.9356,37.4328 57.7103,38.0744 57.5312,37.9669 57.4734,37.1608 57.2554,37.4489 57.1909,36.5334 56.6753)),((36.8709 53.2765,37.135 53.4711,37.8559 52.9188,38.0214 52.8989,37.1608 52.2393,35.4682 52.2022,36.5022 53.0008,37.4328 52.9552,36.8709 53.2765)),((36.8709 53.2765,36.5022 53.0008,35.3776 53.0462,35.3645 53.076,36.1528 53.6763,36.8709 53.2765)),((36.6985 54.0791,36.919 53.8561,36.3552 53.8269,36.6985 54.0791)),((35.5408 58.9593,35.3712 58.8556,34.6522 58.9167,35.5408 58.9593)),((36.0848 57.855,36.3932 58.0447,36.4354 58.0478,36.403 58.0507,36.5949 58.1673,37.1608 58.0478,36.0848 57.855)),((36.0848 57.855,35.9179 57.7512,35.7402 57.7909,36.0848 57.855)),((37.135 53.4711,36.9794 53.5878,37.3119 53.9273,37.0035 54.2999,38.1601 55.1091,38.3093 55.1546,38.2609 55.1775,39.8102 56.1914,39.8205 56.0763,40.425 56.1942,40.5716 55.8007,40.5504 55.7875,39.7601 55.7544,39.8151 55.3187,37.135 53.4711)),((38.2312 56.9795,38.2699 57.0021,38.3093 56.9929,38.2312 56.9795)),((36.4989 58.7512,36.1498 58.553,34.9952 58.6226,35.3712 58.8556,36.4989 58.7512)),((36.4587 57.1544,36.1999 57.0022,34.4816 56.8232,34.8098 57.0409,36.0727 57.0915,35.0338 57.1875,35.4682 57.4674,36.1936 57.4998,35.613 57.5595,35.9179 57.7512,37.0097 57.4998,35.7705 57.2554,36.4587 57.1544)),((38.0535 58.0542,37.4026 58.3187,38.5813 58.7446,37.8553 58.9075,39.7299 59.9314,44.4751 59.81,44.4146 55.3097,40.0925 52.1652,38.3395 52.1652,39.1456 52.7573,39.5787 52.6996,39.2704 52.8471,39.9877 53.3534,40.0019 53.354,39.9942 53.358,43.0243 55.3269,43.0243 56.2614,40.2143 54.467,39.5485 54.5631,39.5485 54.8773,40.3948 54.8773,40.3948 55.2408,39.8205 55.2753,39.8151 55.3187,40.5504 55.7875,40.5761 55.7884,40.5716 55.8007,43.0243 57.2554,43.0243 58.0797,40.4543 56.5923,40.3343 56.9599,39.7903 56.9929,39.7863 57.025,42.5105 58.477,41.6944 58.8542,40.1389 58.048,39.6392 58.0478,39.6392 58.3427,39.7184 58.3823,40.3343 58.3821,40.4136 58.7241,41.2108 59.1035,40.6366 59.3817,39.8163 58.9766,38.5209 59.119,39.4085 58.7696,38.7465 58.4255,38.3698 58.2869,38.432 58.2584,38.0535 58.0542)),((34.4996 55.9565,33.5244 56.1686,33.7222 56.3063,34.5917 56.2949,35.0485 56.303,34.744 56.1118,34.7126 56.11,34.7331 56.1049,34.4996 55.9565)),((34.4996 55.9565,35.0954 55.822,34.9721 55.7463,34.2598 55.8023,34.4996 55.9565)),((31.6069 56.3194,31.5088 55.9411,31.7782 55.7778,30.2092 54.6331,30.2394 53.6774,31.7439 54.8677,31.4182 54.4227,31.8748 54.1736,29.3931 52.2763,29.4536 59.7796,30.5719 59.9919,30.4812 58.8542,32.3249 59.9465,33.6548 59.9465,30.179 57.9196,30.179 56.9764,32.2175 58.3664,32.1738 58.0318,31.5088 57.4998,31.6514 57.1258,30.3301 56.1942,30.2394 55.2753,31.6069 56.3194)),((31.6069 56.3194,31.7506 56.8609,31.6514 57.1258,34.0496 58.6717,34.9952 58.6226,34.6028 58.3749,33.6245 58.271,34.3593 58.2189,33.7581 57.8255,33.2316 57.7748,33.6325 57.7419,31.6069 56.3194)),((33.5244 56.1686,33.1204 55.8832,32.748 55.9072,32.9547 55.7645,31.7439 54.8677,31.8413 54.9989,32.204 55.5156,31.7782 55.7778,33.3418 56.8364,33.8361 56.6953,34.1885 56.6259,33.7222 56.3063,32.8387 56.3117,33.5244 56.1686)),((33.1204 55.8832,34.2598 55.8023,33.6125 55.3778,33.5036 55.3785,32.9547 55.7645,33.1204 55.8832)),((35.3188 55.9582,36.193 55.7319,35.9817 55.5958,35.1358 55.5327,35.7505 55.4454,35.2275 55.0993,34.8335 55.0162,34.9706 54.9262,34.7231 54.7576,34.2593 54.9642,35.0149 55.3613,34.3709 55.3709,34.9721 55.7463,35.6798 55.6863,35.0954 55.822,35.3188 55.9582)),((35.3188 55.9582,34.7331 56.1049,34.744 56.1118,35.6571 56.1619,35.3188 55.9582)),((33.3418 56.8364,32.9596 56.9434,33.5602 56.9781,33.3418 56.8364)),((33.4048 52.8423,34.7731 52.9188,34.7731 53.7847,34.7279 53.8116,34.9611 53.9765,35.3645 53.076,34.2895 52.2208,32.5969 52.2208,33.4048 52.8423)),((33.4048 52.8423,33.1712 52.8276,32.5275 53.1741,34.7231 54.7576,35.0753 54.5981,34.1081 54.1757,34.7279 53.8116,33.4048 52.8423)),((32.2523 53.964,32.476 53.8383,32.0831 53.408,32.5275 53.1741,31.2368 52.1652,29.7861 52.1466,32.2523 53.964)),((32.2523 53.964,31.8748 54.1736,33.6125 55.3778,34.3709 55.3709,32.2523 53.964)),((36.3552 53.8269,36.1528 53.6763,35.9216 53.8026,36.3552 53.8269)),((32.5691 58.5924,34.8637 59.9768,36.2843 59.9616,34.0496 58.6717,33.8361 58.6819,34.7428 59.5659,33.4734 58.8542,32.5691 58.5924)),((32.5691 58.5924,32.2175 58.3664,32.2342 58.4928,32.5691 58.5924)),((33.5602 56.9781,34.0208 57.2724,35.0338 57.1875,34.8098 57.0409,33.5602 56.9781)),((36.3932 58.0447,35.1134 57.9454,35.4314 58.1349,36.403 58.0507,36.3932 58.0447)),((35.1134 57.9454,34.6332 57.6538,33.6325 57.7419,33.7581 57.8255,35.1134 57.9454)),((35.4314 58.1349,34.3593 58.2189,34.6028 58.3749,36.0877 58.5174,35.4314 58.1349)),((35.4682 57.4674,34.2274 57.4023,34.6332 57.6538,35.613 57.5595,35.4682 57.4674)),((34.4816 56.8232,34.3867 56.7596,34.229 56.7948,34.4816 56.8232)),((34.1885 56.6259,34.3867 56.7596,35.4083 56.5254,35.2273 56.414,34.1885 56.6259)),((34.2274 57.4023,34.0208 57.2724,33.1712 57.337,34.2274 57.4023)),((35.0485 56.303,35.2273 56.414,35.71 56.3117,35.0485 56.303)),((35.6571 56.1619,36.0233 56.3789,36.7074 56.211,35.6571 56.1619)),((36.1498 58.553,36.3447 58.5402,36.0877 58.5174,36.1498 58.553)),((40.2143 54.467,40.3948 54.4403,40.6064 54.034,39.9716 53.9807,40.2437 53.5878,39.5485 53.5878,39.9942 53.358,39.9877 53.3534,38.5511 53.2922,40.2143 54.467)),((39.8102 56.1914,39.7903 56.4121,40.2529 56.4682,39.8102 56.1914)),((38.0214 52.8989,38.4609 53.226,39.2704 52.8471,39.1456 52.7573,38.0214 52.8989)),((38.5511 53.2922,38.4609 53.226,38.3395 53.2817,38.5511 53.2922)),((40.4543 56.5923,40.4855 56.4957,40.2529 56.4682,40.4543 56.5923)),((40.1389 58.048,40.2437 58.0478,40.3343 57.4673,39.7299 57.4673,39.7863 57.025,38.4339 56.2361,37.5054 56.5484,37.565 56.5843,38.9742 56.8774,38.4915 57.1308,40.1389 58.048)),((40.4136 58.7241,39.7184 58.3823,39.6392 58.3821,39.6392 58.3427,38.3737 57.6908,38.3395 57.7103,38.8533 58.0638,38.432 58.2584,38.7465 58.4255,39.5485 58.7133,39.4085 58.7696,39.8163 58.9766,40.4552 58.9011,40.4136 58.7241)),((38.3737 57.6908,38.7325 57.4835,38.2186 57.2717,38.4915 57.1308,38.2699 57.0021,37.4489 57.1909,37.9669 57.4734,38.128 57.516,38.0744 57.5312,38.3737 57.6908))) +-------- MultiPolygon with Polygon with Holes +MULTIPOLYGON(((24.3677 61.4598,26.6528 61.1008,26.8726 61.7107,30.564 61.0583,31.3989 62.0215,36.0132 61.1432,36.8921 62.0009,42.6489 60.6301,43.5718 61.3757,47.0435 59.8889,49.5923 60.0868,49.1528 58.1707,51.9214 57.9148,50.2515 56.1455,52.6685 55.826,51.6577 54.2909,52.8882 53.9302,50.647 53.0148,51.394 52.4828,48.0542 51.1793,49.2847 50.5414,47.1753 49.153,43.9233 49.8096,42.561 48.7779,36.936 49.6676,35.2661 48.7489,32.8052 49.5252,27.2241 48.9802,26.1255 50.4015,21.2036 50.205,20.0171 51.5634,17.4683 53.0148,19.4458 54.0852,19.4458 55.8753,19.5776 57.4922,19.5776 58.6769,24.3677 61.4598),(24.4556 59.4227,21.2036 58.4937,21.3354 56.897,21.5991 55.9246,25.2026 55.9984,28.8501 57.0646,27.0923 57.8448,28.8062 59.1759,26.2573 59.1759,24.4556 59.4227),(35.1489 56.5859,36.7074 56.211,34.7126 56.11,36.5563 55.6352,35.1358 55.5327,36.4354 55.3441,34.8335 55.0162,35.6193 54.4929,34.894 54.1226,35.3776 53.0462,37.0604 52.9744,34.9585 51.4814,36.5405 50.4015,39.6606 50.2893,39.7925 52.1335,41.77 50.6808,44.4946 51.9713,47.3071 52.5095,44.0552 53.5403,46.604 53.6967,47.6147 55.4041,45.3735 55.4041,42.8247 56.5837,40.4412 56.1511,40.425 56.1942,39.8205 56.0763,39.7903 56.4121,40.4855 56.4957,40.3343 56.9599,39.7903 56.9929,39.7379 57.4051,40.0149 57.4677,40.3343 57.4673,40.3237 57.5365,42.6929 58.0314,40.8911 59.2659,39.2792 59.0373,38.5209 59.119,38.8838 58.9777,38.0944 58.8545,37.3119 59.0258,37.2327 59.0233,37.1118 59.6677,35.1343 59.8448,31.9702 58.9727,32.25 58.4976,32.2342 58.4928,32.1738 58.0318,31.5088 57.4998,31.7506 56.8609,31.5088 55.9411,32.204 55.5156,31.8413 54.9989,31.627 54.7093,29.5972 55.5037,29.1577 55.7518,22.5659 55.1286,22.5659 53.5403,22.0386 51.4814,26.2573 51.4266,30.1245 50.5414,32.1899 51.1793,30.1245 53.1731,32.4808 53.1989,33.1712 52.8276,34.7731 52.9188,34.7731 53.1793,35.0903 53.1731,34.7731 53.3243,34.7731 53.7847,34.1081 54.1757,35.0753 54.5981,34.2593 54.9642,35.0149 55.3613,33.5036 55.3785,32.748 55.9072,35.6798 55.6863,32.8387 56.3117,34.5917 56.2949,35.71 56.3117,33.8361 56.6953,33.7182 56.7292,35.1489 56.5859)),((35.1489 56.5859,34.229 56.7948,36.9794 57.0751,35.7705 57.2554,37.0097 57.4998,35.7402 57.7909,37.1608 58.0478,36.0123 58.2869,37.191 58.6819,34.6522 58.9167,37.2327 59.0233,37.2876 58.7226,38.0944 58.8545,38.5813 58.7446,37.4026 58.3187,38.3395 57.9356,37.4328 57.7103,38.128 57.516,37.1608 57.2554,38.3092 56.9929,38.309 56.9928,36.375 56.6455,36.8799 56.4895,36.6724 56.4139,35.1489 56.5859)),((33.1079 56.9523,32.25 58.4976,33.4734 58.8542,34.7428 59.5659,33.8361 58.6819,36.3447 58.5402,33.6245 58.271,36.4354 58.0478,33.2316 57.7748,36.1936 57.4998,33.1712 57.337,36.0727 57.0915,33.1079 56.9523)),((33.1079 56.9523,33.1392 56.8934,32.9596 56.9434,33.1079 56.9523)),((33.7182 56.7292,33.2007 56.7768,33.1392 56.8934,33.7182 56.7292)),((37.0604 52.9744,37.2165 53.0798,37.4328 52.9552,37.0604 52.9744)),((34.7731 53.3243,34.7731 53.1793,32.4808 53.1989,32.0831 53.408,32.476 53.8383,31.4182 54.4227,31.627 54.7093,33.1128 54.0852,34.7731 53.3243)),((36.9508 55.414,37.7653 55.1891,36.8822 54.975,36.5845 55.3291,36.9508 55.414)),((36.9508 55.414,36.8283 55.4471,37.9482 55.6376,36.9508 55.414)),((37.2165 53.0798,35.9216 53.8026,36.919 53.8561,36.0123 54.7554,36.8822 54.975,37.0572 54.7635,36.7074 54.6506,37.3119 53.9273,36.9794 53.5878,37.4471 53.2343,37.2165 53.0798)),((37.0572 54.7635,38.3093 55.1546,37.7955 55.3956,38.4907 55.5327,38.3184 55.7179,40.4412 56.1511,40.5761 55.7884,39.7601 55.7544,39.8205 55.2753,40.3948 55.2408,40.3948 54.8773,39.5485 54.8773,39.5485 54.5631,40.3948 54.4403,40.6064 54.034,39.9716 53.9807,40.2437 53.5878,39.5485 53.5878,40.0019 53.354,38.3395 53.2817,39.5787 52.6996,37.8559 52.9188,37.4471 53.2343,37.9907 53.5925,37.0572 54.7635)),((38.5798 57.0849,38.2186 57.2717,38.7325 57.4835,38.3395 57.7103,38.8533 58.0638,38.3698 58.2869,39.5485 58.7133,38.8838 58.9777,39.2792 59.0373,40.4552 58.9011,40.3343 58.3821,39.6392 58.3821,39.6392 58.0478,40.2437 58.0478,40.3237 57.5365,40.0149 57.4677,39.7299 57.4673,39.7379 57.4051,39.0894 57.2553,38.5798 57.0849)),((38.5798 57.0849,38.9742 56.8774,37.463 56.5623,38.944 56.0594,38.1884 55.8564,38.3184 55.7179,38.0262 55.6546,36.647 55.9411,38.2186 56.0594,36.8799 56.4895,38.309 56.9928,38.3093 56.9929,38.3092 56.9929,38.5798 57.0849)),((37.9482 55.6376,38.0262 55.6546,38.0373 55.6523,37.9482 55.6376))) +-------- Polygon with Polygon with Holes +MULTIPOLYGON(((24.3677 61.4598,26.6528 61.1008,26.8726 61.7107,30.564 61.0583,31.3989 62.0215,36.0132 61.1432,36.8921 62.0009,42.6489 60.6301,43.5718 61.3757,47.0435 59.8889,49.5923 60.0868,49.1528 58.1707,51.9214 57.9148,50.2515 56.1455,52.6685 55.826,51.6577 54.2909,52.8882 53.9302,50.647 53.0148,51.394 52.4828,48.0542 51.1793,49.2847 50.5414,47.1753 49.153,43.9233 49.8096,42.561 48.7779,36.936 49.6676,35.2661 48.7489,32.8052 49.5252,27.2241 48.9802,26.1255 50.4015,21.2036 50.205,20.0171 51.5634,17.4683 53.0148,19.4458 54.0852,19.4458 55.8753,19.5776 57.4922,19.5776 58.6769,24.3677 61.4598),(24.4556 59.4227,21.2036 58.4937,21.3354 56.897,21.5991 55.9246,25.2026 55.9984,28.8501 57.0646,27.0923 57.8448,28.8062 59.1759,26.2573 59.1759,24.4556 59.4227),(35.9475 59.7758,36.2843 59.9616,34.8637 59.9768,34.2247 59.6064,31.9702 58.9727,32.2964 58.4175,30.179 56.9764,30.179 57.9196,33.6548 59.9465,32.3249 59.9465,30.4812 58.8542,30.5719 59.9919,29.4536 59.7796,29.4171 55.606,29.1577 55.7518,22.5659 55.1286,22.5659 53.5403,22.0386 51.4814,26.2573 51.4266,30.1245 50.5414,32.1899 51.1793,31.1968 52.1649,31.2368 52.1652,32.5603 53.1989,33.8733 53.1922,32.5969 52.2208,34.2895 52.2208,37.2766 54.4948,37.7431 53.9104,35.4682 52.2022,35.9681 52.2157,34.9585 51.4814,36.5405 50.4015,39.6606 50.2893,39.7925 52.1335,41.77 50.6808,44.4946 51.9713,47.3071 52.5095,44.0552 53.5403,46.604 53.6967,47.6147 55.4041,45.3735 55.4041,44.4212 55.8594,44.4751 59.81,39.7299 59.9314,37.6322 58.7797,37.2876 58.7226,37.2102 59.1452,38.7325 59.9465,37.2817 59.9768,36.7912 59.6986,35.9475 59.7758)),((32.6512 57.792,32.2964 58.4175,34.2247 59.6064,35.1343 59.8448,35.9475 59.7758,32.6512 57.792)),((32.6512 57.792,32.9378 57.2699,30.2394 55.2753,30.3301 56.1942,32.6512 57.792)),((33.2446 56.7729,33.2007 56.7768,32.9378 57.2699,36.7912 59.6986,37.1118 59.6677,37.2102 59.1452,33.2446 56.7729)),((33.2446 56.7729,34.2635 56.6767,31.5682 54.7333,30.7705 55.0525,33.2446 56.7729)),((34.2635 56.6767,37.6322 58.7797,40.2079 59.1718,35.4536 56.5531,34.2635 56.6767)),((40.2079 59.1718,40.6366 59.3817,40.8804 59.2644,40.2079 59.1718)),((34.3351 53.53,35.0903 53.1731,33.8733 53.1922,34.3351 53.53)),((34.3351 53.53,33.5144 53.9057,38.1759 56.9472,39.0894 57.2553,40.9691 57.677,37.1934 55.4694,36.5845 55.3291,36.7219 55.1665,34.3351 53.53)),((32.6907 54.2663,33.1128 54.0852,33.5144 53.9057,32.5603 53.1989,31.1682 53.1903,32.6907 54.2663)),((32.6907 54.2663,32.2591 54.4483,35.4536 56.5531,36.1815 56.4715,32.6907 54.2663)),((38.1759 56.9472,36.6724 56.4139,36.1815 56.4715,41.168 59.0834,41.5887 58.8012,38.1759 56.9472)),((37.2766 54.4948,36.7219 55.1665,37.1934 55.4694,39.4328 55.9511,37.2766 54.4948)),((40.9691 57.677,42.2498 58.3455,42.6929 58.0314,40.9691 57.677)),((30.7705 55.0525,30.2092 54.6331,30.2394 53.6774,31.5682 54.7333,32.2591 54.4483,30.5408 53.1811,30.1245 53.1731,30.3098 53.0028,29.3931 52.2763,29.4171 55.606,29.5972 55.5037,30.7705 55.0525)),((30.5408 53.1811,31.1682 53.1903,30.5785 52.7531,30.3098 53.0028,30.5408 53.1811)),((30.5785 52.7531,31.1968 52.1649,29.7861 52.1466,30.5785 52.7531)),((35.9681 52.2157,37.9907 53.5925,37.7431 53.9104,41.4519 56.3413,42.8247 56.5837,44.4212 55.8594,44.4146 55.3097,40.0925 52.1652,38.3395 52.1652,43.0243 55.3269,43.0243 56.2614,37.1608 52.2393,35.9681 52.2157)),((39.4328 55.9511,43.0243 58.0797,43.0243 57.2554,41.4519 56.3413,39.4328 55.9511)),((41.168 59.0834,40.9299 59.2404,41.2108 59.1035,41.168 59.0834)),((41.5887 58.8012,41.6944 58.8542,42.5105 58.477,42.2498 58.3455,41.5887 58.8012)),((40.9299 59.2404,40.8804 59.2644,40.8911 59.2659,40.9299 59.2404))) diff --git a/tests/queries/0_stateless/01304_polygons_sym_difference.sql b/tests/queries/0_stateless/01304_polygons_sym_difference.sql new file mode 100644 index 00000000000..f4893dd5b33 --- /dev/null +++ b/tests/queries/0_stateless/01304_polygons_sym_difference.sql @@ -0,0 +1,10 @@ +select polygonsSymDifferenceCartesian([[[(0, 0),(0, 3),(1, 2.9),(2, 2.6),(2.6, 2),(2.9, 1),(3, 0),(0, 0)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); + +select '-------- MultiPolygon with Polygon'; +select wkt(polygonsSymDifferenceSpherical([[(29.453587685533865,59.779570356240356),(29.393139070478895,52.276266797422124),(40.636581470703206,59.38168915000267),(41.21084331372543,59.103467777099866),(29.786055068336193,52.146627480315004),(31.23682182965546,52.16517054781818),(41.69443223416517,58.85424941916091),(42.51048853740727,58.47703162291134),(32.59691566839227,52.22075341251539),(34.289476889931414,52.22075341251539),(43.02430176537451,58.07974369546071),(43.02430176537451,57.25537683364851),(35.468224883503325,52.2022335126388),(37.16078610504247,52.23926559241349),(43.02430176537451,56.26136189644947),(43.02430176537451,55.326904361850836),(38.33953409861437,52.16517054781818),(40.09254393520848,52.16517054781818),(44.4146199116388,55.3097062225408),(44.47506852669377,59.80998197603594),(39.72985224487867,59.931351417569715),(30.23941968124846,53.67744677450975),(30.20919537372098,54.63314259659509),(38.73245009647167,59.94649146557819),(37.2816833351524,59.97675082987618),(30.23941968124846,55.2752875586599),(30.33009260383092,56.19415599955667),(36.28428118674541,59.96162460231375),(34.863738732953635,59.97675082987618),(30.178971066193498,56.97640788219866),(30.178971066193498,57.91957806959033),(33.65476643185424,59.94649146557819),(32.32489690064491,59.94649146557819),(30.481214141468342,58.85424941916091),(30.571887064050795,59.99187015036608),(29.453587685533865,59.779570356240356)]], [[[(33.473420586689336,58.85424941916091),(32.23422397806246,58.492830557036),(32.173775363007486,58.03176922751564),(31.508840597402823,57.499784781503735),(31.750635057622702,56.86092686957355),(31.508840597402823,55.941082594334574),(32.20399967053497,55.515591939372456),(31.84130798020516,54.998862226280465),(31.418167674820367,54.422670886434275),(32.47601843828233,53.83826377018255),(32.08310244042503,53.408048308050866),(33.171177511414484,52.82758702113742),(34.77306581037117,52.91880107773494),(34.77306581037117,53.784726518357985),(34.108131044766516,54.17574726780569),(35.07530888564602,54.59813930694554),(34.25925258240394,54.96417435716029),(35.01486027059106,55.361278263643584),(33.50364489421682,55.37845402950552),(32.7480372060297,55.90721384574556),(35.67979503619571,55.68634475630185),(32.83871012861215,56.311688992608396),(34.591719965206266,56.29492065473883),(35.7100193437232,56.311688992608396),(33.83611227701915,56.695333481003644),(32.95960735872209,56.9434497616887),(36.072711034053015,57.091531913901434),(33.171177511414484,57.33702717078384),(36.193608264162954,57.499784781503735),(33.23162612646945,57.77481561306047),(36.43540272438284,58.04776787540811),(33.62454212432676,58.27099811968307),(36.344729801800376,58.54018474404165),(33.83611227701915,58.68186423448108),(34.74284150284369,59.565911441555244),(33.473420586689336,58.85424941916091)]], [[(34.65216858026123,58.91672306881671),(37.19101041256995,58.68186423448108),(36.01226241899805,58.28688958537609),(37.16078610504247,58.04776787540811),(35.74024365125068,57.79092907387934),(37.009664567405046,57.499784781503735),(35.77046795877817,57.25537683364851),(36.979440259877556,57.07510745541089),(34.22902827487645,56.794777197297435),(36.7074214921302,56.210968525786996),(34.712617195316206,56.10998276812964),(36.55629995449277,55.63519693782703),(35.13575750070099,55.53270067649592),(36.43540272438284,55.34409504165558),(34.83351442542614,55.01619492319591),(35.61934642114075,54.49294870011772),(34.89396304048112,54.12264226523038),(35.37755196092087,53.046178687628185),(37.43280487278982,52.95523300597458),(35.92158949641559,53.80257986695776),(36.91899164482259,53.856094327816805),(36.01226241899805,54.75541714463799),(37.765272255592166,55.189110239786885),(36.828318722240134,55.44708256557195),(38.03729102333953,55.652253637168315),(36.64697287707522,55.941082594334574),(38.21863686850443,56.05939028508024),(36.37495410932787,56.64551287174558),(38.30930979108689,56.992876013526654),(37.16078610504247,57.25537683364851),(38.127963945921984,57.516020773674256),(37.43280487278982,57.710289827306724),(38.33953409861437,57.935626886818994),(37.40258056526235,58.31865112960426),(38.58132855883426,58.744648733419496),(37.31190764267989,59.02578062465136),(34.65216858026123,58.91672306881671)]], [[(38.52087994377928,59.11898412389468),(39.54850639971376,58.713270635642914),(38.369758406141855,58.28688958537609),(38.85334732658162,58.06375936407028),(38.33953409861437,57.710289827306724),(38.73245009647167,57.48354156434209),(38.21863686850443,57.271721400459285),(38.97424455669155,56.87744603722649),(37.463029180317314,56.5623320541159),(38.94402024916407,56.05939028508024),(38.18841256097694,55.856355210835915),(38.490655636251795,55.53270067649592),(37.795496563119656,55.39562234093384),(38.30930979108689,55.154587013355666),(36.7074214921302,54.65063295250911),(37.31190764267989,53.92734063371401),(36.979440259877556,53.58783775557231),(37.855945178174615,52.91880107773497),(39.57873070724124,52.69956490610895),(38.33953409861437,53.281741738901104),(40.00187101262603,53.35396273604752),(39.54850639971376,53.58783775557231),(40.24366547284591,53.58783775557231),(39.97164670509855,53.98069568468355),(40.60635716317572,54.03398248547225),(40.39478701048334,54.44025165268903),(39.54850639971376,54.56310590284329),(39.54850639971376,54.87732350170489),(40.39478701048334,54.87732350170489),(40.39478701048334,55.24083903654295),(39.82052516746112,55.2752875586599),(39.760076552406154,55.75443792473942),(40.57613285564824,55.78844000174894),(40.425011318010824,56.19415599955667),(39.82052516746112,56.07626182891758),(39.79030085993364,56.41214455508424),(40.48545993306579,56.495655446714636),(40.33433839542836,56.95993246553937),(39.79030085993364,56.992876013526654),(39.72985224487867,57.46729112028032),(40.33433839542836,57.46729112028032),(40.24366547284591,58.04776787540811),(39.63917932229622,58.04776787540811),(39.63917932229622,58.382088724871295),(40.33433839542836,58.382088724871295),(40.45523562553831,58.9011152358548),(38.52087994377928,59.11898412389468)]]])) format TSV; + +select '-------- MultiPolygon with Polygon with Holes'; +select wkt(polygonsSymDifferenceSpherical([[[(33.473420586689336,58.85424941916091),(32.23422397806246,58.492830557036),(32.173775363007486,58.03176922751564),(31.508840597402823,57.499784781503735),(31.750635057622702,56.86092686957355),(31.508840597402823,55.941082594334574),(32.20399967053497,55.515591939372456),(31.84130798020516,54.998862226280465),(31.418167674820367,54.422670886434275),(32.47601843828233,53.83826377018255),(32.08310244042503,53.408048308050866),(33.171177511414484,52.82758702113742),(34.77306581037117,52.91880107773494),(34.77306581037117,53.784726518357985),(34.108131044766516,54.17574726780569),(35.07530888564602,54.59813930694554),(34.25925258240394,54.96417435716029),(35.01486027059106,55.361278263643584),(33.50364489421682,55.37845402950552),(32.7480372060297,55.90721384574556),(35.67979503619571,55.68634475630185),(32.83871012861215,56.311688992608396),(34.591719965206266,56.29492065473883),(35.7100193437232,56.311688992608396),(33.83611227701915,56.695333481003644),(32.95960735872209,56.9434497616887),(36.072711034053015,57.091531913901434),(33.171177511414484,57.33702717078384),(36.193608264162954,57.499784781503735),(33.23162612646945,57.77481561306047),(36.43540272438284,58.04776787540811),(33.62454212432676,58.27099811968307),(36.344729801800376,58.54018474404165),(33.83611227701915,58.68186423448108),(34.74284150284369,59.565911441555244),(33.473420586689336,58.85424941916091)]], [[(34.65216858026123,58.91672306881671),(37.19101041256995,58.68186423448108),(36.01226241899805,58.28688958537609),(37.16078610504247,58.04776787540811),(35.74024365125068,57.79092907387934),(37.009664567405046,57.499784781503735),(35.77046795877817,57.25537683364851),(36.979440259877556,57.07510745541089),(34.22902827487645,56.794777197297435),(36.7074214921302,56.210968525786996),(34.712617195316206,56.10998276812964),(36.55629995449277,55.63519693782703),(35.13575750070099,55.53270067649592),(36.43540272438284,55.34409504165558),(34.83351442542614,55.01619492319591),(35.61934642114075,54.49294870011772),(34.89396304048112,54.12264226523038),(35.37755196092087,53.046178687628185),(37.43280487278982,52.95523300597458),(35.92158949641559,53.80257986695776),(36.91899164482259,53.856094327816805),(36.01226241899805,54.75541714463799),(37.765272255592166,55.189110239786885),(36.828318722240134,55.44708256557195),(38.03729102333953,55.652253637168315),(36.64697287707522,55.941082594334574),(38.21863686850443,56.05939028508024),(36.37495410932787,56.64551287174558),(38.30930979108689,56.992876013526654),(37.16078610504247,57.25537683364851),(38.127963945921984,57.516020773674256),(37.43280487278982,57.710289827306724),(38.33953409861437,57.935626886818994),(37.40258056526235,58.31865112960426),(38.58132855883426,58.744648733419496),(37.31190764267989,59.02578062465136),(34.65216858026123,58.91672306881671)]], [[(38.52087994377928,59.11898412389468),(39.54850639971376,58.713270635642914),(38.369758406141855,58.28688958537609),(38.85334732658162,58.06375936407028),(38.33953409861437,57.710289827306724),(38.73245009647167,57.48354156434209),(38.21863686850443,57.271721400459285),(38.97424455669155,56.87744603722649),(37.463029180317314,56.5623320541159),(38.94402024916407,56.05939028508024),(38.18841256097694,55.856355210835915),(38.490655636251795,55.53270067649592),(37.795496563119656,55.39562234093384),(38.30930979108689,55.154587013355666),(36.7074214921302,54.65063295250911),(37.31190764267989,53.92734063371401),(36.979440259877556,53.58783775557231),(37.855945178174615,52.91880107773497),(39.57873070724124,52.69956490610895),(38.33953409861437,53.281741738901104),(40.00187101262603,53.35396273604752),(39.54850639971376,53.58783775557231),(40.24366547284591,53.58783775557231),(39.97164670509855,53.98069568468355),(40.60635716317572,54.03398248547225),(40.39478701048334,54.44025165268903),(39.54850639971376,54.56310590284329),(39.54850639971376,54.87732350170489),(40.39478701048334,54.87732350170489),(40.39478701048334,55.24083903654295),(39.82052516746112,55.2752875586599),(39.760076552406154,55.75443792473942),(40.57613285564824,55.78844000174894),(40.425011318010824,56.19415599955667),(39.82052516746112,56.07626182891758),(39.79030085993364,56.41214455508424),(40.48545993306579,56.495655446714636),(40.33433839542836,56.95993246553937),(39.79030085993364,56.992876013526654),(39.72985224487867,57.46729112028032),(40.33433839542836,57.46729112028032),(40.24366547284591,58.04776787540811),(39.63917932229622,58.04776787540811),(39.63917932229622,58.382088724871295),(40.33433839542836,58.382088724871295),(40.45523562553831,58.9011152358548),(38.52087994377928,59.11898412389468)]]], [[(24.367675781249993,61.45977057029751),(19.577636718749993,58.67693767258692),(19.577636718749993,57.492213666700735),(19.445800781249996,55.87531083569678),(19.445800781249996,54.085173420886775),(17.468261718749996,53.014783245859235),(20.017089843749993,51.563412328675895),(21.203613281249993,50.205033264943324),(26.125488281249993,50.40151532278236),(27.22412109374999,48.980216985374994),(32.80517578124999,49.525208341974405),(35.26611328124999,48.74894534343292),(36.93603515624999,49.66762782262194),(42.56103515625,48.77791275550183),(43.92333984374999,49.8096315635631),(47.17529296875,49.152969656170455),(49.28466796875,50.54136296522162),(48.05419921875,51.17934297928929),(51.39404296875,52.48278022207825),(50.64697265625,53.014783245859235),(52.88818359375,53.93021986394004),(51.65771484374999,54.29088164657006),(52.66845703125,55.825973254619015),(50.25146484375,56.145549500679095),(51.92138671875,57.914847767009206),(49.15283203125,58.17070248348605),(49.59228515625,60.086762746260064),(47.043457031249986,59.88893689676584),(43.57177734375,61.37567331572748),(42.64892578125,60.630101766266705),(36.89208984374999,62.000904713685856),(36.01318359374999,61.143235250840576),(31.398925781249993,62.02152819100766),(30.563964843749996,61.05828537037917),(26.872558593749993,61.71070595883174),(26.652832031249993,61.10078883158897),(24.367675781249993,61.45977057029751)], [(24.455566406249993,59.42272750081452),(21.203613281249993,58.49369382056807),(21.335449218749993,56.89700392127261),(21.599121093749993,55.92458580482949),(25.202636718749993,55.998380955359636),(28.850097656249993,57.06463027327854),(27.09228515625,57.844750992890994),(28.806152343749996,59.17592824927138),(26.257324218749993,59.17592824927138),(24.455566406249993,59.42272750081452)], [(35.13427734375,59.84481485969107),(31.970214843749993,58.97266715450152),(33.20068359374999,56.776808316568406),(36.67236328125,56.41390137600675),(39.08935546874999,57.25528054528888),(42.69287109374999,58.03137242177638),(40.89111328124999,59.26588062825809),(37.28759765625,58.722598828043374),(37.11181640624999,59.66774058164964),(35.13427734375,59.84481485969107)], [(29.157714843749993,55.75184939173528),(22.565917968749993,55.128649068488784),(22.565917968749993,53.54030739150019),(22.038574218749996,51.48138289610097),(26.257324218749993,51.42661449707484),(30.124511718749993,50.54136296522162),(32.18994140624999,51.17934297928929),(30.124511718749993,53.173119202640635),(35.09033203124999,53.173119202640635),(33.11279296875,54.085173420886775),(29.597167968749993,55.50374985927513),(29.157714843749993,55.75184939173528)], [(42.82470703125,56.58369172128337),(36.584472656249986,55.329144408405085),(37.99072265625,53.592504809039355),(34.95849609374999,51.48138289610097),(36.54052734374999,50.40151532278236),(39.66064453124999,50.289339253291786),(39.79248046875,52.13348804077148),(41.77001953125,50.68079714532166),(44.49462890624999,51.97134580885171),(47.30712890624999,52.509534770327264),(44.05517578125,53.54030739150019),(46.60400390625,53.696706475303245),(47.61474609375,55.40406982700608),(45.37353515625,55.40406982700608),(42.82470703125,56.58369172128337)]])) format TSV; + +select '-------- Polygon with Polygon with Holes'; +select wkt(polygonsSymDifferenceSpherical([[(29.453587685533865,59.779570356240356),(29.393139070478895,52.276266797422124),(40.636581470703206,59.38168915000267),(41.21084331372543,59.103467777099866),(29.786055068336193,52.146627480315004),(31.23682182965546,52.16517054781818),(41.69443223416517,58.85424941916091),(42.51048853740727,58.47703162291134),(32.59691566839227,52.22075341251539),(34.289476889931414,52.22075341251539),(43.02430176537451,58.07974369546071),(43.02430176537451,57.25537683364851),(35.468224883503325,52.2022335126388),(37.16078610504247,52.23926559241349),(43.02430176537451,56.26136189644947),(43.02430176537451,55.326904361850836),(38.33953409861437,52.16517054781818),(40.09254393520848,52.16517054781818),(44.4146199116388,55.3097062225408),(44.47506852669377,59.80998197603594),(39.72985224487867,59.931351417569715),(30.23941968124846,53.67744677450975),(30.20919537372098,54.63314259659509),(38.73245009647167,59.94649146557819),(37.2816833351524,59.97675082987618),(30.23941968124846,55.2752875586599),(30.33009260383092,56.19415599955667),(36.28428118674541,59.96162460231375),(34.863738732953635,59.97675082987618),(30.178971066193498,56.97640788219866),(30.178971066193498,57.91957806959033),(33.65476643185424,59.94649146557819),(32.32489690064491,59.94649146557819),(30.481214141468342,58.85424941916091),(30.571887064050795,59.99187015036608),(29.453587685533865,59.779570356240356)]], [[(24.367675781249993,61.45977057029751),(19.577636718749993,58.67693767258692),(19.577636718749993,57.492213666700735),(19.445800781249996,55.87531083569678),(19.445800781249996,54.085173420886775),(17.468261718749996,53.014783245859235),(20.017089843749993,51.563412328675895),(21.203613281249993,50.205033264943324),(26.125488281249993,50.40151532278236),(27.22412109374999,48.980216985374994),(32.80517578124999,49.525208341974405),(35.26611328124999,48.74894534343292),(36.93603515624999,49.66762782262194),(42.56103515625,48.77791275550183),(43.92333984374999,49.8096315635631),(47.17529296875,49.152969656170455),(49.28466796875,50.54136296522162),(48.05419921875,51.17934297928929),(51.39404296875,52.48278022207825),(50.64697265625,53.014783245859235),(52.88818359375,53.93021986394004),(51.65771484374999,54.29088164657006),(52.66845703125,55.825973254619015),(50.25146484375,56.145549500679095),(51.92138671875,57.914847767009206),(49.15283203125,58.17070248348605),(49.59228515625,60.086762746260064),(47.043457031249986,59.88893689676584),(43.57177734375,61.37567331572748),(42.64892578125,60.630101766266705),(36.89208984374999,62.000904713685856),(36.01318359374999,61.143235250840576),(31.398925781249993,62.02152819100766),(30.563964843749996,61.05828537037917),(26.872558593749993,61.71070595883174),(26.652832031249993,61.10078883158897),(24.367675781249993,61.45977057029751)], [(24.455566406249993,59.42272750081452),(21.203613281249993,58.49369382056807),(21.335449218749993,56.89700392127261),(21.599121093749993,55.92458580482949),(25.202636718749993,55.998380955359636),(28.850097656249993,57.06463027327854),(27.09228515625,57.844750992890994),(28.806152343749996,59.17592824927138),(26.257324218749993,59.17592824927138),(24.455566406249993,59.42272750081452)], [(35.13427734375,59.84481485969107),(31.970214843749993,58.97266715450152),(33.20068359374999,56.776808316568406),(36.67236328125,56.41390137600675),(39.08935546874999,57.25528054528888),(42.69287109374999,58.03137242177638),(40.89111328124999,59.26588062825809),(37.28759765625,58.722598828043374),(37.11181640624999,59.66774058164964),(35.13427734375,59.84481485969107)], [(29.157714843749993,55.75184939173528),(22.565917968749993,55.128649068488784),(22.565917968749993,53.54030739150019),(22.038574218749996,51.48138289610097),(26.257324218749993,51.42661449707484),(30.124511718749993,50.54136296522162),(32.18994140624999,51.17934297928929),(30.124511718749993,53.173119202640635),(35.09033203124999,53.173119202640635),(33.11279296875,54.085173420886775),(29.597167968749993,55.50374985927513),(29.157714843749993,55.75184939173528)], [(42.82470703125,56.58369172128337),(36.584472656249986,55.329144408405085),(37.99072265625,53.592504809039355),(34.95849609374999,51.48138289610097),(36.54052734374999,50.40151532278236),(39.66064453124999,50.289339253291786),(39.79248046875,52.13348804077148),(41.77001953125,50.68079714532166),(44.49462890624999,51.97134580885171),(47.30712890624999,52.509534770327264),(44.05517578125,53.54030739150019),(46.60400390625,53.696706475303245),(47.61474609375,55.40406982700608),(45.37353515625,55.40406982700608),(42.82470703125,56.58369172128337)]])) format TSV; diff --git a/tests/queries/0_stateless/01305_polygons_union.reference b/tests/queries/0_stateless/01305_polygons_union.reference new file mode 100644 index 00000000000..f87d03c151c --- /dev/null +++ b/tests/queries/0_stateless/01305_polygons_union.reference @@ -0,0 +1,8 @@ +[[[(1,2.9),(1,4),(4,4),(4,1),(2.9,1),(3,0),(0,0),(0,3),(1,2.9)]]] +[[[(4.3666052904432435,50.84337386140151),(4.366227,50.840809),(4.344961,50.833264),(4.338074,50.848677),(4.346693,50.858306),(4.3526804582393535,50.856658100365976),(4.3613577,50.8651821),(4.3613148,50.8651279),(4.3904543,50.8564867),(4.3830299,50.8428851),(4.3666052904432435,50.84337386140151)]]] +-------- MultiPolygon with Polygon +MULTIPOLYGON(((35.5408 58.9593,37.2817 59.9768,38.7325 59.9465,36.9725 59.0149,37.3119 59.0258,37.8553 58.9075,39.7299 59.9314,44.4751 59.81,44.4146 55.3097,40.0925 52.1652,38.3395 52.1652,39.1456 52.7573,38.0214 52.8989,37.1608 52.2393,35.4682 52.2022,36.5022 53.0008,35.3776 53.0462,35.3645 53.076,34.2895 52.2208,32.5969 52.2208,33.4048 52.8423,33.1712 52.8276,32.5275 53.1741,31.2368 52.1652,29.7861 52.1466,32.2523 53.964,31.8748 54.1736,29.3931 52.2763,29.4536 59.7796,30.5719 59.9919,30.4812 58.8542,32.3249 59.9465,33.6548 59.9465,30.179 57.9196,30.179 56.9764,32.2175 58.3664,32.2342 58.4928,32.5691 58.5924,34.8637 59.9768,36.2843 59.9616,34.0496 58.6717,34.9952 58.6226,35.3712 58.8556,34.6522 58.9167,35.5408 58.9593),(36.4989 58.7512,36.1498 58.553,36.3447 58.5402,36.0877 58.5174,35.4314 58.1349,36.403 58.0507,36.5949 58.1673,36.0123 58.2869,37.191 58.6819,36.4989 58.7512),(34.4816 56.8232,34.8098 57.0409,33.5602 56.9781,33.3418 56.8364,33.8361 56.6953,34.1885 56.6259,34.3867 56.7596,34.229 56.7948,34.4816 56.8232),(35.9179 57.7512,35.7402 57.7909,36.0848 57.855,36.3932 58.0447,35.1134 57.9454,34.6332 57.6538,35.613 57.5595,35.9179 57.7512),(36.8709 53.2765,37.135 53.4711,36.9794 53.5878,37.3119 53.9273,37.0035 54.2999,36.6985 54.0791,36.919 53.8561,36.3552 53.8269,36.1528 53.6763,36.8709 53.2765),(38.1601 55.1091,38.3093 55.1546,38.2609 55.1775,38.1601 55.1091),(38.1688 56.0758,38.4339 56.2361,37.5054 56.5484,37.2281 56.3799,38.1688 56.0758),(38.1319 56.0534,36.647 55.9411,37.6238 55.7402,38.1319 56.0534),(37.2824 55.5258,36.8283 55.4471,37.06 55.3843,37.2824 55.5258),(36.151 54.791,36.0123 54.7554,36.0472 54.7217,36.151 54.791),(34.9611 53.9765,34.894 54.1226,35.6193 54.4929,34.9706 54.9262,34.7231 54.7576,35.0753 54.5981,34.1081 54.1757,34.7279 53.8116,34.9611 53.9765),(38.2312 56.9795,37.565 56.5843,38.9742 56.8774,38.4915 57.1308,38.2699 57.0021,38.3093 56.9929,38.2312 56.9795),(36.5334 56.6753,36.375 56.6455,36.4446 56.6242,36.5334 56.6753),(36.1999 57.0022,36.9794 57.0751,36.4587 57.1544,36.1999 57.0022),(34.6028 58.3749,33.6245 58.271,34.3593 58.2189,34.6028 58.3749),(33.7581 57.8255,33.2316 57.7748,33.6325 57.7419,33.7581 57.8255),(31.6069 56.3194,31.7506 56.8609,31.6514 57.1258,30.3301 56.1942,30.2394 55.2753,31.6069 56.3194),(34.2274 57.4023,34.0208 57.2724,35.0338 57.1875,35.4682 57.4674,34.2274 57.4023),(31.7782 55.7778,30.2092 54.6331,30.2394 53.6774,31.7439 54.8677,31.8413 54.9989,32.204 55.5156,31.7782 55.7778),(33.7222 56.3063,32.8387 56.3117,33.5244 56.1686,33.7222 56.3063),(33.1204 55.8832,32.748 55.9072,32.9547 55.7645,33.1204 55.8832),(35.2275 55.0993,36.4354 55.3441,35.7505 55.4454,35.2275 55.0993),(35.9817 55.5958,36.5563 55.6352,36.193 55.7319,35.9817 55.5958),(35.0954 55.822,35.3188 55.9582,34.7331 56.1049,34.4996 55.9565,35.0954 55.822),(34.9721 55.7463,34.2598 55.8023,33.6125 55.3778,34.3709 55.3709,34.9721 55.7463),(35.6571 56.1619,36.0233 56.3789,35.4083 56.5254,35.2273 56.414,35.71 56.3117,35.0485 56.303,34.744 56.1118,35.6571 56.1619),(40.2143 54.467,40.3948 54.4403,40.6064 54.034,39.9716 53.9807,40.2437 53.5878,39.5485 53.5878,39.9942 53.358,43.0243 55.3269,43.0243 56.2614,40.2143 54.467),(38.5511 53.2922,38.4609 53.226,39.2704 52.8471,39.9877 53.3534,38.5511 53.2922),(40.5716 55.8007,43.0243 57.2554,43.0243 58.0797,40.4543 56.5923,40.4855 56.4957,40.2529 56.4682,39.8102 56.1914,39.8205 56.0763,40.425 56.1942,40.5716 55.8007),(40.5504 55.7875,39.7601 55.7544,39.8151 55.3187,40.5504 55.7875),(39.7863 57.025,42.5105 58.477,41.6944 58.8542,40.1389 58.048,40.2437 58.0478,40.3343 57.4673,39.7299 57.4673,39.7863 57.025),(38.0744 57.5312,38.3737 57.6908,38.3395 57.7103,38.8533 58.0638,38.432 58.2584,38.0535 58.0542,38.3395 57.9356,37.4328 57.7103,38.0744 57.5312),(37.9669 57.4734,37.1608 57.2554,37.4489 57.1909,37.9669 57.4734),(40.4136 58.7241,41.2108 59.1035,40.6366 59.3817,39.8163 58.9766,40.4552 58.9011,40.4136 58.7241),(39.7184 58.3823,39.6392 58.3821,39.6392 58.3427,39.7184 58.3823),(38.7465 58.4255,39.5485 58.7133,39.4085 58.7696,38.7465 58.4255))) +-------- MultiPolygon with Polygon with Holes +MULTIPOLYGON(((24.3677 61.4598,26.6528 61.1008,26.8726 61.7107,30.564 61.0583,31.3989 62.0215,36.0132 61.1432,36.8921 62.0009,42.6489 60.6301,43.5718 61.3757,47.0435 59.8889,49.5923 60.0868,49.1528 58.1707,51.9214 57.9148,50.2515 56.1455,52.6685 55.826,51.6577 54.2909,52.8882 53.9302,50.647 53.0148,51.394 52.4828,48.0542 51.1793,49.2847 50.5414,47.1753 49.153,43.9233 49.8096,42.561 48.7779,36.936 49.6676,35.2661 48.7489,32.8052 49.5252,27.2241 48.9802,26.1255 50.4015,21.2036 50.205,20.0171 51.5634,17.4683 53.0148,19.4458 54.0852,19.4458 55.8753,19.5776 57.4922,19.5776 58.6769,24.3677 61.4598),(24.4556 59.4227,21.2036 58.4937,21.3354 56.897,21.5991 55.9246,25.2026 55.9984,28.8501 57.0646,27.0923 57.8448,28.8062 59.1759,26.2573 59.1759,24.4556 59.4227),(33.1079 56.9523,33.1392 56.8934,33.7182 56.7292,35.1489 56.5859,34.229 56.7948,36.9794 57.0751,35.7705 57.2554,37.0097 57.4998,35.7402 57.7909,37.1608 58.0478,36.0123 58.2869,37.191 58.6819,34.6522 58.9167,37.2327 59.0233,37.1118 59.6677,35.1343 59.8448,31.9702 58.9727,32.25 58.4976,33.4734 58.8542,34.7428 59.5659,33.8361 58.6819,36.3447 58.5402,33.6245 58.271,36.4354 58.0478,33.2316 57.7748,36.1936 57.4998,33.1712 57.337,36.0727 57.0915,33.1079 56.9523),(37.0604 52.9744,34.9585 51.4814,36.5405 50.4015,39.6606 50.2893,39.7925 52.1335,41.77 50.6808,44.4946 51.9713,47.3071 52.5095,44.0552 53.5403,46.604 53.6967,47.6147 55.4041,45.3735 55.4041,42.8247 56.5837,40.4412 56.1511,40.5761 55.7884,39.7601 55.7544,39.8205 55.2753,40.3948 55.2408,40.3948 54.8773,39.5485 54.8773,39.5485 54.5631,40.3948 54.4403,40.6064 54.034,39.9716 53.9807,40.2437 53.5878,39.5485 53.5878,40.0019 53.354,38.3395 53.2817,39.5787 52.6996,37.8559 52.9188,37.4471 53.2343,37.2165 53.0798,37.4328 52.9552,37.0604 52.9744),(31.627 54.7093,29.5972 55.5037,29.1577 55.7518,22.5659 55.1286,22.5659 53.5403,22.0386 51.4814,26.2573 51.4266,30.1245 50.5414,32.1899 51.1793,30.1245 53.1731,32.4808 53.1989,32.0831 53.408,32.476 53.8383,31.4182 54.4227,31.627 54.7093),(34.7731 53.3243,34.7731 53.1793,35.0903 53.1731,34.7731 53.3243),(36.9508 55.414,37.7653 55.1891,36.8822 54.975,37.0572 54.7635,38.3093 55.1546,37.7955 55.3956,38.4907 55.5327,38.3184 55.7179,38.0262 55.6546,38.0373 55.6523,37.9482 55.6376,36.9508 55.414),(38.3092 56.9929,38.5798 57.0849,38.2186 57.2717,38.7325 57.4835,38.3395 57.7103,38.8533 58.0638,38.3698 58.2869,39.5485 58.7133,38.8838 58.9777,38.0944 58.8545,38.5813 58.7446,37.4026 58.3187,38.3395 57.9356,37.4328 57.7103,38.128 57.516,37.1608 57.2554,38.3092 56.9929),(38.309 56.9928,36.375 56.6455,36.8799 56.4895,38.309 56.9928),(40.3237 57.5365,42.6929 58.0314,40.8911 59.2659,39.2792 59.0373,40.4552 58.9011,40.3343 58.3821,39.6392 58.3821,39.6392 58.0478,40.2437 58.0478,40.3237 57.5365),(40.0149 57.4677,39.7299 57.4673,39.7379 57.4051,40.0149 57.4677))) +-------- Polygon with Polygon with Holes +MULTIPOLYGON(((24.3677 61.4598,26.6528 61.1008,26.8726 61.7107,30.564 61.0583,31.3989 62.0215,36.0132 61.1432,36.8921 62.0009,42.6489 60.6301,43.5718 61.3757,47.0435 59.8889,49.5923 60.0868,49.1528 58.1707,51.9214 57.9148,50.2515 56.1455,52.6685 55.826,51.6577 54.2909,52.8882 53.9302,50.647 53.0148,51.394 52.4828,48.0542 51.1793,49.2847 50.5414,47.1753 49.153,43.9233 49.8096,42.561 48.7779,36.936 49.6676,35.2661 48.7489,32.8052 49.5252,27.2241 48.9802,26.1255 50.4015,21.2036 50.205,20.0171 51.5634,17.4683 53.0148,19.4458 54.0852,19.4458 55.8753,19.5776 57.4922,19.5776 58.6769,24.3677 61.4598),(24.4556 59.4227,21.2036 58.4937,21.3354 56.897,21.5991 55.9246,25.2026 55.9984,28.8501 57.0646,27.0923 57.8448,28.8062 59.1759,26.2573 59.1759,24.4556 59.4227),(32.6512 57.792,32.9378 57.2699,36.7912 59.6986,35.9475 59.7758,32.6512 57.792),(33.2446 56.7729,34.2635 56.6767,37.6322 58.7797,37.2876 58.7226,37.2102 59.1452,33.2446 56.7729),(36.1815 56.4715,41.168 59.0834,40.9299 59.2404,40.8804 59.2644,40.2079 59.1718,35.4536 56.5531,36.1815 56.4715),(30.7705 55.0525,30.2092 54.6331,30.2394 53.6774,31.5682 54.7333,30.7705 55.0525),(33.8733 53.1922,34.3351 53.53,33.5144 53.9057,32.5603 53.1989,33.8733 53.1922),(31.1968 52.1649,29.7861 52.1466,30.5785 52.7531,30.3098 53.0028,29.3931 52.2763,29.4171 55.606,29.1577 55.7518,22.5659 55.1286,22.5659 53.5403,22.0386 51.4814,26.2573 51.4266,30.1245 50.5414,32.1899 51.1793,31.1968 52.1649),(31.1682 53.1903,32.6907 54.2663,32.2591 54.4483,30.5408 53.1811,31.1682 53.1903),(39.4328 55.9511,37.2766 54.4948,37.7431 53.9104,41.4519 56.3413,39.4328 55.9511),(40.9691 57.677,42.2498 58.3455,41.5887 58.8012,38.1759 56.9472,39.0894 57.2553,40.9691 57.677),(37.1934 55.4694,36.5845 55.3291,36.7219 55.1665,37.1934 55.4694),(32.2964 58.4175,34.2247 59.6064,31.9702 58.9727,32.2964 58.4175),(35.9681 52.2157,34.9585 51.4814,36.5405 50.4015,39.6606 50.2893,39.7925 52.1335,41.77 50.6808,44.4946 51.9713,47.3071 52.5095,44.0552 53.5403,46.604 53.6967,47.6147 55.4041,45.3735 55.4041,44.4212 55.8594,44.4146 55.3097,40.0925 52.1652,38.3395 52.1652,43.0243 55.3269,43.0243 56.2614,37.1608 52.2393,35.9681 52.2157))) diff --git a/tests/queries/0_stateless/01305_polygons_union.sql b/tests/queries/0_stateless/01305_polygons_union.sql new file mode 100644 index 00000000000..01982c21e6e --- /dev/null +++ b/tests/queries/0_stateless/01305_polygons_union.sql @@ -0,0 +1,15 @@ +select polygonsUnionCartesian([[[(0., 0.),(0., 3.),(1., 2.9),(2., 2.6),(2.6, 2.),(2.9, 1),(3., 0.),(0., 0.)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); + +SELECT polygonsUnionCartesian([[[(2., 100.0000991821289), (0., 3.), (1., 2.9), (2., 2.6), (2.6, 2.), (2.9, 1), (3., 0.), (100.0000991821289, 2.)]]], [[[(1., 1.), (1000.0001220703125, nan), (4., 4.), (4., 1.), (1., 1.)]]]); -- { serverError 43 } + +select polygonsUnionSpherical([[[(4.3613577, 50.8651821), (4.349556, 50.8535879), (4.3602419, 50.8435626), (4.3830299, 50.8428851), (4.3904543, 50.8564867), (4.3613148, 50.8651279)]]], [[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]); + +select '-------- MultiPolygon with Polygon'; +select wkt(polygonsUnionSpherical([[(29.453587685533865,59.779570356240356),(29.393139070478895,52.276266797422124),(40.636581470703206,59.38168915000267),(41.21084331372543,59.103467777099866),(29.786055068336193,52.146627480315004),(31.23682182965546,52.16517054781818),(41.69443223416517,58.85424941916091),(42.51048853740727,58.47703162291134),(32.59691566839227,52.22075341251539),(34.289476889931414,52.22075341251539),(43.02430176537451,58.07974369546071),(43.02430176537451,57.25537683364851),(35.468224883503325,52.2022335126388),(37.16078610504247,52.23926559241349),(43.02430176537451,56.26136189644947),(43.02430176537451,55.326904361850836),(38.33953409861437,52.16517054781818),(40.09254393520848,52.16517054781818),(44.4146199116388,55.3097062225408),(44.47506852669377,59.80998197603594),(39.72985224487867,59.931351417569715),(30.23941968124846,53.67744677450975),(30.20919537372098,54.63314259659509),(38.73245009647167,59.94649146557819),(37.2816833351524,59.97675082987618),(30.23941968124846,55.2752875586599),(30.33009260383092,56.19415599955667),(36.28428118674541,59.96162460231375),(34.863738732953635,59.97675082987618),(30.178971066193498,56.97640788219866),(30.178971066193498,57.91957806959033),(33.65476643185424,59.94649146557819),(32.32489690064491,59.94649146557819),(30.481214141468342,58.85424941916091),(30.571887064050795,59.99187015036608),(29.453587685533865,59.779570356240356)]], [[[(33.473420586689336,58.85424941916091),(32.23422397806246,58.492830557036),(32.173775363007486,58.03176922751564),(31.508840597402823,57.499784781503735),(31.750635057622702,56.86092686957355),(31.508840597402823,55.941082594334574),(32.20399967053497,55.515591939372456),(31.84130798020516,54.998862226280465),(31.418167674820367,54.422670886434275),(32.47601843828233,53.83826377018255),(32.08310244042503,53.408048308050866),(33.171177511414484,52.82758702113742),(34.77306581037117,52.91880107773494),(34.77306581037117,53.784726518357985),(34.108131044766516,54.17574726780569),(35.07530888564602,54.59813930694554),(34.25925258240394,54.96417435716029),(35.01486027059106,55.361278263643584),(33.50364489421682,55.37845402950552),(32.7480372060297,55.90721384574556),(35.67979503619571,55.68634475630185),(32.83871012861215,56.311688992608396),(34.591719965206266,56.29492065473883),(35.7100193437232,56.311688992608396),(33.83611227701915,56.695333481003644),(32.95960735872209,56.9434497616887),(36.072711034053015,57.091531913901434),(33.171177511414484,57.33702717078384),(36.193608264162954,57.499784781503735),(33.23162612646945,57.77481561306047),(36.43540272438284,58.04776787540811),(33.62454212432676,58.27099811968307),(36.344729801800376,58.54018474404165),(33.83611227701915,58.68186423448108),(34.74284150284369,59.565911441555244),(33.473420586689336,58.85424941916091)]], [[(34.65216858026123,58.91672306881671),(37.19101041256995,58.68186423448108),(36.01226241899805,58.28688958537609),(37.16078610504247,58.04776787540811),(35.74024365125068,57.79092907387934),(37.009664567405046,57.499784781503735),(35.77046795877817,57.25537683364851),(36.979440259877556,57.07510745541089),(34.22902827487645,56.794777197297435),(36.7074214921302,56.210968525786996),(34.712617195316206,56.10998276812964),(36.55629995449277,55.63519693782703),(35.13575750070099,55.53270067649592),(36.43540272438284,55.34409504165558),(34.83351442542614,55.01619492319591),(35.61934642114075,54.49294870011772),(34.89396304048112,54.12264226523038),(35.37755196092087,53.046178687628185),(37.43280487278982,52.95523300597458),(35.92158949641559,53.80257986695776),(36.91899164482259,53.856094327816805),(36.01226241899805,54.75541714463799),(37.765272255592166,55.189110239786885),(36.828318722240134,55.44708256557195),(38.03729102333953,55.652253637168315),(36.64697287707522,55.941082594334574),(38.21863686850443,56.05939028508024),(36.37495410932787,56.64551287174558),(38.30930979108689,56.992876013526654),(37.16078610504247,57.25537683364851),(38.127963945921984,57.516020773674256),(37.43280487278982,57.710289827306724),(38.33953409861437,57.935626886818994),(37.40258056526235,58.31865112960426),(38.58132855883426,58.744648733419496),(37.31190764267989,59.02578062465136),(34.65216858026123,58.91672306881671)]], [[(38.52087994377928,59.11898412389468),(39.54850639971376,58.713270635642914),(38.369758406141855,58.28688958537609),(38.85334732658162,58.06375936407028),(38.33953409861437,57.710289827306724),(38.73245009647167,57.48354156434209),(38.21863686850443,57.271721400459285),(38.97424455669155,56.87744603722649),(37.463029180317314,56.5623320541159),(38.94402024916407,56.05939028508024),(38.18841256097694,55.856355210835915),(38.490655636251795,55.53270067649592),(37.795496563119656,55.39562234093384),(38.30930979108689,55.154587013355666),(36.7074214921302,54.65063295250911),(37.31190764267989,53.92734063371401),(36.979440259877556,53.58783775557231),(37.855945178174615,52.91880107773497),(39.57873070724124,52.69956490610895),(38.33953409861437,53.281741738901104),(40.00187101262603,53.35396273604752),(39.54850639971376,53.58783775557231),(40.24366547284591,53.58783775557231),(39.97164670509855,53.98069568468355),(40.60635716317572,54.03398248547225),(40.39478701048334,54.44025165268903),(39.54850639971376,54.56310590284329),(39.54850639971376,54.87732350170489),(40.39478701048334,54.87732350170489),(40.39478701048334,55.24083903654295),(39.82052516746112,55.2752875586599),(39.760076552406154,55.75443792473942),(40.57613285564824,55.78844000174894),(40.425011318010824,56.19415599955667),(39.82052516746112,56.07626182891758),(39.79030085993364,56.41214455508424),(40.48545993306579,56.495655446714636),(40.33433839542836,56.95993246553937),(39.79030085993364,56.992876013526654),(39.72985224487867,57.46729112028032),(40.33433839542836,57.46729112028032),(40.24366547284591,58.04776787540811),(39.63917932229622,58.04776787540811),(39.63917932229622,58.382088724871295),(40.33433839542836,58.382088724871295),(40.45523562553831,58.9011152358548),(38.52087994377928,59.11898412389468)]]])) format TSV; + +select '-------- MultiPolygon with Polygon with Holes'; +select wkt(polygonsUnionSpherical([[[(33.473420586689336,58.85424941916091),(32.23422397806246,58.492830557036),(32.173775363007486,58.03176922751564),(31.508840597402823,57.499784781503735),(31.750635057622702,56.86092686957355),(31.508840597402823,55.941082594334574),(32.20399967053497,55.515591939372456),(31.84130798020516,54.998862226280465),(31.418167674820367,54.422670886434275),(32.47601843828233,53.83826377018255),(32.08310244042503,53.408048308050866),(33.171177511414484,52.82758702113742),(34.77306581037117,52.91880107773494),(34.77306581037117,53.784726518357985),(34.108131044766516,54.17574726780569),(35.07530888564602,54.59813930694554),(34.25925258240394,54.96417435716029),(35.01486027059106,55.361278263643584),(33.50364489421682,55.37845402950552),(32.7480372060297,55.90721384574556),(35.67979503619571,55.68634475630185),(32.83871012861215,56.311688992608396),(34.591719965206266,56.29492065473883),(35.7100193437232,56.311688992608396),(33.83611227701915,56.695333481003644),(32.95960735872209,56.9434497616887),(36.072711034053015,57.091531913901434),(33.171177511414484,57.33702717078384),(36.193608264162954,57.499784781503735),(33.23162612646945,57.77481561306047),(36.43540272438284,58.04776787540811),(33.62454212432676,58.27099811968307),(36.344729801800376,58.54018474404165),(33.83611227701915,58.68186423448108),(34.74284150284369,59.565911441555244),(33.473420586689336,58.85424941916091)]], [[(34.65216858026123,58.91672306881671),(37.19101041256995,58.68186423448108),(36.01226241899805,58.28688958537609),(37.16078610504247,58.04776787540811),(35.74024365125068,57.79092907387934),(37.009664567405046,57.499784781503735),(35.77046795877817,57.25537683364851),(36.979440259877556,57.07510745541089),(34.22902827487645,56.794777197297435),(36.7074214921302,56.210968525786996),(34.712617195316206,56.10998276812964),(36.55629995449277,55.63519693782703),(35.13575750070099,55.53270067649592),(36.43540272438284,55.34409504165558),(34.83351442542614,55.01619492319591),(35.61934642114075,54.49294870011772),(34.89396304048112,54.12264226523038),(35.37755196092087,53.046178687628185),(37.43280487278982,52.95523300597458),(35.92158949641559,53.80257986695776),(36.91899164482259,53.856094327816805),(36.01226241899805,54.75541714463799),(37.765272255592166,55.189110239786885),(36.828318722240134,55.44708256557195),(38.03729102333953,55.652253637168315),(36.64697287707522,55.941082594334574),(38.21863686850443,56.05939028508024),(36.37495410932787,56.64551287174558),(38.30930979108689,56.992876013526654),(37.16078610504247,57.25537683364851),(38.127963945921984,57.516020773674256),(37.43280487278982,57.710289827306724),(38.33953409861437,57.935626886818994),(37.40258056526235,58.31865112960426),(38.58132855883426,58.744648733419496),(37.31190764267989,59.02578062465136),(34.65216858026123,58.91672306881671)]], [[(38.52087994377928,59.11898412389468),(39.54850639971376,58.713270635642914),(38.369758406141855,58.28688958537609),(38.85334732658162,58.06375936407028),(38.33953409861437,57.710289827306724),(38.73245009647167,57.48354156434209),(38.21863686850443,57.271721400459285),(38.97424455669155,56.87744603722649),(37.463029180317314,56.5623320541159),(38.94402024916407,56.05939028508024),(38.18841256097694,55.856355210835915),(38.490655636251795,55.53270067649592),(37.795496563119656,55.39562234093384),(38.30930979108689,55.154587013355666),(36.7074214921302,54.65063295250911),(37.31190764267989,53.92734063371401),(36.979440259877556,53.58783775557231),(37.855945178174615,52.91880107773497),(39.57873070724124,52.69956490610895),(38.33953409861437,53.281741738901104),(40.00187101262603,53.35396273604752),(39.54850639971376,53.58783775557231),(40.24366547284591,53.58783775557231),(39.97164670509855,53.98069568468355),(40.60635716317572,54.03398248547225),(40.39478701048334,54.44025165268903),(39.54850639971376,54.56310590284329),(39.54850639971376,54.87732350170489),(40.39478701048334,54.87732350170489),(40.39478701048334,55.24083903654295),(39.82052516746112,55.2752875586599),(39.760076552406154,55.75443792473942),(40.57613285564824,55.78844000174894),(40.425011318010824,56.19415599955667),(39.82052516746112,56.07626182891758),(39.79030085993364,56.41214455508424),(40.48545993306579,56.495655446714636),(40.33433839542836,56.95993246553937),(39.79030085993364,56.992876013526654),(39.72985224487867,57.46729112028032),(40.33433839542836,57.46729112028032),(40.24366547284591,58.04776787540811),(39.63917932229622,58.04776787540811),(39.63917932229622,58.382088724871295),(40.33433839542836,58.382088724871295),(40.45523562553831,58.9011152358548),(38.52087994377928,59.11898412389468)]]], [[(24.367675781249993,61.45977057029751),(19.577636718749993,58.67693767258692),(19.577636718749993,57.492213666700735),(19.445800781249996,55.87531083569678),(19.445800781249996,54.085173420886775),(17.468261718749996,53.014783245859235),(20.017089843749993,51.563412328675895),(21.203613281249993,50.205033264943324),(26.125488281249993,50.40151532278236),(27.22412109374999,48.980216985374994),(32.80517578124999,49.525208341974405),(35.26611328124999,48.74894534343292),(36.93603515624999,49.66762782262194),(42.56103515625,48.77791275550183),(43.92333984374999,49.8096315635631),(47.17529296875,49.152969656170455),(49.28466796875,50.54136296522162),(48.05419921875,51.17934297928929),(51.39404296875,52.48278022207825),(50.64697265625,53.014783245859235),(52.88818359375,53.93021986394004),(51.65771484374999,54.29088164657006),(52.66845703125,55.825973254619015),(50.25146484375,56.145549500679095),(51.92138671875,57.914847767009206),(49.15283203125,58.17070248348605),(49.59228515625,60.086762746260064),(47.043457031249986,59.88893689676584),(43.57177734375,61.37567331572748),(42.64892578125,60.630101766266705),(36.89208984374999,62.000904713685856),(36.01318359374999,61.143235250840576),(31.398925781249993,62.02152819100766),(30.563964843749996,61.05828537037917),(26.872558593749993,61.71070595883174),(26.652832031249993,61.10078883158897),(24.367675781249993,61.45977057029751)], [(24.455566406249993,59.42272750081452),(21.203613281249993,58.49369382056807),(21.335449218749993,56.89700392127261),(21.599121093749993,55.92458580482949),(25.202636718749993,55.998380955359636),(28.850097656249993,57.06463027327854),(27.09228515625,57.844750992890994),(28.806152343749996,59.17592824927138),(26.257324218749993,59.17592824927138),(24.455566406249993,59.42272750081452)], [(35.13427734375,59.84481485969107),(31.970214843749993,58.97266715450152),(33.20068359374999,56.776808316568406),(36.67236328125,56.41390137600675),(39.08935546874999,57.25528054528888),(42.69287109374999,58.03137242177638),(40.89111328124999,59.26588062825809),(37.28759765625,58.722598828043374),(37.11181640624999,59.66774058164964),(35.13427734375,59.84481485969107)], [(29.157714843749993,55.75184939173528),(22.565917968749993,55.128649068488784),(22.565917968749993,53.54030739150019),(22.038574218749996,51.48138289610097),(26.257324218749993,51.42661449707484),(30.124511718749993,50.54136296522162),(32.18994140624999,51.17934297928929),(30.124511718749993,53.173119202640635),(35.09033203124999,53.173119202640635),(33.11279296875,54.085173420886775),(29.597167968749993,55.50374985927513),(29.157714843749993,55.75184939173528)], [(42.82470703125,56.58369172128337),(36.584472656249986,55.329144408405085),(37.99072265625,53.592504809039355),(34.95849609374999,51.48138289610097),(36.54052734374999,50.40151532278236),(39.66064453124999,50.289339253291786),(39.79248046875,52.13348804077148),(41.77001953125,50.68079714532166),(44.49462890624999,51.97134580885171),(47.30712890624999,52.509534770327264),(44.05517578125,53.54030739150019),(46.60400390625,53.696706475303245),(47.61474609375,55.40406982700608),(45.37353515625,55.40406982700608),(42.82470703125,56.58369172128337)]])) format TSV; + +select '-------- Polygon with Polygon with Holes'; +select wkt(polygonsUnionSpherical([[(29.453587685533865,59.779570356240356),(29.393139070478895,52.276266797422124),(40.636581470703206,59.38168915000267),(41.21084331372543,59.103467777099866),(29.786055068336193,52.146627480315004),(31.23682182965546,52.16517054781818),(41.69443223416517,58.85424941916091),(42.51048853740727,58.47703162291134),(32.59691566839227,52.22075341251539),(34.289476889931414,52.22075341251539),(43.02430176537451,58.07974369546071),(43.02430176537451,57.25537683364851),(35.468224883503325,52.2022335126388),(37.16078610504247,52.23926559241349),(43.02430176537451,56.26136189644947),(43.02430176537451,55.326904361850836),(38.33953409861437,52.16517054781818),(40.09254393520848,52.16517054781818),(44.4146199116388,55.3097062225408),(44.47506852669377,59.80998197603594),(39.72985224487867,59.931351417569715),(30.23941968124846,53.67744677450975),(30.20919537372098,54.63314259659509),(38.73245009647167,59.94649146557819),(37.2816833351524,59.97675082987618),(30.23941968124846,55.2752875586599),(30.33009260383092,56.19415599955667),(36.28428118674541,59.96162460231375),(34.863738732953635,59.97675082987618),(30.178971066193498,56.97640788219866),(30.178971066193498,57.91957806959033),(33.65476643185424,59.94649146557819),(32.32489690064491,59.94649146557819),(30.481214141468342,58.85424941916091),(30.571887064050795,59.99187015036608),(29.453587685533865,59.779570356240356)]], [[(24.367675781249993,61.45977057029751),(19.577636718749993,58.67693767258692),(19.577636718749993,57.492213666700735),(19.445800781249996,55.87531083569678),(19.445800781249996,54.085173420886775),(17.468261718749996,53.014783245859235),(20.017089843749993,51.563412328675895),(21.203613281249993,50.205033264943324),(26.125488281249993,50.40151532278236),(27.22412109374999,48.980216985374994),(32.80517578124999,49.525208341974405),(35.26611328124999,48.74894534343292),(36.93603515624999,49.66762782262194),(42.56103515625,48.77791275550183),(43.92333984374999,49.8096315635631),(47.17529296875,49.152969656170455),(49.28466796875,50.54136296522162),(48.05419921875,51.17934297928929),(51.39404296875,52.48278022207825),(50.64697265625,53.014783245859235),(52.88818359375,53.93021986394004),(51.65771484374999,54.29088164657006),(52.66845703125,55.825973254619015),(50.25146484375,56.145549500679095),(51.92138671875,57.914847767009206),(49.15283203125,58.17070248348605),(49.59228515625,60.086762746260064),(47.043457031249986,59.88893689676584),(43.57177734375,61.37567331572748),(42.64892578125,60.630101766266705),(36.89208984374999,62.000904713685856),(36.01318359374999,61.143235250840576),(31.398925781249993,62.02152819100766),(30.563964843749996,61.05828537037917),(26.872558593749993,61.71070595883174),(26.652832031249993,61.10078883158897),(24.367675781249993,61.45977057029751)], [(24.455566406249993,59.42272750081452),(21.203613281249993,58.49369382056807),(21.335449218749993,56.89700392127261),(21.599121093749993,55.92458580482949),(25.202636718749993,55.998380955359636),(28.850097656249993,57.06463027327854),(27.09228515625,57.844750992890994),(28.806152343749996,59.17592824927138),(26.257324218749993,59.17592824927138),(24.455566406249993,59.42272750081452)], [(35.13427734375,59.84481485969107),(31.970214843749993,58.97266715450152),(33.20068359374999,56.776808316568406),(36.67236328125,56.41390137600675),(39.08935546874999,57.25528054528888),(42.69287109374999,58.03137242177638),(40.89111328124999,59.26588062825809),(37.28759765625,58.722598828043374),(37.11181640624999,59.66774058164964),(35.13427734375,59.84481485969107)], [(29.157714843749993,55.75184939173528),(22.565917968749993,55.128649068488784),(22.565917968749993,53.54030739150019),(22.038574218749996,51.48138289610097),(26.257324218749993,51.42661449707484),(30.124511718749993,50.54136296522162),(32.18994140624999,51.17934297928929),(30.124511718749993,53.173119202640635),(35.09033203124999,53.173119202640635),(33.11279296875,54.085173420886775),(29.597167968749993,55.50374985927513),(29.157714843749993,55.75184939173528)], [(42.82470703125,56.58369172128337),(36.584472656249986,55.329144408405085),(37.99072265625,53.592504809039355),(34.95849609374999,51.48138289610097),(36.54052734374999,50.40151532278236),(39.66064453124999,50.289339253291786),(39.79248046875,52.13348804077148),(41.77001953125,50.68079714532166),(44.49462890624999,51.97134580885171),(47.30712890624999,52.509534770327264),(44.05517578125,53.54030739150019),(46.60400390625,53.696706475303245),(47.61474609375,55.40406982700608),(45.37353515625,55.40406982700608),(42.82470703125,56.58369172128337)]])) format TSV; + diff --git a/tests/queries/0_stateless/01306_polygons_intersection.reference b/tests/queries/0_stateless/01306_polygons_intersection.reference new file mode 100644 index 00000000000..43ee975913e --- /dev/null +++ b/tests/queries/0_stateless/01306_polygons_intersection.reference @@ -0,0 +1,10 @@ +[[[(1,2.9),(2,2.6),(2.6,2),(2.9,1),(1,1),(1,2.9)]]] +[] +[] +[[[(4.3666052904432435,50.84337386140151),(4.3602419,50.8435626),(4.349556,50.8535879),(4.3526804582393535,50.856658100365976),(4.367945,50.852455),(4.3666052904432435,50.84337386140151)]]] +-------- MultiPolygon with Polygon +MULTIPOLYGON(((35.5408 58.9593,36.9725 59.0149,36.4989 58.7512,35.3712 58.8556,35.5408 58.9593)),((34.4816 56.8232,36.1999 57.0022,35.4083 56.5254,34.3867 56.7596,34.4816 56.8232)),((35.9179 57.7512,36.0848 57.855,37.1608 58.0478,36.5949 58.1673,37.8553 58.9075,38.5813 58.7446,37.4026 58.3187,38.0535 58.0542,36.4587 57.1544,35.7705 57.2554,37.0097 57.4998,35.9179 57.7512)),((36.8709 53.2765,37.4328 52.9552,36.5022 53.0008,36.8709 53.2765)),((36.1528 53.6763,35.3645 53.076,34.9611 53.9765,36.0472 54.7217,36.6985 54.0791,36.3552 53.8269,35.9216 53.8026,36.1528 53.6763)),((37.0035 54.2999,36.7074 54.6506,38.1601 55.1091,37.0035 54.2999)),((38.1688 56.0758,38.2186 56.0594,38.1319 56.0534,38.1688 56.0758)),((37.6238 55.7402,38.0373 55.6523,37.2824 55.5258,37.6238 55.7402)),((37.06 55.3843,37.7653 55.1891,36.151 54.791,37.06 55.3843)),((38.2312 56.9795,36.5334 56.6753,37.4489 57.1909,38.2699 57.0021,38.2312 56.9795)),((37.2281 56.3799,36.193 55.7319,35.3188 55.9582,35.6571 56.1619,36.7074 56.211,36.0233 56.3789,36.4446 56.6242,37.2281 56.3799)),((34.9952 58.6226,36.1498 58.553,36.0877 58.5174,34.6028 58.3749,34.9952 58.6226)),((34.3593 58.2189,35.4314 58.1349,35.1134 57.9454,33.7581 57.8255,34.3593 58.2189)),((33.6325 57.7419,34.6332 57.6538,34.2274 57.4023,33.1712 57.337,34.0208 57.2724,33.5602 56.9781,32.9596 56.9434,33.3418 56.8364,31.7782 55.7778,31.5088 55.9411,31.6069 56.3194,33.6325 57.7419)),((36.403 58.0507,36.4354 58.0478,36.3932 58.0447,36.403 58.0507)),((35.613 57.5595,36.1936 57.4998,35.4682 57.4674,35.613 57.5595)),((35.0338 57.1875,36.0727 57.0915,34.8098 57.0409,35.0338 57.1875)),((34.1885 56.6259,35.2273 56.414,35.0485 56.303,34.5917 56.2949,33.7222 56.3063,34.1885 56.6259)),((33.5244 56.1686,34.4996 55.9565,34.2598 55.8023,33.1204 55.8832,33.5244 56.1686)),((32.9547 55.7645,33.5036 55.3785,33.6125 55.3778,31.8748 54.1736,31.4182 54.4227,31.7439 54.8677,32.9547 55.7645)),((34.7279 53.8116,34.7731 53.7847,34.7731 52.9188,33.4048 52.8423,34.7279 53.8116)),((34.7231 54.7576,32.5275 53.1741,32.0831 53.408,32.476 53.8383,32.2523 53.964,34.3709 55.3709,35.0149 55.3613,34.2593 54.9642,34.7231 54.7576)),((34.9706 54.9262,34.8335 55.0162,35.2275 55.0993,34.9706 54.9262)),((35.7505 55.4454,35.1358 55.5327,35.9817 55.5958,35.7505 55.4454)),((35.0954 55.822,35.6798 55.6863,34.9721 55.7463,35.0954 55.822)),((34.7331 56.1049,34.7126 56.11,34.744 56.1118,34.7331 56.1049)),((40.2143 54.467,38.5511 53.2922,38.3395 53.2817,38.4609 53.226,38.0214 52.8989,37.8559 52.9188,37.135 53.4711,39.8151 55.3187,39.8205 55.2753,40.3948 55.2408,40.3948 54.8773,39.5485 54.8773,39.5485 54.5631,40.2143 54.467)),((40.5716 55.8007,40.5761 55.7884,40.5504 55.7875,40.5716 55.8007)),((40.4543 56.5923,40.2529 56.4682,39.7903 56.4121,39.8102 56.1914,38.2609 55.1775,37.7955 55.3956,38.4907 55.5327,38.1884 55.8564,38.944 56.0594,38.4339 56.2361,39.7863 57.025,39.7903 56.9929,40.3343 56.9599,40.4543 56.5923)),((40.1389 58.048,38.4915 57.1308,38.2186 57.2717,38.7325 57.4835,38.3737 57.6908,39.6392 58.3427,39.6392 58.0478,40.1389 58.048)),((37.5054 56.5484,37.463 56.5623,37.565 56.5843,37.5054 56.5484)),((38.0744 57.5312,38.128 57.516,37.9669 57.4734,38.0744 57.5312)),((40.4136 58.7241,40.3343 58.3821,39.7184 58.3823,40.4136 58.7241)),((39.8163 58.9766,39.4085 58.7696,38.5209 59.119,39.8163 58.9766)),((38.432 58.2584,38.3698 58.2869,38.7465 58.4255,38.432 58.2584)),((32.2175 58.3664,32.5691 58.5924,33.4734 58.8542,34.7428 59.5659,33.8361 58.6819,34.0496 58.6717,31.6514 57.1258,31.5088 57.4998,32.1738 58.0318,32.2175 58.3664)),((39.9942 53.358,40.0019 53.354,39.9877 53.3534,39.9942 53.358)),((39.2704 52.8471,39.5787 52.6996,39.1456 52.7573,39.2704 52.8471))) +-------- MultiPolygon with Polygon with Holes +MULTIPOLYGON(((33.1079 56.9523,32.9596 56.9434,33.1392 56.8934,33.2007 56.7768,33.7182 56.7292,33.8361 56.6953,35.71 56.3117,34.5917 56.2949,32.8387 56.3117,35.6798 55.6863,32.748 55.9072,33.5036 55.3785,35.0149 55.3613,34.2593 54.9642,35.0753 54.5981,34.1081 54.1757,34.7731 53.7847,34.7731 53.3243,33.1128 54.0852,31.627 54.7093,31.8413 54.9989,32.204 55.5156,31.5088 55.9411,31.7506 56.8609,31.5088 57.4998,32.1738 58.0318,32.2342 58.4928,32.25 58.4976,33.1079 56.9523)),((35.1489 56.5859,36.6724 56.4139,36.8799 56.4895,38.2186 56.0594,36.647 55.9411,38.0262 55.6546,37.9482 55.6376,36.8283 55.4471,36.9508 55.414,36.5845 55.3291,36.8822 54.975,36.0123 54.7554,36.919 53.8561,35.9216 53.8026,37.2165 53.0798,37.0604 52.9744,35.3776 53.0462,34.894 54.1226,35.6193 54.4929,34.8335 55.0162,36.4354 55.3441,35.1358 55.5327,36.5563 55.6352,34.7126 56.11,36.7074 56.211,35.1489 56.5859)),((37.2327 59.0233,37.3119 59.0258,38.0944 58.8545,37.2876 58.7226,37.2327 59.0233)),((37.4471 53.2343,36.9794 53.5878,37.3119 53.9273,36.7074 54.6506,37.0572 54.7635,37.9907 53.5925,37.4471 53.2343)),((34.7731 53.1793,34.7731 52.9188,33.1712 52.8276,32.4808 53.1989,34.7731 53.1793)),((40.4412 56.1511,38.3184 55.7179,38.1884 55.8564,38.944 56.0594,37.463 56.5623,38.9742 56.8774,38.5798 57.0849,39.0894 57.2553,39.7379 57.4051,39.7903 56.9929,40.3343 56.9599,40.4855 56.4957,39.7903 56.4121,39.8205 56.0763,40.425 56.1942,40.4412 56.1511)),((38.3092 56.9929,38.3093 56.9929,38.309 56.9928,38.3092 56.9929)),((40.3237 57.5365,40.3343 57.4673,40.0149 57.4677,40.3237 57.5365)),((39.2792 59.0373,38.8838 58.9777,38.5209 59.119,39.2792 59.0373))) +-------- Polygon with Polygon with Holes +MULTIPOLYGON(((32.6512 57.792,30.3301 56.1942,30.2394 55.2753,32.9378 57.2699,33.2007 56.7768,33.2446 56.7729,30.7705 55.0525,29.5972 55.5037,29.4171 55.606,29.4536 59.7796,30.5719 59.9919,30.4812 58.8542,32.3249 59.9465,33.6548 59.9465,30.179 57.9196,30.179 56.9764,32.2964 58.4175,32.6512 57.792)),((35.9475 59.7758,35.1343 59.8448,34.2247 59.6064,34.8637 59.9768,36.2843 59.9616,35.9475 59.7758)),((36.7912 59.6986,37.2817 59.9768,38.7325 59.9465,37.2102 59.1452,37.1118 59.6677,36.7912 59.6986)),((34.2635 56.6767,35.4536 56.5531,32.2591 54.4483,31.5682 54.7333,34.2635 56.6767)),((36.1815 56.4715,36.6724 56.4139,38.1759 56.9472,33.5144 53.9057,33.1128 54.0852,32.6907 54.2663,36.1815 56.4715)),((33.8733 53.1922,35.0903 53.1731,34.3351 53.53,36.7219 55.1665,37.2766 54.4948,34.2895 52.2208,32.5969 52.2208,33.8733 53.1922)),((31.1968 52.1649,30.5785 52.7531,31.1682 53.1903,32.5603 53.1989,31.2368 52.1652,31.1968 52.1649)),((30.3098 53.0028,30.1245 53.1731,30.5408 53.1811,30.3098 53.0028)),((37.6322 58.7797,39.7299 59.9314,44.4751 59.81,44.4212 55.8594,42.8247 56.5837,41.4519 56.3413,43.0243 57.2554,43.0243 58.0797,39.4328 55.9511,37.1934 55.4694,40.9691 57.677,42.6929 58.0314,42.2498 58.3455,42.5105 58.477,41.6944 58.8542,41.5887 58.8012,41.168 59.0834,41.2108 59.1035,40.9299 59.2404,40.8911 59.2659,40.8804 59.2644,40.6366 59.3817,40.2079 59.1718,37.6322 58.7797)),((35.9681 52.2157,35.4682 52.2022,37.7431 53.9104,37.9907 53.5925,35.9681 52.2157))) diff --git a/tests/queries/0_stateless/01306_polygons_intersection.sql b/tests/queries/0_stateless/01306_polygons_intersection.sql new file mode 100644 index 00000000000..144408ca0ae --- /dev/null +++ b/tests/queries/0_stateless/01306_polygons_intersection.sql @@ -0,0 +1,14 @@ +select polygonsIntersectionCartesian([[[(0., 0.),(0., 3.),(1., 2.9),(2., 2.6),(2.6, 2.),(2.9, 1.),(3., 0.),(0., 0.)]]], [[[(1., 1.),(1., 4.),(4., 4.),(4., 1.),(1., 1.)]]]); +select polygonsIntersectionCartesian([[[(0., 0.),(0., 3.),(1., 2.9),(2., 2.6),(2.6, 2.),(2.9, 1.),(3., 0.),(0., 0.)]]], [[[(3., 3.),(3., 4.),(4., 4.),(4., 3.),(3., 3.)]]]); + +select polygonsIntersectionSpherical([[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]], [[[(25.0010, 136.9987), (17.7500, 142.5000), (11.3733, 142.5917)]]]); +select polygonsIntersectionSpherical([[[(4.3613577, 50.8651821), (4.349556, 50.8535879), (4.3602419, 50.8435626), (4.3830299, 50.8428851), (4.3904543, 50.8564867), (4.3613148, 50.8651279)]]], [[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]); + +select '-------- MultiPolygon with Polygon'; +select wkt(polygonsIntersectionSpherical([[(29.453587685533865,59.779570356240356),(29.393139070478895,52.276266797422124),(40.636581470703206,59.38168915000267),(41.21084331372543,59.103467777099866),(29.786055068336193,52.146627480315004),(31.23682182965546,52.16517054781818),(41.69443223416517,58.85424941916091),(42.51048853740727,58.47703162291134),(32.59691566839227,52.22075341251539),(34.289476889931414,52.22075341251539),(43.02430176537451,58.07974369546071),(43.02430176537451,57.25537683364851),(35.468224883503325,52.2022335126388),(37.16078610504247,52.23926559241349),(43.02430176537451,56.26136189644947),(43.02430176537451,55.326904361850836),(38.33953409861437,52.16517054781818),(40.09254393520848,52.16517054781818),(44.4146199116388,55.3097062225408),(44.47506852669377,59.80998197603594),(39.72985224487867,59.931351417569715),(30.23941968124846,53.67744677450975),(30.20919537372098,54.63314259659509),(38.73245009647167,59.94649146557819),(37.2816833351524,59.97675082987618),(30.23941968124846,55.2752875586599),(30.33009260383092,56.19415599955667),(36.28428118674541,59.96162460231375),(34.863738732953635,59.97675082987618),(30.178971066193498,56.97640788219866),(30.178971066193498,57.91957806959033),(33.65476643185424,59.94649146557819),(32.32489690064491,59.94649146557819),(30.481214141468342,58.85424941916091),(30.571887064050795,59.99187015036608),(29.453587685533865,59.779570356240356)]], [[[(33.473420586689336,58.85424941916091),(32.23422397806246,58.492830557036),(32.173775363007486,58.03176922751564),(31.508840597402823,57.499784781503735),(31.750635057622702,56.86092686957355),(31.508840597402823,55.941082594334574),(32.20399967053497,55.515591939372456),(31.84130798020516,54.998862226280465),(31.418167674820367,54.422670886434275),(32.47601843828233,53.83826377018255),(32.08310244042503,53.408048308050866),(33.171177511414484,52.82758702113742),(34.77306581037117,52.91880107773494),(34.77306581037117,53.784726518357985),(34.108131044766516,54.17574726780569),(35.07530888564602,54.59813930694554),(34.25925258240394,54.96417435716029),(35.01486027059106,55.361278263643584),(33.50364489421682,55.37845402950552),(32.7480372060297,55.90721384574556),(35.67979503619571,55.68634475630185),(32.83871012861215,56.311688992608396),(34.591719965206266,56.29492065473883),(35.7100193437232,56.311688992608396),(33.83611227701915,56.695333481003644),(32.95960735872209,56.9434497616887),(36.072711034053015,57.091531913901434),(33.171177511414484,57.33702717078384),(36.193608264162954,57.499784781503735),(33.23162612646945,57.77481561306047),(36.43540272438284,58.04776787540811),(33.62454212432676,58.27099811968307),(36.344729801800376,58.54018474404165),(33.83611227701915,58.68186423448108),(34.74284150284369,59.565911441555244),(33.473420586689336,58.85424941916091)]], [[(34.65216858026123,58.91672306881671),(37.19101041256995,58.68186423448108),(36.01226241899805,58.28688958537609),(37.16078610504247,58.04776787540811),(35.74024365125068,57.79092907387934),(37.009664567405046,57.499784781503735),(35.77046795877817,57.25537683364851),(36.979440259877556,57.07510745541089),(34.22902827487645,56.794777197297435),(36.7074214921302,56.210968525786996),(34.712617195316206,56.10998276812964),(36.55629995449277,55.63519693782703),(35.13575750070099,55.53270067649592),(36.43540272438284,55.34409504165558),(34.83351442542614,55.01619492319591),(35.61934642114075,54.49294870011772),(34.89396304048112,54.12264226523038),(35.37755196092087,53.046178687628185),(37.43280487278982,52.95523300597458),(35.92158949641559,53.80257986695776),(36.91899164482259,53.856094327816805),(36.01226241899805,54.75541714463799),(37.765272255592166,55.189110239786885),(36.828318722240134,55.44708256557195),(38.03729102333953,55.652253637168315),(36.64697287707522,55.941082594334574),(38.21863686850443,56.05939028508024),(36.37495410932787,56.64551287174558),(38.30930979108689,56.992876013526654),(37.16078610504247,57.25537683364851),(38.127963945921984,57.516020773674256),(37.43280487278982,57.710289827306724),(38.33953409861437,57.935626886818994),(37.40258056526235,58.31865112960426),(38.58132855883426,58.744648733419496),(37.31190764267989,59.02578062465136),(34.65216858026123,58.91672306881671)]], [[(38.52087994377928,59.11898412389468),(39.54850639971376,58.713270635642914),(38.369758406141855,58.28688958537609),(38.85334732658162,58.06375936407028),(38.33953409861437,57.710289827306724),(38.73245009647167,57.48354156434209),(38.21863686850443,57.271721400459285),(38.97424455669155,56.87744603722649),(37.463029180317314,56.5623320541159),(38.94402024916407,56.05939028508024),(38.18841256097694,55.856355210835915),(38.490655636251795,55.53270067649592),(37.795496563119656,55.39562234093384),(38.30930979108689,55.154587013355666),(36.7074214921302,54.65063295250911),(37.31190764267989,53.92734063371401),(36.979440259877556,53.58783775557231),(37.855945178174615,52.91880107773497),(39.57873070724124,52.69956490610895),(38.33953409861437,53.281741738901104),(40.00187101262603,53.35396273604752),(39.54850639971376,53.58783775557231),(40.24366547284591,53.58783775557231),(39.97164670509855,53.98069568468355),(40.60635716317572,54.03398248547225),(40.39478701048334,54.44025165268903),(39.54850639971376,54.56310590284329),(39.54850639971376,54.87732350170489),(40.39478701048334,54.87732350170489),(40.39478701048334,55.24083903654295),(39.82052516746112,55.2752875586599),(39.760076552406154,55.75443792473942),(40.57613285564824,55.78844000174894),(40.425011318010824,56.19415599955667),(39.82052516746112,56.07626182891758),(39.79030085993364,56.41214455508424),(40.48545993306579,56.495655446714636),(40.33433839542836,56.95993246553937),(39.79030085993364,56.992876013526654),(39.72985224487867,57.46729112028032),(40.33433839542836,57.46729112028032),(40.24366547284591,58.04776787540811),(39.63917932229622,58.04776787540811),(39.63917932229622,58.382088724871295),(40.33433839542836,58.382088724871295),(40.45523562553831,58.9011152358548),(38.52087994377928,59.11898412389468)]]])) format TSV; + +select '-------- MultiPolygon with Polygon with Holes'; +select wkt(polygonsIntersectionSpherical([[[(33.473420586689336,58.85424941916091),(32.23422397806246,58.492830557036),(32.173775363007486,58.03176922751564),(31.508840597402823,57.499784781503735),(31.750635057622702,56.86092686957355),(31.508840597402823,55.941082594334574),(32.20399967053497,55.515591939372456),(31.84130798020516,54.998862226280465),(31.418167674820367,54.422670886434275),(32.47601843828233,53.83826377018255),(32.08310244042503,53.408048308050866),(33.171177511414484,52.82758702113742),(34.77306581037117,52.91880107773494),(34.77306581037117,53.784726518357985),(34.108131044766516,54.17574726780569),(35.07530888564602,54.59813930694554),(34.25925258240394,54.96417435716029),(35.01486027059106,55.361278263643584),(33.50364489421682,55.37845402950552),(32.7480372060297,55.90721384574556),(35.67979503619571,55.68634475630185),(32.83871012861215,56.311688992608396),(34.591719965206266,56.29492065473883),(35.7100193437232,56.311688992608396),(33.83611227701915,56.695333481003644),(32.95960735872209,56.9434497616887),(36.072711034053015,57.091531913901434),(33.171177511414484,57.33702717078384),(36.193608264162954,57.499784781503735),(33.23162612646945,57.77481561306047),(36.43540272438284,58.04776787540811),(33.62454212432676,58.27099811968307),(36.344729801800376,58.54018474404165),(33.83611227701915,58.68186423448108),(34.74284150284369,59.565911441555244),(33.473420586689336,58.85424941916091)]], [[(34.65216858026123,58.91672306881671),(37.19101041256995,58.68186423448108),(36.01226241899805,58.28688958537609),(37.16078610504247,58.04776787540811),(35.74024365125068,57.79092907387934),(37.009664567405046,57.499784781503735),(35.77046795877817,57.25537683364851),(36.979440259877556,57.07510745541089),(34.22902827487645,56.794777197297435),(36.7074214921302,56.210968525786996),(34.712617195316206,56.10998276812964),(36.55629995449277,55.63519693782703),(35.13575750070099,55.53270067649592),(36.43540272438284,55.34409504165558),(34.83351442542614,55.01619492319591),(35.61934642114075,54.49294870011772),(34.89396304048112,54.12264226523038),(35.37755196092087,53.046178687628185),(37.43280487278982,52.95523300597458),(35.92158949641559,53.80257986695776),(36.91899164482259,53.856094327816805),(36.01226241899805,54.75541714463799),(37.765272255592166,55.189110239786885),(36.828318722240134,55.44708256557195),(38.03729102333953,55.652253637168315),(36.64697287707522,55.941082594334574),(38.21863686850443,56.05939028508024),(36.37495410932787,56.64551287174558),(38.30930979108689,56.992876013526654),(37.16078610504247,57.25537683364851),(38.127963945921984,57.516020773674256),(37.43280487278982,57.710289827306724),(38.33953409861437,57.935626886818994),(37.40258056526235,58.31865112960426),(38.58132855883426,58.744648733419496),(37.31190764267989,59.02578062465136),(34.65216858026123,58.91672306881671)]], [[(38.52087994377928,59.11898412389468),(39.54850639971376,58.713270635642914),(38.369758406141855,58.28688958537609),(38.85334732658162,58.06375936407028),(38.33953409861437,57.710289827306724),(38.73245009647167,57.48354156434209),(38.21863686850443,57.271721400459285),(38.97424455669155,56.87744603722649),(37.463029180317314,56.5623320541159),(38.94402024916407,56.05939028508024),(38.18841256097694,55.856355210835915),(38.490655636251795,55.53270067649592),(37.795496563119656,55.39562234093384),(38.30930979108689,55.154587013355666),(36.7074214921302,54.65063295250911),(37.31190764267989,53.92734063371401),(36.979440259877556,53.58783775557231),(37.855945178174615,52.91880107773497),(39.57873070724124,52.69956490610895),(38.33953409861437,53.281741738901104),(40.00187101262603,53.35396273604752),(39.54850639971376,53.58783775557231),(40.24366547284591,53.58783775557231),(39.97164670509855,53.98069568468355),(40.60635716317572,54.03398248547225),(40.39478701048334,54.44025165268903),(39.54850639971376,54.56310590284329),(39.54850639971376,54.87732350170489),(40.39478701048334,54.87732350170489),(40.39478701048334,55.24083903654295),(39.82052516746112,55.2752875586599),(39.760076552406154,55.75443792473942),(40.57613285564824,55.78844000174894),(40.425011318010824,56.19415599955667),(39.82052516746112,56.07626182891758),(39.79030085993364,56.41214455508424),(40.48545993306579,56.495655446714636),(40.33433839542836,56.95993246553937),(39.79030085993364,56.992876013526654),(39.72985224487867,57.46729112028032),(40.33433839542836,57.46729112028032),(40.24366547284591,58.04776787540811),(39.63917932229622,58.04776787540811),(39.63917932229622,58.382088724871295),(40.33433839542836,58.382088724871295),(40.45523562553831,58.9011152358548),(38.52087994377928,59.11898412389468)]]], [[(24.367675781249993,61.45977057029751),(19.577636718749993,58.67693767258692),(19.577636718749993,57.492213666700735),(19.445800781249996,55.87531083569678),(19.445800781249996,54.085173420886775),(17.468261718749996,53.014783245859235),(20.017089843749993,51.563412328675895),(21.203613281249993,50.205033264943324),(26.125488281249993,50.40151532278236),(27.22412109374999,48.980216985374994),(32.80517578124999,49.525208341974405),(35.26611328124999,48.74894534343292),(36.93603515624999,49.66762782262194),(42.56103515625,48.77791275550183),(43.92333984374999,49.8096315635631),(47.17529296875,49.152969656170455),(49.28466796875,50.54136296522162),(48.05419921875,51.17934297928929),(51.39404296875,52.48278022207825),(50.64697265625,53.014783245859235),(52.88818359375,53.93021986394004),(51.65771484374999,54.29088164657006),(52.66845703125,55.825973254619015),(50.25146484375,56.145549500679095),(51.92138671875,57.914847767009206),(49.15283203125,58.17070248348605),(49.59228515625,60.086762746260064),(47.043457031249986,59.88893689676584),(43.57177734375,61.37567331572748),(42.64892578125,60.630101766266705),(36.89208984374999,62.000904713685856),(36.01318359374999,61.143235250840576),(31.398925781249993,62.02152819100766),(30.563964843749996,61.05828537037917),(26.872558593749993,61.71070595883174),(26.652832031249993,61.10078883158897),(24.367675781249993,61.45977057029751)], [(24.455566406249993,59.42272750081452),(21.203613281249993,58.49369382056807),(21.335449218749993,56.89700392127261),(21.599121093749993,55.92458580482949),(25.202636718749993,55.998380955359636),(28.850097656249993,57.06463027327854),(27.09228515625,57.844750992890994),(28.806152343749996,59.17592824927138),(26.257324218749993,59.17592824927138),(24.455566406249993,59.42272750081452)], [(35.13427734375,59.84481485969107),(31.970214843749993,58.97266715450152),(33.20068359374999,56.776808316568406),(36.67236328125,56.41390137600675),(39.08935546874999,57.25528054528888),(42.69287109374999,58.03137242177638),(40.89111328124999,59.26588062825809),(37.28759765625,58.722598828043374),(37.11181640624999,59.66774058164964),(35.13427734375,59.84481485969107)], [(29.157714843749993,55.75184939173528),(22.565917968749993,55.128649068488784),(22.565917968749993,53.54030739150019),(22.038574218749996,51.48138289610097),(26.257324218749993,51.42661449707484),(30.124511718749993,50.54136296522162),(32.18994140624999,51.17934297928929),(30.124511718749993,53.173119202640635),(35.09033203124999,53.173119202640635),(33.11279296875,54.085173420886775),(29.597167968749993,55.50374985927513),(29.157714843749993,55.75184939173528)], [(42.82470703125,56.58369172128337),(36.584472656249986,55.329144408405085),(37.99072265625,53.592504809039355),(34.95849609374999,51.48138289610097),(36.54052734374999,50.40151532278236),(39.66064453124999,50.289339253291786),(39.79248046875,52.13348804077148),(41.77001953125,50.68079714532166),(44.49462890624999,51.97134580885171),(47.30712890624999,52.509534770327264),(44.05517578125,53.54030739150019),(46.60400390625,53.696706475303245),(47.61474609375,55.40406982700608),(45.37353515625,55.40406982700608),(42.82470703125,56.58369172128337)]])) format TSV; + +select '-------- Polygon with Polygon with Holes'; +select wkt(polygonsIntersectionSpherical([[(29.453587685533865,59.779570356240356),(29.393139070478895,52.276266797422124),(40.636581470703206,59.38168915000267),(41.21084331372543,59.103467777099866),(29.786055068336193,52.146627480315004),(31.23682182965546,52.16517054781818),(41.69443223416517,58.85424941916091),(42.51048853740727,58.47703162291134),(32.59691566839227,52.22075341251539),(34.289476889931414,52.22075341251539),(43.02430176537451,58.07974369546071),(43.02430176537451,57.25537683364851),(35.468224883503325,52.2022335126388),(37.16078610504247,52.23926559241349),(43.02430176537451,56.26136189644947),(43.02430176537451,55.326904361850836),(38.33953409861437,52.16517054781818),(40.09254393520848,52.16517054781818),(44.4146199116388,55.3097062225408),(44.47506852669377,59.80998197603594),(39.72985224487867,59.931351417569715),(30.23941968124846,53.67744677450975),(30.20919537372098,54.63314259659509),(38.73245009647167,59.94649146557819),(37.2816833351524,59.97675082987618),(30.23941968124846,55.2752875586599),(30.33009260383092,56.19415599955667),(36.28428118674541,59.96162460231375),(34.863738732953635,59.97675082987618),(30.178971066193498,56.97640788219866),(30.178971066193498,57.91957806959033),(33.65476643185424,59.94649146557819),(32.32489690064491,59.94649146557819),(30.481214141468342,58.85424941916091),(30.571887064050795,59.99187015036608),(29.453587685533865,59.779570356240356)]], [[(24.367675781249993,61.45977057029751),(19.577636718749993,58.67693767258692),(19.577636718749993,57.492213666700735),(19.445800781249996,55.87531083569678),(19.445800781249996,54.085173420886775),(17.468261718749996,53.014783245859235),(20.017089843749993,51.563412328675895),(21.203613281249993,50.205033264943324),(26.125488281249993,50.40151532278236),(27.22412109374999,48.980216985374994),(32.80517578124999,49.525208341974405),(35.26611328124999,48.74894534343292),(36.93603515624999,49.66762782262194),(42.56103515625,48.77791275550183),(43.92333984374999,49.8096315635631),(47.17529296875,49.152969656170455),(49.28466796875,50.54136296522162),(48.05419921875,51.17934297928929),(51.39404296875,52.48278022207825),(50.64697265625,53.014783245859235),(52.88818359375,53.93021986394004),(51.65771484374999,54.29088164657006),(52.66845703125,55.825973254619015),(50.25146484375,56.145549500679095),(51.92138671875,57.914847767009206),(49.15283203125,58.17070248348605),(49.59228515625,60.086762746260064),(47.043457031249986,59.88893689676584),(43.57177734375,61.37567331572748),(42.64892578125,60.630101766266705),(36.89208984374999,62.000904713685856),(36.01318359374999,61.143235250840576),(31.398925781249993,62.02152819100766),(30.563964843749996,61.05828537037917),(26.872558593749993,61.71070595883174),(26.652832031249993,61.10078883158897),(24.367675781249993,61.45977057029751)], [(24.455566406249993,59.42272750081452),(21.203613281249993,58.49369382056807),(21.335449218749993,56.89700392127261),(21.599121093749993,55.92458580482949),(25.202636718749993,55.998380955359636),(28.850097656249993,57.06463027327854),(27.09228515625,57.844750992890994),(28.806152343749996,59.17592824927138),(26.257324218749993,59.17592824927138),(24.455566406249993,59.42272750081452)], [(35.13427734375,59.84481485969107),(31.970214843749993,58.97266715450152),(33.20068359374999,56.776808316568406),(36.67236328125,56.41390137600675),(39.08935546874999,57.25528054528888),(42.69287109374999,58.03137242177638),(40.89111328124999,59.26588062825809),(37.28759765625,58.722598828043374),(37.11181640624999,59.66774058164964),(35.13427734375,59.84481485969107)], [(29.157714843749993,55.75184939173528),(22.565917968749993,55.128649068488784),(22.565917968749993,53.54030739150019),(22.038574218749996,51.48138289610097),(26.257324218749993,51.42661449707484),(30.124511718749993,50.54136296522162),(32.18994140624999,51.17934297928929),(30.124511718749993,53.173119202640635),(35.09033203124999,53.173119202640635),(33.11279296875,54.085173420886775),(29.597167968749993,55.50374985927513),(29.157714843749993,55.75184939173528)], [(42.82470703125,56.58369172128337),(36.584472656249986,55.329144408405085),(37.99072265625,53.592504809039355),(34.95849609374999,51.48138289610097),(36.54052734374999,50.40151532278236),(39.66064453124999,50.289339253291786),(39.79248046875,52.13348804077148),(41.77001953125,50.68079714532166),(44.49462890624999,51.97134580885171),(47.30712890624999,52.509534770327264),(44.05517578125,53.54030739150019),(46.60400390625,53.696706475303245),(47.61474609375,55.40406982700608),(45.37353515625,55.40406982700608),(42.82470703125,56.58369172128337)]])) format TSV; diff --git a/tests/queries/0_stateless/01307_polygon_perimeter.reference b/tests/queries/0_stateless/01307_polygon_perimeter.reference new file mode 100644 index 00000000000..209e3ef4b62 --- /dev/null +++ b/tests/queries/0_stateless/01307_polygon_perimeter.reference @@ -0,0 +1 @@ +20 diff --git a/tests/queries/0_stateless/01307_polygon_perimeter.sql b/tests/queries/0_stateless/01307_polygon_perimeter.sql new file mode 100644 index 00000000000..18f5b385826 --- /dev/null +++ b/tests/queries/0_stateless/01307_polygon_perimeter.sql @@ -0,0 +1 @@ +select polygonPerimeterCartesian([[[(0., 0.), (0., 5.), (5., 5.), (5., 0.), (0., 0.)]]]); diff --git a/tests/queries/0_stateless/01308_polygon_area.reference b/tests/queries/0_stateless/01308_polygon_area.reference new file mode 100644 index 00000000000..56d0c4ef174 --- /dev/null +++ b/tests/queries/0_stateless/01308_polygon_area.reference @@ -0,0 +1,2 @@ +25 +9.387703638370358e-8 diff --git a/tests/queries/0_stateless/01308_polygon_area.sql b/tests/queries/0_stateless/01308_polygon_area.sql new file mode 100644 index 00000000000..e3a44ad7d51 --- /dev/null +++ b/tests/queries/0_stateless/01308_polygon_area.sql @@ -0,0 +1,3 @@ +select polygonAreaCartesian([[[(0., 0.), (0., 5.), (5., 5.), (5., 0.)]]]); +select polygonAreaSpherical([[[(4.346693, 50.858306), (4.367945, 50.852455), (4.366227, 50.840809), (4.344961, 50.833264), (4.338074, 50.848677), (4.346693, 50.858306)]]]); +SELECT polygonAreaCartesian([]); -- { serverError 36 } diff --git a/tests/queries/0_stateless/01508_partition_pruning.reference b/tests/queries/0_stateless/01508_partition_pruning.reference deleted file mode 100644 index 0cc40d23b41..00000000000 --- a/tests/queries/0_stateless/01508_partition_pruning.reference +++ /dev/null @@ -1,244 +0,0 @@ ---------- tMM ---------------------------- -select uniqExact(_part), count() from tMM where toDate(d)=toDate('2020-09-15'); -0 0 -Selected 0 parts by partition key, 0 parts by primary key, 0 marks by primary key, 0 marks to read from 0 ranges - -select uniqExact(_part), count() from tMM where toDate(d)=toDate('2020-09-01'); -2 2880 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toDate(d)=toDate('2020-10-15'); -1 1440 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from tMM where toDate(d)='2020-09-15'; -0 0 -Selected 0 parts by partition key, 0 parts by primary key, 0 marks by primary key, 0 marks to read from 0 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d)=202009; -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toYYYYMMDD(d)=20200816; -2 2880 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toYYYYMMDD(d)=20201015; -1 1440 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from tMM where toDate(d)='2020-10-15'; -1 1440 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from tMM where d >= '2020-09-01 00:00:00' and d<'2020-10-15 00:00:00'; -3 15000 -Selected 3 parts by partition key, 3 parts by primary key, 3 marks by primary key, 3 marks to read from 3 ranges - -select uniqExact(_part), count() from tMM where d >= '2020-01-16 00:00:00' and d < toDateTime('2021-08-17 00:00:00'); -6 30000 -Selected 6 parts by partition key, 6 parts by primary key, 6 marks by primary key, 6 marks to read from 6 ranges - -select uniqExact(_part), count() from tMM where d >= '2020-09-16 00:00:00' and d < toDateTime('2020-10-01 00:00:00'); -0 0 -Selected 0 parts by partition key, 0 parts by primary key, 0 marks by primary key, 0 marks to read from 0 ranges - -select uniqExact(_part), count() from tMM where d >= '2020-09-12 00:00:00' and d < '2020-10-16 00:00:00'; -2 6440 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toStartOfDay(d) >= '2020-09-12 00:00:00'; -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toStartOfDay(d) = '2020-09-01 00:00:00'; -2 2880 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toStartOfDay(d) = '2020-10-01 00:00:00'; -1 1440 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from tMM where toStartOfDay(d) >= '2020-09-15 00:00:00' and d < '2020-10-16 00:00:00'; -2 6440 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d) between 202009 and 202010; -4 20000 -Selected 4 parts by partition key, 4 parts by primary key, 4 marks by primary key, 4 marks to read from 4 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d) between 202009 and 202009; -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d) between 202009 and 202010 and toStartOfDay(d) = '2020-10-01 00:00:00'; -1 1440 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d) >= 202009 and toStartOfDay(d) < '2020-10-02 00:00:00'; -3 11440 -Selected 3 parts by partition key, 3 parts by primary key, 3 marks by primary key, 3 marks to read from 3 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d) > 202009 and toStartOfDay(d) < '2020-10-02 00:00:00'; -1 1440 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d)+1 > 202009 and toStartOfDay(d) < '2020-10-02 00:00:00'; -3 11440 -Selected 3 parts by partition key, 3 parts by primary key, 3 marks by primary key, 3 marks to read from 3 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d)+1 > 202010 and toStartOfDay(d) < '2020-10-02 00:00:00'; -1 1440 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d)+1 > 202010; -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d-1)+1 = 202010; -3 9999 -Selected 3 parts by partition key, 3 parts by primary key, 3 marks by primary key, 3 marks to read from 3 ranges - -select uniqExact(_part), count() from tMM where toStartOfMonth(d) >= '2020-09-15'; -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toStartOfMonth(d) >= '2020-09-01'; -4 20000 -Selected 4 parts by partition key, 4 parts by primary key, 4 marks by primary key, 4 marks to read from 4 ranges - -select uniqExact(_part), count() from tMM where toStartOfMonth(d) >= '2020-09-01' and toStartOfMonth(d) < '2020-10-01'; -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d-1)+1 = 202010; -2 9999 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d)+1 > 202010; -1 10000 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from tMM where toYYYYMM(d) between 202009 and 202010; -2 20000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - ---------- tDD ---------------------------- -select uniqExact(_part), count() from tDD where toDate(d)=toDate('2020-09-24'); -1 10000 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() FROM tDD WHERE toDate(d) = toDate('2020-09-24'); -1 10000 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() FROM tDD WHERE toDate(d) = '2020-09-24'; -1 10000 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() FROM tDD WHERE toDate(d) >= '2020-09-23' and toDate(d) <= '2020-09-26'; -3 40000 -Selected 3 parts by partition key, 3 parts by primary key, 4 marks by primary key, 4 marks to read from 3 ranges - -select uniqExact(_part), count() FROM tDD WHERE toYYYYMMDD(d) >= 20200923 and toDate(d) <= '2020-09-26'; -3 40000 -Selected 3 parts by partition key, 3 parts by primary key, 4 marks by primary key, 4 marks to read from 3 ranges - ---------- sDD ---------------------------- -select uniqExact(_part), count() from sDD; -6 30000 -Selected 6 parts by partition key, 6 parts by primary key, 6 marks by primary key, 6 marks to read from 6 ranges - -select uniqExact(_part), count() from sDD where toYYYYMM(toDateTime(intDiv(d,1000),'UTC')-1)+1 = 202010; -3 9999 -Selected 3 parts by partition key, 3 parts by primary key, 3 marks by primary key, 3 marks to read from 3 ranges - -select uniqExact(_part), count() from sDD where toYYYYMM(toDateTime(intDiv(d,1000),'UTC')-1) = 202010; -2 9999 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from sDD where toYYYYMM(toDateTime(intDiv(d,1000),'UTC')-1) = 202110; -0 0 -Selected 0 parts by partition key, 0 parts by primary key, 0 marks by primary key, 0 marks to read from 0 ranges - -select uniqExact(_part), count() from sDD where toYYYYMM(toDateTime(intDiv(d,1000),'UTC'))+1 > 202009 and toStartOfDay(toDateTime(intDiv(d,1000),'UTC')) < toDateTime('2020-10-02 00:00:00','UTC'); -3 11440 -Selected 3 parts by partition key, 3 parts by primary key, 3 marks by primary key, 3 marks to read from 3 ranges - -select uniqExact(_part), count() from sDD where toYYYYMM(toDateTime(intDiv(d,1000),'UTC'))+1 > 202009 and toDateTime(intDiv(d,1000),'UTC') < toDateTime('2020-10-01 00:00:00','UTC'); -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from sDD where d >= 1598918400000; -4 20000 -Selected 4 parts by partition key, 4 parts by primary key, 4 marks by primary key, 4 marks to read from 4 ranges - -select uniqExact(_part), count() from sDD where d >= 1598918400000 and toYYYYMM(toDateTime(intDiv(d,1000),'UTC')-1) < 202010; -3 10001 -Selected 3 parts by partition key, 3 parts by primary key, 3 marks by primary key, 3 marks to read from 3 ranges - ---------- xMM ---------------------------- -select uniqExact(_part), count() from xMM where toStartOfDay(d) >= '2020-10-01 00:00:00'; -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d <= '2020-10-01 00:00:00'; -3 10001 -Selected 3 parts by partition key, 3 parts by primary key, 3 marks by primary key, 3 marks to read from 3 ranges - -select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d < '2020-10-01 00:00:00'; -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d <= '2020-10-01 00:00:00' and a=1; -1 1 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d <= '2020-10-01 00:00:00' and a<>3; -2 5001 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d < '2020-10-01 00:00:00' and a<>3; -1 5000 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d < '2020-11-01 00:00:00' and a = 1; -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from xMM where a = 1; -3 15000 -Selected 3 parts by partition key, 3 parts by primary key, 3 marks by primary key, 3 marks to read from 3 ranges - -select uniqExact(_part), count() from xMM where a = 66; -0 0 -Selected 0 parts by partition key, 0 parts by primary key, 0 marks by primary key, 0 marks to read from 0 ranges - -select uniqExact(_part), count() from xMM where a <> 66; -6 30000 -Selected 6 parts by partition key, 6 parts by primary key, 6 marks by primary key, 6 marks to read from 6 ranges - -select uniqExact(_part), count() from xMM where a = 2; -2 10000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from xMM where a = 1; -2 15000 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from xMM where toStartOfDay(d) >= '2020-10-01 00:00:00'; -1 10000 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - -select uniqExact(_part), count() from xMM where a <> 66; -5 30000 -Selected 5 parts by partition key, 5 parts by primary key, 5 marks by primary key, 5 marks to read from 5 ranges - -select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d <= '2020-10-01 00:00:00' and a<>3; -2 5001 -Selected 2 parts by partition key, 2 parts by primary key, 2 marks by primary key, 2 marks to read from 2 ranges - -select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d < '2020-10-01 00:00:00' and a<>3; -1 5000 -Selected 1 parts by partition key, 1 parts by primary key, 1 marks by primary key, 1 marks to read from 1 ranges - diff --git a/tests/queries/0_stateless/01508_partition_pruning.queries b/tests/queries/0_stateless/01508_partition_pruning_long.queries similarity index 100% rename from tests/queries/0_stateless/01508_partition_pruning.queries rename to tests/queries/0_stateless/01508_partition_pruning_long.queries diff --git a/tests/queries/0_stateless/01508_partition_pruning_long.reference b/tests/queries/0_stateless/01508_partition_pruning_long.reference new file mode 100644 index 00000000000..70f529c6058 --- /dev/null +++ b/tests/queries/0_stateless/01508_partition_pruning_long.reference @@ -0,0 +1,244 @@ +--------- tMM ---------------------------- +select uniqExact(_part), count() from tMM where toDate(d)=toDate('2020-09-15'); +0 0 +Selected 0/6 parts by partition key, 0 parts by primary key, 0/0 marks by primary key, 0 marks to read from 0 ranges + +select uniqExact(_part), count() from tMM where toDate(d)=toDate('2020-09-01'); +2 2880 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toDate(d)=toDate('2020-10-15'); +1 1440 +Selected 1/6 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from tMM where toDate(d)='2020-09-15'; +0 0 +Selected 0/6 parts by partition key, 0 parts by primary key, 0/0 marks by primary key, 0 marks to read from 0 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d)=202009; +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toYYYYMMDD(d)=20200816; +2 2880 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toYYYYMMDD(d)=20201015; +1 1440 +Selected 1/6 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from tMM where toDate(d)='2020-10-15'; +1 1440 +Selected 1/6 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from tMM where d >= '2020-09-01 00:00:00' and d<'2020-10-15 00:00:00'; +3 15000 +Selected 3/6 parts by partition key, 3 parts by primary key, 3/6 marks by primary key, 3 marks to read from 3 ranges + +select uniqExact(_part), count() from tMM where d >= '2020-01-16 00:00:00' and d < toDateTime('2021-08-17 00:00:00'); +6 30000 +Selected 6/6 parts by partition key, 6 parts by primary key, 6/12 marks by primary key, 6 marks to read from 6 ranges + +select uniqExact(_part), count() from tMM where d >= '2020-09-16 00:00:00' and d < toDateTime('2020-10-01 00:00:00'); +0 0 +Selected 0/6 parts by partition key, 0 parts by primary key, 0/0 marks by primary key, 0 marks to read from 0 ranges + +select uniqExact(_part), count() from tMM where d >= '2020-09-12 00:00:00' and d < '2020-10-16 00:00:00'; +2 6440 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toStartOfDay(d) >= '2020-09-12 00:00:00'; +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toStartOfDay(d) = '2020-09-01 00:00:00'; +2 2880 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toStartOfDay(d) = '2020-10-01 00:00:00'; +1 1440 +Selected 1/6 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from tMM where toStartOfDay(d) >= '2020-09-15 00:00:00' and d < '2020-10-16 00:00:00'; +2 6440 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d) between 202009 and 202010; +4 20000 +Selected 4/6 parts by partition key, 4 parts by primary key, 4/8 marks by primary key, 4 marks to read from 4 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d) between 202009 and 202009; +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d) between 202009 and 202010 and toStartOfDay(d) = '2020-10-01 00:00:00'; +1 1440 +Selected 1/6 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d) >= 202009 and toStartOfDay(d) < '2020-10-02 00:00:00'; +3 11440 +Selected 3/6 parts by partition key, 3 parts by primary key, 3/6 marks by primary key, 3 marks to read from 3 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d) > 202009 and toStartOfDay(d) < '2020-10-02 00:00:00'; +1 1440 +Selected 1/6 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d)+1 > 202009 and toStartOfDay(d) < '2020-10-02 00:00:00'; +3 11440 +Selected 3/6 parts by partition key, 3 parts by primary key, 3/6 marks by primary key, 3 marks to read from 3 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d)+1 > 202010 and toStartOfDay(d) < '2020-10-02 00:00:00'; +1 1440 +Selected 1/6 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d)+1 > 202010; +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d-1)+1 = 202010; +3 9999 +Selected 3/6 parts by partition key, 3 parts by primary key, 3/6 marks by primary key, 3 marks to read from 3 ranges + +select uniqExact(_part), count() from tMM where toStartOfMonth(d) >= '2020-09-15'; +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toStartOfMonth(d) >= '2020-09-01'; +4 20000 +Selected 4/6 parts by partition key, 4 parts by primary key, 4/8 marks by primary key, 4 marks to read from 4 ranges + +select uniqExact(_part), count() from tMM where toStartOfMonth(d) >= '2020-09-01' and toStartOfMonth(d) < '2020-10-01'; +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d-1)+1 = 202010; +2 9999 +Selected 2/3 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d)+1 > 202010; +1 10000 +Selected 1/3 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from tMM where toYYYYMM(d) between 202009 and 202010; +2 20000 +Selected 2/3 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +--------- tDD ---------------------------- +select uniqExact(_part), count() from tDD where toDate(d)=toDate('2020-09-24'); +1 10000 +Selected 1/4 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() FROM tDD WHERE toDate(d) = toDate('2020-09-24'); +1 10000 +Selected 1/4 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() FROM tDD WHERE toDate(d) = '2020-09-24'; +1 10000 +Selected 1/4 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() FROM tDD WHERE toDate(d) >= '2020-09-23' and toDate(d) <= '2020-09-26'; +3 40000 +Selected 3/4 parts by partition key, 3 parts by primary key, 4/7 marks by primary key, 4 marks to read from 3 ranges + +select uniqExact(_part), count() FROM tDD WHERE toYYYYMMDD(d) >= 20200923 and toDate(d) <= '2020-09-26'; +3 40000 +Selected 3/4 parts by partition key, 3 parts by primary key, 4/7 marks by primary key, 4 marks to read from 3 ranges + +--------- sDD ---------------------------- +select uniqExact(_part), count() from sDD; +6 30000 +Selected 6/6 parts by partition key, 6 parts by primary key, 6/12 marks by primary key, 6 marks to read from 6 ranges + +select uniqExact(_part), count() from sDD where toYYYYMM(toDateTime(intDiv(d,1000),'UTC')-1)+1 = 202010; +3 9999 +Selected 3/6 parts by partition key, 3 parts by primary key, 3/6 marks by primary key, 3 marks to read from 3 ranges + +select uniqExact(_part), count() from sDD where toYYYYMM(toDateTime(intDiv(d,1000),'UTC')-1) = 202010; +2 9999 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from sDD where toYYYYMM(toDateTime(intDiv(d,1000),'UTC')-1) = 202110; +0 0 +Selected 0/6 parts by partition key, 0 parts by primary key, 0/0 marks by primary key, 0 marks to read from 0 ranges + +select uniqExact(_part), count() from sDD where toYYYYMM(toDateTime(intDiv(d,1000),'UTC'))+1 > 202009 and toStartOfDay(toDateTime(intDiv(d,1000),'UTC')) < toDateTime('2020-10-02 00:00:00','UTC'); +3 11440 +Selected 3/6 parts by partition key, 3 parts by primary key, 3/6 marks by primary key, 3 marks to read from 3 ranges + +select uniqExact(_part), count() from sDD where toYYYYMM(toDateTime(intDiv(d,1000),'UTC'))+1 > 202009 and toDateTime(intDiv(d,1000),'UTC') < toDateTime('2020-10-01 00:00:00','UTC'); +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from sDD where d >= 1598918400000; +4 20000 +Selected 4/6 parts by partition key, 4 parts by primary key, 4/8 marks by primary key, 4 marks to read from 4 ranges + +select uniqExact(_part), count() from sDD where d >= 1598918400000 and toYYYYMM(toDateTime(intDiv(d,1000),'UTC')-1) < 202010; +3 10001 +Selected 3/6 parts by partition key, 3 parts by primary key, 3/6 marks by primary key, 3 marks to read from 3 ranges + +--------- xMM ---------------------------- +select uniqExact(_part), count() from xMM where toStartOfDay(d) >= '2020-10-01 00:00:00'; +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d <= '2020-10-01 00:00:00'; +3 10001 +Selected 3/6 parts by partition key, 3 parts by primary key, 3/6 marks by primary key, 3 marks to read from 3 ranges + +select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d < '2020-10-01 00:00:00'; +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d <= '2020-10-01 00:00:00' and a=1; +1 1 +Selected 1/6 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d <= '2020-10-01 00:00:00' and a<>3; +2 5001 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d < '2020-10-01 00:00:00' and a<>3; +1 5000 +Selected 1/6 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d < '2020-11-01 00:00:00' and a = 1; +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from xMM where a = 1; +3 15000 +Selected 3/6 parts by partition key, 3 parts by primary key, 3/6 marks by primary key, 3 marks to read from 3 ranges + +select uniqExact(_part), count() from xMM where a = 66; +0 0 +Selected 0/6 parts by partition key, 0 parts by primary key, 0/0 marks by primary key, 0 marks to read from 0 ranges + +select uniqExact(_part), count() from xMM where a <> 66; +6 30000 +Selected 6/6 parts by partition key, 6 parts by primary key, 6/12 marks by primary key, 6 marks to read from 6 ranges + +select uniqExact(_part), count() from xMM where a = 2; +2 10000 +Selected 2/6 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from xMM where a = 1; +2 15000 +Selected 2/5 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from xMM where toStartOfDay(d) >= '2020-10-01 00:00:00'; +1 10000 +Selected 1/5 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + +select uniqExact(_part), count() from xMM where a <> 66; +5 30000 +Selected 5/5 parts by partition key, 5 parts by primary key, 5/10 marks by primary key, 5 marks to read from 5 ranges + +select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d <= '2020-10-01 00:00:00' and a<>3; +2 5001 +Selected 2/5 parts by partition key, 2 parts by primary key, 2/4 marks by primary key, 2 marks to read from 2 ranges + +select uniqExact(_part), count() from xMM where d >= '2020-09-01 00:00:00' and d < '2020-10-01 00:00:00' and a<>3; +1 5000 +Selected 1/5 parts by partition key, 1 parts by primary key, 1/2 marks by primary key, 1 marks to read from 1 ranges + diff --git a/tests/queries/0_stateless/01508_partition_pruning.sh b/tests/queries/0_stateless/01508_partition_pruning_long.sh similarity index 88% rename from tests/queries/0_stateless/01508_partition_pruning.sh rename to tests/queries/0_stateless/01508_partition_pruning_long.sh index b5ec6388d5c..1b3c524ac77 100755 --- a/tests/queries/0_stateless/01508_partition_pruning.sh +++ b/tests/queries/0_stateless/01508_partition_pruning_long.sh @@ -4,8 +4,8 @@ # Description of test result: # Test the correctness of the partition # pruning -# -# Script executes queries from a file 01508_partition_pruning.queries (1 line = 1 query) +# +# Script executes queries from a file 01508_partition_pruning_long.queries (1 line = 1 query) # Queries are started with 'select' (but NOT with 'SELECT') are executed with log_level=debug #------------------------------------------------------------------------------------------- @@ -18,7 +18,7 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) #export CURDIR=. -queries="${CURDIR}/01508_partition_pruning.queries" +queries="${CURDIR}/01508_partition_pruning_long.queries" while IFS= read -r sql do [ -z "$sql" ] && continue @@ -30,9 +30,7 @@ do ${CLICKHOUSE_CLIENT} --query "$sql" 2>&1 | grep -oh "Selected .* parts by partition key, *. parts by primary key, .* marks by primary key, .* marks to read from .* ranges.*$" CLICKHOUSE_CLIENT=$(echo ${CLICKHOUSE_CLIENT} | sed 's/--send_logs_level=debug/'"--send_logs_level=${CLICKHOUSE_CLIENT_SERVER_LOGS_LEVEL}"'/g') echo "" - else + else ${CLICKHOUSE_CLIENT} --query "$sql" - fi + fi done < "$queries" - - diff --git a/tests/queries/0_stateless/01541_max_memory_usage_for_user.reference b/tests/queries/0_stateless/01541_max_memory_usage_for_user_long.reference similarity index 100% rename from tests/queries/0_stateless/01541_max_memory_usage_for_user.reference rename to tests/queries/0_stateless/01541_max_memory_usage_for_user_long.reference diff --git a/tests/queries/0_stateless/01541_max_memory_usage_for_user.sh b/tests/queries/0_stateless/01541_max_memory_usage_for_user_long.sh similarity index 94% rename from tests/queries/0_stateless/01541_max_memory_usage_for_user.sh rename to tests/queries/0_stateless/01541_max_memory_usage_for_user_long.sh index c81bd1a6ce4..32877bfd0fe 100755 --- a/tests/queries/0_stateless/01541_max_memory_usage_for_user.sh +++ b/tests/queries/0_stateless/01541_max_memory_usage_for_user_long.sh @@ -66,4 +66,7 @@ echo 'OK' ${CLICKHOUSE_CLIENT} --query "DROP USER test_01541"; +# Reset max_memory_usage_for_user, so it will not affect other tests +${CLICKHOUSE_CLIENT} --max_memory_usage_for_user=0 -q "SELECT 1 FORMAT Null" + exit 0 diff --git a/tests/queries/0_stateless/01550_create_map_type.reference b/tests/queries/0_stateless/01550_create_map_type.reference index 877199e92d5..d4794ac1459 100644 --- a/tests/queries/0_stateless/01550_create_map_type.reference +++ b/tests/queries/0_stateless/01550_create_map_type.reference @@ -6,6 +6,8 @@ lisi female zhangsan gender +2020-01-01 {1:0,2:1} +2020-01-01 {1:0,2:-1} 1116 1117 1118 diff --git a/tests/queries/0_stateless/01550_create_map_type.sql b/tests/queries/0_stateless/01550_create_map_type.sql index 695a40c42b4..26bbf3c7dde 100644 --- a/tests/queries/0_stateless/01550_create_map_type.sql +++ b/tests/queries/0_stateless/01550_create_map_type.sql @@ -22,7 +22,21 @@ select a[b] from table_map; select b from table_map where a = map('name','lisi', 'gender', 'female'); drop table if exists table_map; --- Int type +-- Big Integer type + +create table table_map (d DATE, m Map(Int8, UInt256)) ENGINE = MergeTree() order by d; +insert into table_map values ('2020-01-01', map(1, 0, 2, 1)); +select * from table_map; +drop table table_map; + +-- Integer type + +create table table_map (d DATE, m Map(Int8, Int8)) ENGINE = MergeTree() order by d; +insert into table_map values ('2020-01-01', map(1, 0, 2, -1)); +select * from table_map; +drop table table_map; + +-- Unsigned Int type drop table if exists table_map; create table table_map(a Map(UInt8, UInt64), b UInt8) Engine = MergeTree() order by b; insert into table_map select map(number, number+5), number from numbers(1111,4); diff --git a/tests/queries/0_stateless/01551_mergetree_read_in_order_spread.reference b/tests/queries/0_stateless/01551_mergetree_read_in_order_spread.reference index fb07aec9dd5..becc626c1bb 100644 --- a/tests/queries/0_stateless/01551_mergetree_read_in_order_spread.reference +++ b/tests/queries/0_stateless/01551_mergetree_read_in_order_spread.reference @@ -2,7 +2,7 @@ ExpressionTransform (Aggregating) FinalizingSimpleTransform - AggregatingSortedTransform 3 → 1 + FinishAggregatingInOrderTransform 3 → 1 AggregatingInOrderTransform × 3 (Expression) ExpressionTransform × 3 diff --git a/tests/queries/0_stateless/01591_window_functions.reference b/tests/queries/0_stateless/01591_window_functions.reference index 217a8571d5f..d2543f0db75 100644 --- a/tests/queries/0_stateless/01591_window_functions.reference +++ b/tests/queries/0_stateless/01591_window_functions.reference @@ -920,3 +920,76 @@ FROM numbers(2) ; 1 0 1 1 +-- some true window functions -- rank and friends +select number, p, o, + count(*) over w, + rank() over w, + dense_rank() over w, + row_number() over w +from (select number, intDiv(number, 5) p, mod(number, 3) o + from numbers(31) order by o, number) t +window w as (partition by p order by o) +order by p, o, number +settings max_block_size = 2; +0 0 0 2 1 1 1 +3 0 0 2 1 1 2 +1 0 1 4 3 2 3 +4 0 1 4 3 2 4 +2 0 2 5 5 3 5 +6 1 0 2 1 1 1 +9 1 0 2 1 1 2 +7 1 1 3 3 2 3 +5 1 2 5 4 3 4 +8 1 2 5 4 3 5 +12 2 0 1 1 1 1 +10 2 1 3 2 2 2 +13 2 1 3 2 2 3 +11 2 2 5 4 3 4 +14 2 2 5 4 3 5 +15 3 0 2 1 1 2 +18 3 0 2 1 1 1 +16 3 1 4 3 2 3 +19 3 1 4 3 2 4 +17 3 2 5 5 3 5 +21 4 0 2 1 1 1 +24 4 0 2 1 1 2 +22 4 1 3 3 2 3 +20 4 2 5 4 3 5 +23 4 2 5 4 3 4 +27 5 0 1 1 1 1 +25 5 1 3 2 2 2 +28 5 1 3 2 2 3 +26 5 2 5 4 3 4 +29 5 2 5 4 3 5 +30 6 0 1 1 1 1 +-- our replacement for lag/lead +select + anyOrNull(number) + over (order by number rows between 1 preceding and 1 preceding), + anyOrNull(number) + over (order by number rows between 1 following and 1 following) +from numbers(5); +\N 1 +0 2 +1 3 +2 4 +3 \N +-- case-insensitive SQL-standard synonyms for any and anyLast +select + number, + fIrSt_VaLue(number) over w, + lAsT_vAlUe(number) over w +from numbers(10) +window w as (order by number range between 1 preceding and 1 following) +order by number +; +0 0 1 +1 0 2 +2 1 3 +3 2 4 +4 3 5 +5 4 6 +6 5 7 +7 6 8 +8 7 9 +9 8 9 diff --git a/tests/queries/0_stateless/01591_window_functions.sql b/tests/queries/0_stateless/01591_window_functions.sql index 8742562a621..03bd8371e23 100644 --- a/tests/queries/0_stateless/01591_window_functions.sql +++ b/tests/queries/0_stateless/01591_window_functions.sql @@ -315,3 +315,33 @@ SELECT max(number) OVER (ORDER BY number ASC NULLS FIRST) FROM numbers(2) ; + +-- some true window functions -- rank and friends +select number, p, o, + count(*) over w, + rank() over w, + dense_rank() over w, + row_number() over w +from (select number, intDiv(number, 5) p, mod(number, 3) o + from numbers(31) order by o, number) t +window w as (partition by p order by o) +order by p, o, number +settings max_block_size = 2; + +-- our replacement for lag/lead +select + anyOrNull(number) + over (order by number rows between 1 preceding and 1 preceding), + anyOrNull(number) + over (order by number rows between 1 following and 1 following) +from numbers(5); + +-- case-insensitive SQL-standard synonyms for any and anyLast +select + number, + fIrSt_VaLue(number) over w, + lAsT_vAlUe(number) over w +from numbers(10) +window w as (order by number range between 1 preceding and 1 following) +order by number +; diff --git a/tests/queries/0_stateless/01592_long_window_functions1.reference b/tests/queries/0_stateless/01592_long_window_functions1.reference new file mode 100644 index 00000000000..5160cca9c3e --- /dev/null +++ b/tests/queries/0_stateless/01592_long_window_functions1.reference @@ -0,0 +1,4 @@ +---- arrays ---- +6360452672161319041 +---- window f ---- +6360452672161319041 diff --git a/tests/queries/0_stateless/01592_long_window_functions1.sql b/tests/queries/0_stateless/01592_long_window_functions1.sql new file mode 100644 index 00000000000..bb0f77ff60a --- /dev/null +++ b/tests/queries/0_stateless/01592_long_window_functions1.sql @@ -0,0 +1,36 @@ +drop table if exists stack; + +set allow_experimental_window_functions = 1; +set max_insert_threads = 4; + +create table stack(item_id Int64, brand_id Int64, rack_id Int64, dt DateTime, expiration_dt DateTime, quantity UInt64) +Engine = MergeTree +partition by toYYYYMM(dt) +order by (brand_id, toStartOfHour(dt)); + +insert into stack +select number%99991, number%11, number%1111, toDateTime('2020-01-01 00:00:00')+number/100, + toDateTime('2020-02-01 00:00:00')+number/10, intDiv(number,100)+1 +from numbers_mt(10000000); + +select '---- arrays ----'; + +select cityHash64( toString( groupArray (tuple(*) ) )) from ( + select brand_id, rack_id, arrayJoin(arraySlice(arraySort(groupArray(quantity)),1,2)) quantity + from stack + group by brand_id, rack_id + order by brand_id, rack_id, quantity +) t; + + +select '---- window f ----'; + +select cityHash64( toString( groupArray (tuple(*) ) )) from ( + select brand_id, rack_id, quantity from + ( select brand_id, rack_id, quantity, row_number() over (partition by brand_id, rack_id order by quantity) rn + from stack ) as t0 + where rn <= 2 + order by brand_id, rack_id, quantity +) t; + +drop table if exists stack; diff --git a/tests/queries/0_stateless/01592_window_functions.reference b/tests/queries/0_stateless/01592_window_functions.reference new file mode 100644 index 00000000000..8ca5086821b --- /dev/null +++ b/tests/queries/0_stateless/01592_window_functions.reference @@ -0,0 +1,81 @@ +---- Q1 ---- +Dell Vostro 800.00 Laptop 850 +HP Elite 1200.00 Laptop 850 +Lenovo Thinkpad 700.00 Laptop 850 +Sony VAIO 700.00 Laptop 850 +HTC One 400.00 Smartphone 500 +Microsoft Lumia 200.00 Smartphone 500 +Nexus 500.00 Smartphone 500 +iPhone 900.00 Smartphone 500 +Kindle Fire 150.00 Tablet 350 +Samsung Galaxy Tab 200.00 Tablet 350 +iPad 700.00 Tablet 350 +---- Q2 ---- +Lenovo Thinkpad Laptop 700.00 1 +Sony VAIO Laptop 700.00 1 +Dell Vostro Laptop 800.00 3 +HP Elite Laptop 1200.00 4 +Microsoft Lumia Smartphone 200.00 1 +HTC One Smartphone 400.00 2 +Nexus Smartphone 500.00 3 +iPhone Smartphone 900.00 4 +Kindle Fire Tablet 150.00 1 +Samsung Galaxy Tab Tablet 200.00 2 +iPad Tablet 700.00 3 +---- Q3 ---- +HP Elite Laptop 1200.00 1 +Dell Vostro Laptop 800.00 2 +Lenovo Thinkpad Laptop 700.00 3 +Sony VAIO Laptop 700.00 4 +iPhone Smartphone 900.00 1 +Nexus Smartphone 500.00 2 +HTC One Smartphone 400.00 3 +Microsoft Lumia Smartphone 200.00 4 +iPad Tablet 700.00 1 +Samsung Galaxy Tab Tablet 200.00 2 +Kindle Fire Tablet 150.00 3 +---- Q4 ---- +Lenovo Thinkpad Laptop 700.00 700.00 1 +Sony VAIO Laptop 700.00 700.00 1 +Dell Vostro Laptop 800.00 700.00 2 +HP Elite Laptop 1200.00 700.00 3 +Microsoft Lumia Smartphone 200.00 200.00 1 +HTC One Smartphone 400.00 200.00 2 +Nexus Smartphone 500.00 200.00 3 +iPhone Smartphone 900.00 200.00 4 +---- Q5 ---- +Sony VAIO Laptop 700.00 700.00 +Lenovo Thinkpad Laptop 700.00 700.00 +HP Elite Laptop 1200.00 700.00 +Dell Vostro Laptop 800.00 700.00 +iPhone Smartphone 900.00 900.00 +Nexus Smartphone 500.00 900.00 +Microsoft Lumia Smartphone 200.00 900.00 +HTC One Smartphone 400.00 900.00 +iPad Tablet 700.00 700.00 +Samsung Galaxy Tab Tablet 200.00 700.00 +Kindle Fire Tablet 150.00 700.00 +---- Q6 ---- +Dell Vostro Laptop 800.00 1200.00 +HP Elite Laptop 1200.00 1200.00 +Lenovo Thinkpad Laptop 700.00 1200.00 +Sony VAIO Laptop 700.00 1200.00 +HTC One Smartphone 400.00 900.00 +Microsoft Lumia Smartphone 200.00 900.00 +Nexus Smartphone 500.00 900.00 +iPhone Smartphone 900.00 900.00 +Kindle Fire Tablet 150.00 700.00 +Samsung Galaxy Tab Tablet 200.00 700.00 +iPad Tablet 700.00 700.00 +---- Q7 ---- +Dell Vostro 800.00 Laptop 733 850 +HP Elite 1200.00 Laptop 850 850 +Lenovo Thinkpad 700.00 Laptop 700 850 +Sony VAIO 700.00 Laptop 700 850 +HTC One 400.00 Smartphone 300 500 +Microsoft Lumia 200.00 Smartphone 200 500 +Nexus 500.00 Smartphone 367 500 +iPhone 900.00 Smartphone 500 500 +Kindle Fire 150.00 Tablet 150 350 +Samsung Galaxy Tab 200.00 Tablet 175 350 +iPad 700.00 Tablet 350 350 diff --git a/tests/queries/0_stateless/01592_window_functions.sql b/tests/queries/0_stateless/01592_window_functions.sql new file mode 100644 index 00000000000..8d5033fc821 --- /dev/null +++ b/tests/queries/0_stateless/01592_window_functions.sql @@ -0,0 +1,107 @@ +set allow_experimental_window_functions = 1; + +drop table if exists product_groups; +drop table if exists products; + +CREATE TABLE product_groups ( + group_id Int64, + group_name String +) Engine = Memory; + + +CREATE TABLE products ( + product_id Int64, + product_name String, + price DECIMAL(11, 2), + group_id Int64 +) Engine = Memory; + +INSERT INTO product_groups VALUES (1, 'Smartphone'),(2, 'Laptop'),(3, 'Tablet'); + +INSERT INTO products (product_id,product_name, group_id,price) VALUES (1, 'Microsoft Lumia', 1, 200), (2, 'HTC One', 1, 400), (3, 'Nexus', 1, 500), (4, 'iPhone', 1, 900),(5, 'HP Elite', 2, 1200),(6, 'Lenovo Thinkpad', 2, 700),(7, 'Sony VAIO', 2, 700),(8, 'Dell Vostro', 2, 800),(9, 'iPad', 3, 700),(10, 'Kindle Fire', 3, 150),(11, 'Samsung Galaxy Tab', 3, 200); + +select '---- Q1 ----'; + +SELECT + product_name, + price, + group_name, + AVG(price) OVER (PARTITION BY group_name) +FROM products INNER JOIN product_groups USING (group_id) +order by group_name, product_name, price; + +select '---- Q2 ----'; + +SELECT + product_name, + group_name, + price, + rank() OVER (PARTITION BY group_name ORDER BY price) rank +FROM products INNER JOIN product_groups USING (group_id) +order by group_name, rank, price; + +select '---- Q3 ----'; +SELECT + product_name, + group_name, + price, + row_number() OVER (PARTITION BY group_name ORDER BY price desc) rn +FROM products INNER JOIN product_groups USING (group_id) +ORDER BY group_name, rn; + +select '---- Q4 ----'; +SELECT * +FROM +( + SELECT + product_name, + group_name, + price, + min(price) OVER (PARTITION BY group_name) AS min_price, + dense_rank() OVER (PARTITION BY group_name ORDER BY price ASC) AS r + FROM products + INNER JOIN product_groups USING (group_id) +) AS t +WHERE min_price > 160 +ORDER BY + group_name ASC, + r ASC, + product_name ASC; + +select '---- Q5 ----'; +SELECT + product_name, + group_name, + price, + FIRST_VALUE (price) OVER (PARTITION BY group_name ORDER BY product_name desc) AS price_per_group_per_alphab +FROM products INNER JOIN product_groups USING (group_id) +order by group_name, product_name desc; + +select '---- Q6 ----'; +SELECT + product_name, + group_name, + price, + LAST_VALUE (price) OVER (PARTITION BY group_name ORDER BY + price RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS highest_price_per_group +FROM + products +INNER JOIN product_groups USING (group_id) +order by group_name, product_name; + +select '---- Q7 ----'; +select product_name, price, group_name, round(avg0), round(avg1) +from ( +SELECT + product_name, + price, + group_name, + avg(price) OVER (PARTITION BY group_name ORDER BY price) avg0, + avg(price) OVER (PARTITION BY group_name ORDER BY + price RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) avg1 +FROM products INNER JOIN product_groups USING (group_id)) t +order by group_name, product_name, price; + +drop table product_groups; +drop table products; diff --git a/tests/queries/0_stateless/01602_runningConcurrency.reference b/tests/queries/0_stateless/01602_runningConcurrency.reference new file mode 100644 index 00000000000..1bd238ccde8 --- /dev/null +++ b/tests/queries/0_stateless/01602_runningConcurrency.reference @@ -0,0 +1,19 @@ +Invocation with Date columns +1 +2 +3 +2 +1 +Invocation with DateTime +1 +2 +3 +2 +1 +Invocation with DateTime64 +1 +2 +3 +2 +1 +Erroneous cases diff --git a/tests/queries/0_stateless/01602_runningConcurrency.sql b/tests/queries/0_stateless/01602_runningConcurrency.sql new file mode 100644 index 00000000000..55b3aae867a --- /dev/null +++ b/tests/queries/0_stateless/01602_runningConcurrency.sql @@ -0,0 +1,51 @@ +-- +SELECT 'Invocation with Date columns'; + +DROP TABLE IF EXISTS runningConcurrency_test; +CREATE TABLE runningConcurrency_test(begin Date, end Date) ENGINE = Memory; + +INSERT INTO runningConcurrency_test VALUES ('2020-12-01', '2020-12-10'), ('2020-12-02', '2020-12-10'), ('2020-12-03', '2020-12-12'), ('2020-12-10', '2020-12-12'), ('2020-12-13', '2020-12-20'); +SELECT runningConcurrency(begin, end) FROM runningConcurrency_test; + +DROP TABLE runningConcurrency_test; + +-- +SELECT 'Invocation with DateTime'; + +DROP TABLE IF EXISTS runningConcurrency_test; +CREATE TABLE runningConcurrency_test(begin DateTime, end DateTime) ENGINE = Memory; + +INSERT INTO runningConcurrency_test VALUES ('2020-12-01 00:00:00', '2020-12-01 00:59:59'), ('2020-12-01 00:30:00', '2020-12-01 00:59:59'), ('2020-12-01 00:40:00', '2020-12-01 01:30:30'), ('2020-12-01 01:10:00', '2020-12-01 01:30:30'), ('2020-12-01 01:50:00', '2020-12-01 01:59:59'); +SELECT runningConcurrency(begin, end) FROM runningConcurrency_test; + +DROP TABLE runningConcurrency_test; + +-- +SELECT 'Invocation with DateTime64'; + +DROP TABLE IF EXISTS runningConcurrency_test; +CREATE TABLE runningConcurrency_test(begin DateTime64(3), end DateTime64(3)) ENGINE = Memory; + +INSERT INTO runningConcurrency_test VALUES ('2020-12-01 00:00:00.000', '2020-12-01 00:00:00.100'), ('2020-12-01 00:00:00.010', '2020-12-01 00:00:00.100'), ('2020-12-01 00:00:00.020', '2020-12-01 00:00:00.200'), ('2020-12-01 00:00:00.150', '2020-12-01 00:00:00.200'), ('2020-12-01 00:00:00.250', '2020-12-01 00:00:00.300'); +SELECT runningConcurrency(begin, end) FROM runningConcurrency_test; + +DROP TABLE runningConcurrency_test; + +-- +SELECT 'Erroneous cases'; + +-- Constant columns are currently not supported. +SELECT runningConcurrency(toDate(arrayJoin([1, 2])), toDate('2000-01-01')); -- { serverError 44 } + +-- Unsupported data types +SELECT runningConcurrency('strings are', 'not supported'); -- { serverError 43 } +SELECT runningConcurrency(NULL, NULL); -- { serverError 43 } +SELECT runningConcurrency(CAST(NULL, 'Nullable(DateTime)'), CAST(NULL, 'Nullable(DateTime)')); -- { serverError 43 } + +-- Mismatching data types +SELECT runningConcurrency(toDate('2000-01-01'), toDateTime('2000-01-01 00:00:00')); -- { serverError 43 } + +-- begin > end +SELECT runningConcurrency(toDate('2000-01-02'), toDate('2000-01-01')); -- { serverError 117 } + + diff --git a/tests/queries/0_stateless/01605_skip_idx_compact_parts.sql b/tests/queries/0_stateless/01605_skip_idx_compact_parts.sql index db28b7f9438..d57ccdcf9fc 100644 --- a/tests/queries/0_stateless/01605_skip_idx_compact_parts.sql +++ b/tests/queries/0_stateless/01605_skip_idx_compact_parts.sql @@ -3,14 +3,14 @@ CREATE TABLE skip_idx_comp_parts (a Int, b Int, index b_idx b TYPE minmax GRANUL ENGINE = MergeTree ORDER BY a SETTINGS index_granularity=256, merge_max_block_size=100; -SYSTEM STOP MERGES; +SYSTEM STOP MERGES skip_idx_comp_parts; INSERT INTO skip_idx_comp_parts SELECT number, number FROM numbers(200); INSERT INTO skip_idx_comp_parts SELECT number, number FROM numbers(200); INSERT INTO skip_idx_comp_parts SELECT number, number FROM numbers(200); INSERT INTO skip_idx_comp_parts SELECT number, number FROM numbers(200); -SYSTEM START MERGES; +SYSTEM START MERGES skip_idx_comp_parts; OPTIMIZE TABLE skip_idx_comp_parts FINAL; SELECT count() FROM skip_idx_comp_parts WHERE b > 100; diff --git a/tests/queries/0_stateless/01611_constant_folding_subqueries.reference b/tests/queries/0_stateless/01611_constant_folding_subqueries.reference index ac91b53b754..e46fd479413 100644 --- a/tests/queries/0_stateless/01611_constant_folding_subqueries.reference +++ b/tests/queries/0_stateless/01611_constant_folding_subqueries.reference @@ -5,5 +5,7 @@ SELECT (SELECT * FROM system.numbers LIMIT 1 OFFSET 1) AS n, toUInt64(10 / n) FO 1,10 EXPLAIN SYNTAX SELECT (SELECT * FROM system.numbers LIMIT 1 OFFSET 1) AS n, toUInt64(10 / n); SELECT - identity(cast(0, \'UInt64\')) AS n, + identity(CAST(0, \'UInt64\')) AS n, toUInt64(10 / n) +SELECT * FROM (WITH (SELECT * FROM system.numbers LIMIT 1 OFFSET 1) AS n, toUInt64(10 / n) as q SELECT * FROM system.one WHERE q > 0); +0 diff --git a/tests/queries/0_stateless/01611_constant_folding_subqueries.sql b/tests/queries/0_stateless/01611_constant_folding_subqueries.sql index abf67a8ed6a..59f057d1ec5 100644 --- a/tests/queries/0_stateless/01611_constant_folding_subqueries.sql +++ b/tests/queries/0_stateless/01611_constant_folding_subqueries.sql @@ -2,3 +2,4 @@ SELECT * FROM (SELECT (SELECT * FROM system.numbers LIMIT 1 OFFSET 1) AS n, toUInt64(10 / n)) FORMAT CSV; SELECT (SELECT * FROM system.numbers LIMIT 1 OFFSET 1) AS n, toUInt64(10 / n) FORMAT CSV; EXPLAIN SYNTAX SELECT (SELECT * FROM system.numbers LIMIT 1 OFFSET 1) AS n, toUInt64(10 / n); +SELECT * FROM (WITH (SELECT * FROM system.numbers LIMIT 1 OFFSET 1) AS n, toUInt64(10 / n) as q SELECT * FROM system.one WHERE q > 0); diff --git a/tests/queries/0_stateless/01637_nullable_fuzz3.reference b/tests/queries/0_stateless/01637_nullable_fuzz3.reference index d9cf16b9d2a..795a0159ac8 100644 --- a/tests/queries/0_stateless/01637_nullable_fuzz3.reference +++ b/tests/queries/0_stateless/01637_nullable_fuzz3.reference @@ -1,2 +1,6 @@ 0 + +0 + +0 0 0 diff --git a/tests/queries/0_stateless/01637_nullable_fuzz3.sql b/tests/queries/0_stateless/01637_nullable_fuzz3.sql index 21bf8999eae..6cfd0fc7d1c 100644 --- a/tests/queries/0_stateless/01637_nullable_fuzz3.sql +++ b/tests/queries/0_stateless/01637_nullable_fuzz3.sql @@ -1,4 +1,6 @@ DROP TABLE IF EXISTS t; CREATE TABLE t (`item_id` UInt64, `price_sold` Float32, `date` Date) ENGINE = MergeTree ORDER BY item_id; SELECT item_id FROM (SELECT item_id FROM t GROUP BY item_id WITH TOTALS) AS l FULL OUTER JOIN (SELECT item_id FROM t GROUP BY item_id WITH TOTALS) AS r USING (item_id); +SELECT item_id FROM (SELECT item_id FROM t GROUP BY item_id WITH TOTALS) AS l FULL OUTER JOIN (SELECT item_id FROM t GROUP BY item_id WITH TOTALS) AS r USING (item_id) SETTINGS join_use_nulls = '1'; +SELECT * FROM (SELECT item_id, sum(price_sold) as price_sold FROM t GROUP BY item_id WITH TOTALS) AS l FULL OUTER JOIN (SELECT item_id, sum(price_sold) as price_sold FROM t GROUP BY item_id WITH TOTALS) AS r USING (item_id) SETTINGS join_use_nulls = '1'; DROP TABLE t; diff --git a/tests/queries/0_stateless/01643_merge_tree_fsync_smoke.reference b/tests/queries/0_stateless/01643_merge_tree_fsync_smoke.reference index 654db9dbc86..f57d5df6efd 100644 --- a/tests/queries/0_stateless/01643_merge_tree_fsync_smoke.reference +++ b/tests/queries/0_stateless/01643_merge_tree_fsync_smoke.reference @@ -10,3 +10,5 @@ wide fsync_after_insert,fsync_part_directory 1 memory in_memory_parts_insert_sync 1 +wide fsync_part_directory,vertical +1 diff --git a/tests/queries/0_stateless/01643_merge_tree_fsync_smoke.sql b/tests/queries/0_stateless/01643_merge_tree_fsync_smoke.sql index 21ebb607693..644cf063a33 100644 --- a/tests/queries/0_stateless/01643_merge_tree_fsync_smoke.sql +++ b/tests/queries/0_stateless/01643_merge_tree_fsync_smoke.sql @@ -4,34 +4,47 @@ select 'default'; create table data_01643 (key Int) engine=MergeTree() order by key; insert into data_01643 values (1); select * from data_01643; +optimize table data_01643 final; drop table data_01643; select 'compact fsync_after_insert'; create table data_01643 (key Int) engine=MergeTree() order by key settings min_rows_for_wide_part=2, fsync_after_insert=1; insert into data_01643 values (1); select * from data_01643; +optimize table data_01643 final; drop table data_01643; select 'compact fsync_after_insert,fsync_part_directory'; create table data_01643 (key Int) engine=MergeTree() order by key settings min_rows_for_wide_part=2, fsync_after_insert=1, fsync_part_directory=1; insert into data_01643 values (1); select * from data_01643; +optimize table data_01643 final; drop table data_01643; select 'wide fsync_after_insert'; create table data_01643 (key Int) engine=MergeTree() order by key settings min_bytes_for_wide_part=0, fsync_after_insert=1; insert into data_01643 values (1); select * from data_01643; +optimize table data_01643 final; drop table data_01643; select 'wide fsync_after_insert,fsync_part_directory'; create table data_01643 (key Int) engine=MergeTree() order by key settings min_bytes_for_wide_part=0, fsync_after_insert=1, fsync_part_directory=1; insert into data_01643 values (1); select * from data_01643; +optimize table data_01643 final; drop table data_01643; select 'memory in_memory_parts_insert_sync'; create table data_01643 (key Int) engine=MergeTree() order by key settings min_rows_for_compact_part=2, in_memory_parts_insert_sync=1, fsync_after_insert=1, fsync_part_directory=1; insert into data_01643 values (1); select * from data_01643; +optimize table data_01643 final; +drop table data_01643; + +select 'wide fsync_part_directory,vertical'; +create table data_01643 (key Int) engine=MergeTree() order by key settings min_bytes_for_wide_part=0, fsync_part_directory=1, enable_vertical_merge_algorithm=1, vertical_merge_algorithm_min_rows_to_activate=1, vertical_merge_algorithm_min_columns_to_activate=1; +insert into data_01643 values (1); +select * from data_01643; +optimize table data_01643 final; drop table data_01643; diff --git a/tests/queries/0_stateless/01650_drop_part_and_deduplication_zookeeper.sql b/tests/queries/0_stateless/01650_drop_part_and_deduplication_zookeeper.sql index 50596680618..c3e459dfc49 100644 --- a/tests/queries/0_stateless/01650_drop_part_and_deduplication_zookeeper.sql +++ b/tests/queries/0_stateless/01650_drop_part_and_deduplication_zookeeper.sql @@ -5,7 +5,7 @@ CREATE TABLE partitioned_table ( partitioner UInt8, value String ) -ENGINE ReplicatedMergeTree('/clickhouse/test/01650_drop_part_and_deduplication/partitioned_table', '1') +ENGINE ReplicatedMergeTree('/clickhouse/01650_drop_part_and_deduplication_partitioned_table', '1') ORDER BY key PARTITION BY partitioner; @@ -16,24 +16,24 @@ INSERT INTO partitioned_table VALUES (11, 1, 'AA'), (22, 2, 'BB'), (33, 3, 'CC') SELECT partition_id, name FROM system.parts WHERE table = 'partitioned_table' AND database = currentDatabase() ORDER BY name; -SELECT substring(name, 1, 2), value FROM system.zookeeper WHERE path='/clickhouse/test/01650_drop_part_and_deduplication/partitioned_table/blocks/' ORDER BY value; +SELECT substring(name, 1, 2), value FROM system.zookeeper WHERE path='/clickhouse/01650_drop_part_and_deduplication_partitioned_table/blocks/' ORDER BY value; INSERT INTO partitioned_table VALUES (33, 3, 'CC'); -- must be deduplicated SELECT partition_id, name FROM system.parts WHERE table = 'partitioned_table' AND database = currentDatabase() ORDER BY name; -SELECT substring(name, 1, 2), value FROM system.zookeeper WHERE path='/clickhouse/test/01650_drop_part_and_deduplication/partitioned_table/blocks/' ORDER BY value; +SELECT substring(name, 1, 2), value FROM system.zookeeper WHERE path='/clickhouse/01650_drop_part_and_deduplication_partitioned_table/blocks/' ORDER BY value; ALTER TABLE partitioned_table DROP PART '3_1_1_0'; SELECT partition_id, name FROM system.parts WHERE table = 'partitioned_table' AND database = currentDatabase() ORDER BY name; -SELECT substring(name, 1, 2), value FROM system.zookeeper WHERE path='/clickhouse/test/01650_drop_part_and_deduplication/partitioned_table/blocks/' ORDER BY value; +SELECT substring(name, 1, 2), value FROM system.zookeeper WHERE path='/clickhouse/01650_drop_part_and_deduplication_partitioned_table/blocks/' ORDER BY value; INSERT INTO partitioned_table VALUES (33, 3, 'CC'); -- mustn't be deduplicated SELECT partition_id, name FROM system.parts WHERE table = 'partitioned_table' AND database = currentDatabase() ORDER BY name; -SELECT substring(name, 1, 2), value FROM system.zookeeper WHERE path='/clickhouse/test/01650_drop_part_and_deduplication/partitioned_table/blocks/' ORDER BY value; +SELECT substring(name, 1, 2), value FROM system.zookeeper WHERE path='/clickhouse/01650_drop_part_and_deduplication_partitioned_table/blocks/' ORDER BY value; DROP TABLE IF EXISTS partitioned_table; diff --git a/tests/queries/0_stateless/01653_move_conditions_from_join_on_to_where.reference b/tests/queries/0_stateless/01653_move_conditions_from_join_on_to_where.reference new file mode 100644 index 00000000000..19487c9f942 --- /dev/null +++ b/tests/queries/0_stateless/01653_move_conditions_from_join_on_to_where.reference @@ -0,0 +1,140 @@ +---------Q1---------- +2 2 2 20 +SELECT + a, + b, + table2.a, + table2.b +FROM table1 +ALL INNER JOIN +( + SELECT + a, + b + FROM table2 +) AS table2 ON a = table2.a +WHERE table2.b = toUInt32(20) +---------Q2---------- +2 2 2 20 +SELECT + a, + b, + table2.a, + table2.b +FROM table1 +ALL INNER JOIN +( + SELECT + a, + b + FROM table2 +) AS table2 ON a = table2.a +WHERE (table2.a < table2.b) AND (table2.b = toUInt32(20)) +---------Q3---------- +---------Q4---------- +6 40 +SELECT + a, + table2.b +FROM table1 +ALL INNER JOIN +( + SELECT + a, + b + FROM table2 +) AS table2 ON a = toUInt32(10 - table2.a) +WHERE (b = 6) AND (table2.b > 20) +---------Q5---------- +SELECT + a, + table2.b +FROM table1 +ALL INNER JOIN +( + SELECT + a, + b + FROM table2 + WHERE 0 +) AS table2 ON a = table2.a +WHERE 0 +---------Q6---------- +---------Q7---------- +0 0 0 0 +SELECT + a, + b, + table2.a, + table2.b +FROM table1 +ALL INNER JOIN +( + SELECT + a, + b + FROM table2 +) AS table2 ON a = table2.a +WHERE (table2.b < toUInt32(40)) AND (b < 1) +---------Q8---------- +---------Q9---will not be optimized---------- +SELECT + a, + b, + table2.a, + table2.b +FROM table1 +ALL LEFT JOIN +( + SELECT + a, + b + FROM table2 +) AS table2 ON (a = table2.a) AND (b = toUInt32(10)) +SELECT + a, + b, + table2.a, + table2.b +FROM table1 +ALL RIGHT JOIN +( + SELECT + a, + b + FROM table2 +) AS table2 ON (a = table2.a) AND (b = toUInt32(10)) +SELECT + a, + b, + table2.a, + table2.b +FROM table1 +ALL FULL OUTER JOIN +( + SELECT + a, + b + FROM table2 +) AS table2 ON (a = table2.a) AND (b = toUInt32(10)) +SELECT + a, + b, + table2.a, + table2.b +FROM table1 +ALL FULL OUTER JOIN +( + SELECT + a, + b + FROM table2 +) AS table2 ON (a = table2.a) AND (table2.b = toUInt32(10)) +WHERE a < toUInt32(20) +SELECT + a, + b, + table2.a, + table2.b +FROM table1 +CROSS JOIN table2 diff --git a/tests/queries/0_stateless/01653_move_conditions_from_join_on_to_where.sql b/tests/queries/0_stateless/01653_move_conditions_from_join_on_to_where.sql new file mode 100644 index 00000000000..23871a9c47c --- /dev/null +++ b/tests/queries/0_stateless/01653_move_conditions_from_join_on_to_where.sql @@ -0,0 +1,48 @@ +DROP TABLE IF EXISTS table1; +DROP TABLE IF EXISTS table2; + +CREATE TABLE table1 (a UInt32, b UInt32) ENGINE = Memory; +CREATE TABLE table2 (a UInt32, b UInt32) ENGINE = Memory; + +INSERT INTO table1 SELECT number, number FROM numbers(10); +INSERT INTO table2 SELECT number * 2, number * 20 FROM numbers(6); + +SELECT '---------Q1----------'; +SELECT * FROM table1 JOIN table2 ON (table1.a = table2.a) AND (table2.b = toUInt32(20)); +EXPLAIN SYNTAX SELECT * FROM table1 JOIN table2 ON (table1.a = table2.a) AND (table2.b = toUInt32(20)); + +SELECT '---------Q2----------'; +SELECT * FROM table1 JOIN table2 ON (table1.a = table2.a) AND (table2.a < table2.b) AND (table2.b = toUInt32(20)); +EXPLAIN SYNTAX SELECT * FROM table1 JOIN table2 ON (table1.a = table2.a) AND (table2.a < table2.b) AND (table2.b = toUInt32(20)); + +SELECT '---------Q3----------'; +SELECT * FROM table1 JOIN table2 ON (table1.a = toUInt32(table2.a + 5)) AND (table2.a < table1.b) AND (table2.b > toUInt32(20)); -- { serverError 48 } + +SELECT '---------Q4----------'; +SELECT table1.a, table2.b FROM table1 INNER JOIN table2 ON (table1.a = toUInt32(10 - table2.a)) AND (table1.b = 6) AND (table2.b > 20); +EXPLAIN SYNTAX SELECT table1.a, table2.b FROM table1 INNER JOIN table2 ON (table1.a = toUInt32(10 - table2.a)) AND (table1.b = 6) AND (table2.b > 20); + +SELECT '---------Q5----------'; +SELECT table1.a, table2.b FROM table1 JOIN table2 ON (table1.a = table2.a) AND (table1.b = 6) AND (table2.b > 20) AND (10 < 6); +EXPLAIN SYNTAX SELECT table1.a, table2.b FROM table1 JOIN table2 ON (table1.a = table2.a) AND (table1.b = 6) AND (table2.b > 20) AND (10 < 6); + +SELECT '---------Q6----------'; +SELECT table1.a, table2.b FROM table1 JOIN table2 ON (table1.b = 6) AND (table2.b > 20); -- { serverError 403 } + +SELECT '---------Q7----------'; +SELECT * FROM table1 JOIN table2 ON (table1.a = table2.a) AND (table2.b < toUInt32(40)) where table1.b < 1; +EXPLAIN SYNTAX SELECT * FROM table1 JOIN table2 ON (table1.a = table2.a) AND (table2.b < toUInt32(40)) where table1.b < 1; +SELECT * FROM table1 JOIN table2 ON (table1.a = table2.a) AND (table2.b < toUInt32(40)) where table1.b > 10; + +SELECT '---------Q8----------'; +SELECT * FROM table1 INNER JOIN table2 ON (table1.a = table2.a) AND (table2.b < toUInt32(table1, 10)); -- { serverError 47 } + +SELECT '---------Q9---will not be optimized----------'; +EXPLAIN SYNTAX SELECT * FROM table1 LEFT JOIN table2 ON (table1.a = table2.a) AND (table1.b = toUInt32(10)); +EXPLAIN SYNTAX SELECT * FROM table1 RIGHT JOIN table2 ON (table1.a = table2.a) AND (table1.b = toUInt32(10)); +EXPLAIN SYNTAX SELECT * FROM table1 FULL JOIN table2 ON (table1.a = table2.a) AND (table1.b = toUInt32(10)); +EXPLAIN SYNTAX SELECT * FROM table1 FULL JOIN table2 ON (table1.a = table2.a) AND (table2.b = toUInt32(10)) WHERE table1.a < toUInt32(20); +EXPLAIN SYNTAX SELECT * FROM table1 , table2; + +DROP TABLE table1; +DROP TABLE table2; diff --git a/tests/queries/0_stateless/01655_plan_optimizations.reference b/tests/queries/0_stateless/01655_plan_optimizations.reference index fda40305f9d..99b32b74ca7 100644 --- a/tests/queries/0_stateless/01655_plan_optimizations.reference +++ b/tests/queries/0_stateless/01655_plan_optimizations.reference @@ -1,7 +1,9 @@ -sipHash should be calculated after filtration +Too many optimizations applied to query plan +Too many optimizations applied to query plan +> sipHash should be calculated after filtration FUNCTION sipHash64 Filter column: equals -sorting steps should know about limit +> sorting steps should know about limit Limit 10 MergingSorted Limit 10 @@ -9,3 +11,115 @@ MergeSorting Limit 10 PartialSorting Limit 10 +-- filter push down -- +> filter should be pushed down after aggregating +Aggregating +Filter +0 1 +1 2 +2 3 +3 4 +4 5 +5 6 +6 7 +7 8 +8 9 +9 10 +> filter should be pushed down after aggregating, column after aggregation is const +COLUMN Const(UInt8) -> notEquals(y, 0) +Aggregating +Filter +Filter +0 1 1 +1 2 1 +2 3 1 +3 4 1 +4 5 1 +5 6 1 +6 7 1 +7 8 1 +8 9 1 +9 10 1 +> one condition of filter should be pushed down after aggregating, other condition is aliased +Filter column +ALIAS notEquals(s, 4) :: 1 -> and(notEquals(y, 0), notEquals(s, 4)) +Aggregating +Filter column: notEquals(y, 0) +0 1 +1 2 +2 3 +3 4 +5 6 +6 7 +7 8 +8 9 +9 10 +> one condition of filter should be pushed down after aggregating, other condition is casted +Filter column +FUNCTION CAST(minus(s, 4) :: 1, UInt8 :: 3) -> and(notEquals(y, 0), minus(s, 4)) +Aggregating +Filter column: notEquals(y, 0) +0 1 +1 2 +2 3 +3 4 +5 6 +6 7 +7 8 +8 9 +9 10 +> one condition of filter should be pushed down after aggregating, other two conditions are ANDed +Filter column +FUNCTION and(minus(s, 8) :: 1, minus(s, 4) :: 2) -> and(notEquals(y, 0), minus(s, 8), minus(s, 4)) +Aggregating +Filter column: notEquals(y, 0) +0 1 +1 2 +2 3 +3 4 +5 6 +6 7 +7 8 +9 10 +> two conditions of filter should be pushed down after aggregating and ANDed, one condition is aliased +Filter column +ALIAS notEquals(s, 8) :: 1 -> and(notEquals(y, 0), notEquals(s, 8), minus(y, 4)) +Aggregating +Filter column: and(notEquals(y, 0), minus(y, 4)) +0 1 +1 2 +2 3 +4 5 +5 6 +6 7 +7 8 +9 10 +> filter is split, one part is filtered before ARRAY JOIN +Filter column: and(notEquals(y, 2), notEquals(x, 0)) +ARRAY JOIN x +Filter column: notEquals(y, 2) +1 3 +> filter is pushed down before Distinct +Distinct +Distinct +Filter column: notEquals(y, 2) +0 0 +0 1 +1 0 +1 1 +> filter is pushed down before sorting steps +MergingSorted +MergeSorting +PartialSorting +Filter column: and(notEquals(x, 0), notEquals(y, 0)) +1 2 +1 1 +> filter is pushed down before TOTALS HAVING and aggregating +TotalsHaving +Aggregating +Filter column: notEquals(y, 2) +0 12 +1 15 +3 10 + +0 37 diff --git a/tests/queries/0_stateless/01655_plan_optimizations.sh b/tests/queries/0_stateless/01655_plan_optimizations.sh index 4f3541f9dde..3148dc4a597 100755 --- a/tests/queries/0_stateless/01655_plan_optimizations.sh +++ b/tests/queries/0_stateless/01655_plan_optimizations.sh @@ -4,7 +4,149 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # shellcheck source=../shell_config.sh . "$CURDIR"/../shell_config.sh -echo "sipHash should be calculated after filtration" +$CLICKHOUSE_CLIENT -q "select x + 1 from (select y + 2 as x from (select dummy + 3 as y)) settings query_plan_max_optimizations_to_apply = 1" 2>&1 | + grep -o "Too many optimizations applied to query plan" + +echo "> sipHash should be calculated after filtration" $CLICKHOUSE_CLIENT -q "explain actions = 1 select sum(x), sum(y) from (select sipHash64(number) as x, bitAnd(number, 1024) as y from numbers_mt(1000000000) limit 1000000000) where y = 0" | grep -o "FUNCTION sipHash64\|Filter column: equals" -echo "sorting steps should know about limit" +echo "> sorting steps should know about limit" $CLICKHOUSE_CLIENT -q "explain actions = 1 select number from (select number from numbers(500000000) order by -number) limit 10" | grep -o "MergingSorted\|MergeSorting\|PartialSorting\|Limit 10" + +echo "-- filter push down --" +echo "> filter should be pushed down after aggregating" +$CLICKHOUSE_CLIENT -q " + explain select * from (select sum(x), y from ( + select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 + settings enable_optimize_predicate_expression=0" | grep -o "Aggregating\|Filter" +$CLICKHOUSE_CLIENT -q " + select s, y from (select sum(x) as s, y from ( + select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 order by s, y + settings enable_optimize_predicate_expression=0" + +echo "> filter should be pushed down after aggregating, column after aggregation is const" +$CLICKHOUSE_CLIENT -q " + explain actions = 1 select s, y, y != 0 from (select sum(x) as s, y from ( + select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 + settings enable_optimize_predicate_expression=0" | grep -o "Aggregating\|Filter\|COLUMN Const(UInt8) -> notEquals(y, 0)" +$CLICKHOUSE_CLIENT -q " + select s, y, y != 0 from (select sum(x) as s, y from ( + select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 order by s, y, y != 0 + settings enable_optimize_predicate_expression=0" + +echo "> one condition of filter should be pushed down after aggregating, other condition is aliased" +$CLICKHOUSE_CLIENT -q " + explain actions = 1 select s, y from ( + select sum(x) as s, y from (select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 and s != 4 + settings enable_optimize_predicate_expression=0" | + grep -o "Aggregating\|Filter column\|Filter column: notEquals(y, 0)\|ALIAS notEquals(s, 4) :: 1 -> and(notEquals(y, 0), notEquals(s, 4))" +$CLICKHOUSE_CLIENT -q " + select s, y from ( + select sum(x) as s, y from (select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 and s != 4 order by s, y + settings enable_optimize_predicate_expression=0" + +echo "> one condition of filter should be pushed down after aggregating, other condition is casted" +$CLICKHOUSE_CLIENT -q " + explain actions = 1 select s, y from ( + select sum(x) as s, y from (select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 and s - 4 + settings enable_optimize_predicate_expression=0" | + grep -o "Aggregating\|Filter column\|Filter column: notEquals(y, 0)\|FUNCTION CAST(minus(s, 4) :: 1, UInt8 :: 3) -> and(notEquals(y, 0), minus(s, 4))" +$CLICKHOUSE_CLIENT -q " + select s, y from ( + select sum(x) as s, y from (select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 and s - 4 order by s, y + settings enable_optimize_predicate_expression=0" + +echo "> one condition of filter should be pushed down after aggregating, other two conditions are ANDed" +$CLICKHOUSE_CLIENT -q " + explain actions = 1 select s, y from ( + select sum(x) as s, y from (select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 and s - 8 and s - 4 + settings enable_optimize_predicate_expression=0" | + grep -o "Aggregating\|Filter column\|Filter column: notEquals(y, 0)\|FUNCTION and(minus(s, 8) :: 1, minus(s, 4) :: 2) -> and(notEquals(y, 0), minus(s, 8), minus(s, 4))" +$CLICKHOUSE_CLIENT -q " + select s, y from ( + select sum(x) as s, y from (select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 and s - 8 and s - 4 order by s, y + settings enable_optimize_predicate_expression=0" + +echo "> two conditions of filter should be pushed down after aggregating and ANDed, one condition is aliased" +$CLICKHOUSE_CLIENT -q " + explain actions = 1 select s, y from ( + select sum(x) as s, y from (select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 and s != 8 and y - 4 + settings enable_optimize_predicate_expression=0" | + grep -o "Aggregating\|Filter column\|Filter column: and(notEquals(y, 0), minus(y, 4))\|ALIAS notEquals(s, 8) :: 1 -> and(notEquals(y, 0), notEquals(s, 8), minus(y, 4))" +$CLICKHOUSE_CLIENT -q " + select s, y from ( + select sum(x) as s, y from (select number as x, number + 1 as y from numbers(10)) group by y + ) where y != 0 and s != 8 and y - 4 order by s, y + settings enable_optimize_predicate_expression=0" + +echo "> filter is split, one part is filtered before ARRAY JOIN" +$CLICKHOUSE_CLIENT -q " + explain actions = 1 select x, y from ( + select range(number) as x, number + 1 as y from numbers(3) + ) array join x where y != 2 and x != 0" | + grep -o "Filter column: and(notEquals(y, 2), notEquals(x, 0))\|ARRAY JOIN x\|Filter column: notEquals(y, 2)" +$CLICKHOUSE_CLIENT -q " + select x, y from ( + select range(number) as x, number + 1 as y from numbers(3) + ) array join x where y != 2 and x != 0 order by x, y" + +# echo "> filter is split, one part is filtered before Aggregating and Cube" +# $CLICKHOUSE_CLIENT -q " +# explain actions = 1 select * from ( +# select sum(x) as s, x, y from (select number as x, number + 1 as y from numbers(10)) group by x, y with cube +# ) where y != 0 and s != 4 +# settings enable_optimize_predicate_expression=0" | +# grep -o "Cube\|Aggregating\|Filter column: notEquals(y, 0)" +# $CLICKHOUSE_CLIENT -q " +# select s, x, y from ( +# select sum(x) as s, x, y from (select number as x, number + 1 as y from numbers(10)) group by x, y with cube +# ) where y != 0 and s != 4 order by s, x, y +# settings enable_optimize_predicate_expression=0" + +echo "> filter is pushed down before Distinct" +$CLICKHOUSE_CLIENT -q " + explain actions = 1 select x, y from ( + select distinct x, y from (select number % 2 as x, number % 3 as y from numbers(10)) + ) where y != 2 + settings enable_optimize_predicate_expression=0" | + grep -o "Distinct\|Filter column: notEquals(y, 2)" +$CLICKHOUSE_CLIENT -q " + select x, y from ( + select distinct x, y from (select number % 2 as x, number % 3 as y from numbers(10)) + ) where y != 2 order by x, y + settings enable_optimize_predicate_expression=0" + +echo "> filter is pushed down before sorting steps" +$CLICKHOUSE_CLIENT -q " + explain actions = 1 select x, y from ( + select number % 2 as x, number % 3 as y from numbers(6) order by y desc + ) where x != 0 and y != 0 + settings enable_optimize_predicate_expression = 0" | + grep -o "MergingSorted\|MergeSorting\|PartialSorting\|Filter column: and(notEquals(x, 0), notEquals(y, 0))" +$CLICKHOUSE_CLIENT -q " + select x, y from ( + select number % 2 as x, number % 3 as y from numbers(6) order by y desc + ) where x != 0 and y != 0 + settings enable_optimize_predicate_expression = 0" + +echo "> filter is pushed down before TOTALS HAVING and aggregating" +$CLICKHOUSE_CLIENT -q " + explain actions = 1 select * from ( + select y, sum(x) from (select number as x, number % 4 as y from numbers(10)) group by y with totals + ) where y != 2 + settings enable_optimize_predicate_expression=0" | + grep -o "TotalsHaving\|Aggregating\|Filter column: notEquals(y, 2)" +$CLICKHOUSE_CLIENT -q " + select * from ( + select y, sum(x) from (select number as x, number % 4 as y from numbers(10)) group by y with totals + ) where y != 2" diff --git a/tests/queries/0_stateless/01656_test_query_log_factories_info.reference b/tests/queries/0_stateless/01656_test_query_log_factories_info.reference index 3c93cd9ec26..af7feae5a38 100644 --- a/tests/queries/0_stateless/01656_test_query_log_factories_info.reference +++ b/tests/queries/0_stateless/01656_test_query_log_factories_info.reference @@ -1,8 +1,8 @@ -2 worl [123,1,1] 49 \N 50 4950 Nullable(UInt64) 50 -2 worl [123,1,1] 49 \N 50 4950 Nullable(UInt64) 50 +2 worl 1 1 0 4950 99 [123,1,1] 49 \N 50 4950 Nullable(UInt64) 50 +2 worl 1 1 0 4950 99 [123,1,1] 49 \N 50 4950 Nullable(UInt64) 50 arraySort(used_aggregate_functions) -['avg','count','groupBitAnd','sum','uniq'] +['avg','count','groupBitAnd','max','sum','uniq'] arraySort(used_aggregate_function_combinators) ['Array','If','OrDefault','OrNull'] @@ -11,7 +11,7 @@ arraySort(used_table_functions) ['numbers'] arraySort(used_functions) -['addDays','array','arrayFlatten','cast','modulo','plus','substring','toDate','toDayOfYear','toTypeName','toWeek'] +['CAST','CRC32','addDays','array','arrayFlatten','modulo','plus','pow','round','substring','tanh','toDate','toDayOfYear','toTypeName','toWeek'] arraySort(used_data_type_families) ['Array','Int32','Nullable','String'] @@ -20,5 +20,5 @@ used_database_engines ['Atomic'] arraySort(used_data_type_families) used_storages -['DateTime','Int64'] ['Memory'] +['Int64','datetime'] ['Memory'] diff --git a/tests/queries/0_stateless/01656_test_query_log_factories_info.sql b/tests/queries/0_stateless/01656_test_query_log_factories_info.sql index 9f374def8b5..3a890ce16f9 100644 --- a/tests/queries/0_stateless/01656_test_query_log_factories_info.sql +++ b/tests/queries/0_stateless/01656_test_query_log_factories_info.sql @@ -1,5 +1,9 @@ +SET database_atomic_wait_for_drop_and_detach_synchronously=1; + SELECT uniqArray([1, 1, 2]), SUBSTRING('Hello, world', 7, 5), + POW(1, 2), ROUND(TANh(1)), CrC32(''), + SUM(number), MAX(number), flatten([[[BIT_AND(123)]], [[mod(3, 2)], [CAST('1' AS INTEGER)]]]), week(toDate('2000-12-05')), CAST(arrayJoin([NULL, NULL]) AS Nullable(TEXT)), @@ -47,7 +51,7 @@ WHERE current_database = currentDatabase() AND type == 'QueryFinish' AND (query ORDER BY query_start_time DESC LIMIT 1 FORMAT TabSeparatedWithNames; SELECT ''; -CREATE OR REPLACE TABLE test_query_log_factories_info1.memory_table (id BIGINT, date DateTime) ENGINE=Memory(); +CREATE OR REPLACE TABLE test_query_log_factories_info1.memory_table (id BIGINT, date DATETIME) ENGINE=Memory(); SYSTEM FLUSH LOGS; SELECT arraySort(used_data_type_families), used_storages diff --git a/tests/queries/0_stateless/01658_read_file_to_stringcolumn.reference b/tests/queries/0_stateless/01658_read_file_to_stringcolumn.reference new file mode 100644 index 00000000000..87659c32e39 --- /dev/null +++ b/tests/queries/0_stateless/01658_read_file_to_stringcolumn.reference @@ -0,0 +1,25 @@ +aaaaaaaaa bbbbbbbbb +:0 +:0 +:0 +ccccccccc aaaaaaaaa bbbbbbbbb +ccccccccc aaaaaaaaa bbbbbbbbb +:0 +aaaaaaaaa +bbbbbbbbb +ccccccccc +:107 +:79 +:35 +:35 +:35 +699415 +aaaaaaaaa bbbbbbbbb +ccccccccc aaaaaaaaa bbbbbbbbb +ccccccccc aaaaaaaaa bbbbbbbbb +ccccccccc aaaaaaaaa bbbbbbbbb +ccccccccc aaaaaaaaa bbbbbbbbb +699415 0 +:0 +:107 +:79 diff --git a/tests/queries/0_stateless/01658_read_file_to_stringcolumn.sh b/tests/queries/0_stateless/01658_read_file_to_stringcolumn.sh new file mode 100755 index 00000000000..593f0e59ea7 --- /dev/null +++ b/tests/queries/0_stateless/01658_read_file_to_stringcolumn.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +set -eu + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +# Data preparation. +# Now we can get the user_files_path by use the table file function for trick. also we can get it by query as: +# "insert into function file('exist.txt', 'CSV', 'val1 char') values ('aaaa'); select _path from file('exist.txt', 'CSV', 'val1 char')" +user_files_path=$(clickhouse-client --query "select _path,_file from file('nonexist.txt', 'CSV', 'val1 char')" 2>&1 |grep Exception | awk '{gsub("/nonexist.txt","",$9); print $9}') + +mkdir -p ${user_files_path}/ +echo -n aaaaaaaaa > ${user_files_path}/a.txt +echo -n bbbbbbbbb > ${user_files_path}/b.txt +echo -n ccccccccc > ${user_files_path}/c.txt +echo -n ccccccccc > /tmp/c.txt +mkdir -p ${user_files_path}/dir + + +### 1st TEST in CLIENT mode. +${CLICKHOUSE_CLIENT} --query "drop table if exists data;" +${CLICKHOUSE_CLIENT} --query "create table data (A String, B String) engine=MergeTree() order by A;" + + +# Valid cases: +${CLICKHOUSE_CLIENT} --query "select file('${user_files_path}/a.txt'), file('${user_files_path}/b.txt');";echo ":"$? +${CLICKHOUSE_CLIENT} --query "insert into data select file('${user_files_path}/a.txt'), file('${user_files_path}/b.txt');";echo ":"$? +${CLICKHOUSE_CLIENT} --query "insert into data select file('${user_files_path}/a.txt'), file('${user_files_path}/b.txt');";echo ":"$? +${CLICKHOUSE_CLIENT} --query "select file('${user_files_path}/c.txt'), * from data";echo ":"$? +${CLICKHOUSE_CLIENT} --multiquery --query " + create table filenames(name String) engine=MergeTree() order by tuple(); + insert into filenames values ('a.txt'), ('b.txt'), ('c.txt'); + select file(name) from filenames format TSV; + drop table if exists filenames; +" + +# Invalid cases: (Here using sub-shell to catch exception avoiding the test quit) +# Test non-exists file +echo "clickhouse-client --query "'"select file('"'nonexist.txt'), file('${user_files_path}/b.txt')"'";echo :$?' | bash 2>/dev/null +# Test isDir +echo "clickhouse-client --query "'"select file('"'${user_files_path}/dir'), file('${user_files_path}/b.txt')"'";echo :$?' | bash 2>/dev/null +# Test path out of the user_files directory. It's not allowed in client mode +echo "clickhouse-client --query "'"select file('"'/tmp/c.txt'), file('${user_files_path}/b.txt')"'";echo :$?' | bash 2>/dev/null + +# Test relative path consists of ".." whose absolute path is out of the user_files directory. +echo "clickhouse-client --query "'"select file('"'${user_files_path}/../../../../tmp/c.txt'), file('b.txt')"'";echo :$?' | bash 2>/dev/null +echo "clickhouse-client --query "'"select file('"'../../../../a.txt'), file('${user_files_path}/b.txt')"'";echo :$?' | bash 2>/dev/null + + +### 2nd TEST in LOCAL mode. + +echo -n aaaaaaaaa > a.txt +echo -n bbbbbbbbb > b.txt +echo -n ccccccccc > c.txt +mkdir -p dir +#Test for large files, with length : 699415 +c_count=$(wc -c ${CURDIR}/01518_nullable_aggregate_states2.reference | awk '{print $1}') +echo $c_count + +# Valid cases: +# The default dir is the CWD path in LOCAL mode +${CLICKHOUSE_LOCAL} --query " + drop table if exists data; + create table data (A String, B String) engine=MergeTree() order by A; + select file('a.txt'), file('b.txt'); + insert into data select file('a.txt'), file('b.txt'); + insert into data select file('a.txt'), file('b.txt'); + select file('c.txt'), * from data; + select file('/tmp/c.txt'), * from data; + select $c_count, $c_count -length(file('${CURDIR}/01518_nullable_aggregate_states2.reference')) +" +echo ":"$? + + +# Invalid cases: (Here using sub-shell to catch exception avoiding the test quit) +# Test non-exists file +echo "clickhouse-local --query "'"select file('"'nonexist.txt'), file('b.txt')"'";echo :$?' | bash 2>/dev/null + +# Test isDir +echo "clickhouse-local --query "'"select file('"'dir'), file('b.txt')"'";echo :$?' | bash 2>/dev/null + +# Restore +rm -rf a.txt b.txt c.txt dir +rm -rf ${user_files_path}/a.txt +rm -rf ${user_files_path}/b.txt +rm -rf ${user_files_path}/c.txt +rm -rf /tmp/c.txt +rm -rf ${user_files_path}/dir diff --git a/tests/queries/0_stateless/01669_columns_declaration_serde.sql b/tests/queries/0_stateless/01669_columns_declaration_serde.sql index 8e3354d63cd..a6bf1184e9f 100644 --- a/tests/queries/0_stateless/01669_columns_declaration_serde.sql +++ b/tests/queries/0_stateless/01669_columns_declaration_serde.sql @@ -22,12 +22,12 @@ DROP TABLE IF EXISTS test_r1; DROP TABLE IF EXISTS test_r2; CREATE TABLE test_r1 (x UInt64, "\\" String DEFAULT '\r\n\t\\' || ' -') ENGINE = ReplicatedMergeTree('/clickhouse/test', 'r1') ORDER BY "\\"; +') ENGINE = ReplicatedMergeTree('/clickhouse/test_01669', 'r1') ORDER BY "\\"; INSERT INTO test_r1 ("\\") VALUES ('\\'); CREATE TABLE test_r2 (x UInt64, "\\" String DEFAULT '\r\n\t\\' || ' -') ENGINE = ReplicatedMergeTree('/clickhouse/test', 'r2') ORDER BY "\\"; +') ENGINE = ReplicatedMergeTree('/clickhouse/test_01669', 'r2') ORDER BY "\\"; SYSTEM SYNC REPLICA test_r2; diff --git a/tests/queries/0_stateless/01670_distributed_bytes_to_throw_insert.reference b/tests/queries/0_stateless/01670_distributed_bytes_to_throw_insert.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01670_distributed_bytes_to_throw_insert.sql b/tests/queries/0_stateless/01670_distributed_bytes_to_throw_insert.sql new file mode 100644 index 00000000000..1415c895290 --- /dev/null +++ b/tests/queries/0_stateless/01670_distributed_bytes_to_throw_insert.sql @@ -0,0 +1,14 @@ +drop table if exists dist_01670; +drop table if exists data_01670; + +create table data_01670 (key Int) engine=Null(); +create table dist_01670 (key Int) engine=Distributed(test_shard_localhost, currentDatabase(), data_01670) settings bytes_to_throw_insert=1; +system stop distributed sends dist_01670; +-- first batch is always OK, since there is no pending bytes yet +insert into dist_01670 select * from numbers(1) settings prefer_localhost_replica=0; +-- second will fail, because of bytes_to_throw_insert=1 +-- (previous block definitelly takes more, since it has header) +insert into dist_01670 select * from numbers(1) settings prefer_localhost_replica=0; -- { serverError 574 } +system flush distributed dist_01670; +drop table dist_01670; +drop table data_01670; diff --git a/tests/queries/0_stateless/01674_htm_xml_coarse_parse.reference b/tests/queries/0_stateless/01674_htm_xml_coarse_parse.reference new file mode 100644 index 00000000000..9cca4934551 --- /dev/null +++ b/tests/queries/0_stateless/01674_htm_xml_coarse_parse.reference @@ -0,0 +1,9 @@ + + +Here is CDTATA. +This is a white space test. +This is a complex test. world '); +SELECT extractTextFromHTML(''); +SELECT extractTextFromHTML('This is a white space test.'); +SELECT extractTextFromHTML('This is a complex test. Hello, world ]]>world ]]> hello\n]]>hello\n'); + +DROP TABLE IF EXISTS defaults; +CREATE TABLE defaults +( + stringColumn String +) ENGINE = Memory(); + +INSERT INTO defaults values ('hello, world'), (''), (''), ('white space collapse'); + +SELECT extractTextFromHTML(stringColumn) FROM defaults; +DROP table defaults; diff --git a/tests/queries/0_stateless/01675_distributed_bytes_to_delay_insert.reference b/tests/queries/0_stateless/01675_distributed_bytes_to_delay_insert.reference new file mode 100644 index 00000000000..d8c50c741ea --- /dev/null +++ b/tests/queries/0_stateless/01675_distributed_bytes_to_delay_insert.reference @@ -0,0 +1,3 @@ +max_delay_to_insert will throw +max_delay_to_insert will succeed +flushed diff --git a/tests/queries/0_stateless/01675_distributed_bytes_to_delay_insert.sh b/tests/queries/0_stateless/01675_distributed_bytes_to_delay_insert.sh new file mode 100755 index 00000000000..bad12e4cd58 --- /dev/null +++ b/tests/queries/0_stateless/01675_distributed_bytes_to_delay_insert.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash + +# NOTE: $SECONDS accuracy is second, so we need some delta, hence -1 in time conditions. + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +max_delay_to_insert=5 + +${CLICKHOUSE_CLIENT} -nq " +drop table if exists dist_01675; +drop table if exists data_01675; +" + +${CLICKHOUSE_CLIENT} -nq " +create table data_01675 (key Int) engine=Null(); +create table dist_01675 (key Int) engine=Distributed(test_shard_localhost, currentDatabase(), data_01675) settings bytes_to_delay_insert=1, max_delay_to_insert=$max_delay_to_insert; +system stop distributed sends dist_01675; +" + +# +# Case 1: max_delay_to_insert will throw. +# +echo "max_delay_to_insert will throw" + +start_seconds=$SECONDS +${CLICKHOUSE_CLIENT} --testmode -nq " +-- first batch is always OK, since there is no pending bytes yet +insert into dist_01675 select * from numbers(1) settings prefer_localhost_replica=0; +-- second will fail, because of bytes_to_delay_insert=1 and max_delay_to_insert=5, +-- while distributed sends is stopped. +-- +-- (previous block definitelly takes more, since it has header) +insert into dist_01675 select * from numbers(1) settings prefer_localhost_replica=0; -- { serverError 574 } +system flush distributed dist_01675; +" +end_seconds=$SECONDS + +if (( (end_seconds-start_seconds)<(max_delay_to_insert-1) )); then + echo "max_delay_to_insert was not satisfied ($end_seconds-$start_seconds)" +fi + +# +# Case 2: max_delay_to_insert will finally finished. +# +echo "max_delay_to_insert will succeed" + +max_delay_to_insert=10 +${CLICKHOUSE_CLIENT} -nq " +drop table dist_01675; +create table dist_01675 (key Int) engine=Distributed(test_shard_localhost, currentDatabase(), data_01675) settings bytes_to_delay_insert=1, max_delay_to_insert=$max_delay_to_insert; +system stop distributed sends dist_01675; +" + +flush_delay=4 +function flush_distributed_worker() +{ + sleep $flush_delay + ${CLICKHOUSE_CLIENT} -q "system flush distributed dist_01675" + echo flushed +} +flush_distributed_worker & + +start_seconds=$SECONDS +${CLICKHOUSE_CLIENT} --testmode -nq " +-- first batch is always OK, since there is no pending bytes yet +insert into dist_01675 select * from numbers(1) settings prefer_localhost_replica=0; +-- second will succcedd, due to SYSTEM FLUSH DISTRIBUTED in background. +insert into dist_01675 select * from numbers(1) settings prefer_localhost_replica=0; +" +end_seconds=$SECONDS +wait + +if (( (end_seconds-start_seconds)<(flush_delay-1) )); then + echo "max_delay_to_insert was not wait flush_delay ($end_seconds-$start_seconds)" +fi +if (( (end_seconds-start_seconds)>=(max_delay_to_insert-1) )); then + echo "max_delay_to_insert was overcommited ($end_seconds-$start_seconds)" +fi + + +${CLICKHOUSE_CLIENT} -nq " +drop table dist_01675; +drop table data_01675; +" diff --git a/tests/queries/0_stateless/01676_range_hashed_dictionary.reference b/tests/queries/0_stateless/01676_range_hashed_dictionary.reference new file mode 100644 index 00000000000..23a5180d99c --- /dev/null +++ b/tests/queries/0_stateless/01676_range_hashed_dictionary.reference @@ -0,0 +1,58 @@ +Dictionary not nullable +dictGet +0.33 +0.42 +0.46 +0.2 +0.4 +dictHas +1 +1 +1 +0 +select columns from dictionary +allColumns +1 2019-05-05 2019-05-20 0.33 +1 2019-05-21 2019-05-30 0.42 +2 2019-05-21 2019-05-30 0.46 +noColumns +1 +1 +1 +onlySpecificColumns +1 2019-05-05 0.33 +1 2019-05-21 0.42 +2 2019-05-21 0.46 +onlySpecificColumn +0.33 +0.42 +0.46 +Dictionary nullable +dictGet +0.33 +0.42 +\N +0.2 +0.4 +dictHas +1 +1 +1 +0 +select columns from dictionary +allColumns +1 2019-05-05 2019-05-20 0.33 +1 2019-05-21 2019-05-30 0.42 +2 2019-05-21 2019-05-30 \N +noColumns +1 +1 +1 +onlySpecificColumns +1 2019-05-05 0.33 +1 2019-05-21 0.42 +2 2019-05-21 \N +onlySpecificColumn +0.33 +0.42 +\N diff --git a/tests/queries/0_stateless/01676_range_hashed_dictionary.sql b/tests/queries/0_stateless/01676_range_hashed_dictionary.sql new file mode 100644 index 00000000000..455e850b239 --- /dev/null +++ b/tests/queries/0_stateless/01676_range_hashed_dictionary.sql @@ -0,0 +1,110 @@ +DROP DATABASE IF EXISTS database_for_range_dict; + +CREATE DATABASE database_for_range_dict; + +CREATE TABLE database_for_range_dict.date_table +( + CountryID UInt64, + StartDate Date, + EndDate Date, + Tax Float64 +) +ENGINE = MergeTree() +ORDER BY CountryID; + +INSERT INTO database_for_range_dict.date_table VALUES(1, toDate('2019-05-05'), toDate('2019-05-20'), 0.33); +INSERT INTO database_for_range_dict.date_table VALUES(1, toDate('2019-05-21'), toDate('2019-05-30'), 0.42); +INSERT INTO database_for_range_dict.date_table VALUES(2, toDate('2019-05-21'), toDate('2019-05-30'), 0.46); + +CREATE DICTIONARY database_for_range_dict.range_dictionary +( + CountryID UInt64, + StartDate Date, + EndDate Date, + Tax Float64 DEFAULT 0.2 +) +PRIMARY KEY CountryID +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'date_table' DB 'database_for_range_dict')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(RANGE_HASHED()) +RANGE(MIN StartDate MAX EndDate); + +SELECT 'Dictionary not nullable'; +SELECT 'dictGet'; +SELECT dictGet('database_for_range_dict.range_dictionary', 'Tax', toUInt64(1), toDate('2019-05-15')); +SELECT dictGet('database_for_range_dict.range_dictionary', 'Tax', toUInt64(1), toDate('2019-05-29')); +SELECT dictGet('database_for_range_dict.range_dictionary', 'Tax', toUInt64(2), toDate('2019-05-29')); +SELECT dictGet('database_for_range_dict.range_dictionary', 'Tax', toUInt64(2), toDate('2019-05-31')); +SELECT dictGetOrDefault('database_for_range_dict.range_dictionary', 'Tax', toUInt64(2), toDate('2019-05-31'), 0.4); +SELECT 'dictHas'; +SELECT dictHas('database_for_range_dict.range_dictionary', toUInt64(1), toDate('2019-05-15')); +SELECT dictHas('database_for_range_dict.range_dictionary', toUInt64(1), toDate('2019-05-29')); +SELECT dictHas('database_for_range_dict.range_dictionary', toUInt64(2), toDate('2019-05-29')); +SELECT dictHas('database_for_range_dict.range_dictionary', toUInt64(2), toDate('2019-05-31')); +SELECT 'select columns from dictionary'; +SELECT 'allColumns'; +SELECT * FROM database_for_range_dict.range_dictionary; +SELECT 'noColumns'; +SELECT 1 FROM database_for_range_dict.range_dictionary; +SELECT 'onlySpecificColumns'; +SELECT CountryID, StartDate, Tax FROM database_for_range_dict.range_dictionary; +SELECT 'onlySpecificColumn'; +SELECT Tax FROM database_for_range_dict.range_dictionary; + +DROP TABLE database_for_range_dict.date_table; +DROP DICTIONARY database_for_range_dict.range_dictionary; + +CREATE TABLE database_for_range_dict.date_table +( + CountryID UInt64, + StartDate Date, + EndDate Date, + Tax Nullable(Float64) +) +ENGINE = MergeTree() +ORDER BY CountryID; + +INSERT INTO database_for_range_dict.date_table VALUES(1, toDate('2019-05-05'), toDate('2019-05-20'), 0.33); +INSERT INTO database_for_range_dict.date_table VALUES(1, toDate('2019-05-21'), toDate('2019-05-30'), 0.42); +INSERT INTO database_for_range_dict.date_table VALUES(2, toDate('2019-05-21'), toDate('2019-05-30'), NULL); + +CREATE DICTIONARY database_for_range_dict.range_dictionary_nullable +( + CountryID UInt64, + StartDate Date, + EndDate Date, + Tax Nullable(Float64) DEFAULT 0.2 +) +PRIMARY KEY CountryID +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'date_table' DB 'database_for_range_dict')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(RANGE_HASHED()) +RANGE(MIN StartDate MAX EndDate); + +SELECT 'Dictionary nullable'; +SELECT 'dictGet'; +SELECT dictGet('database_for_range_dict.range_dictionary_nullable', 'Tax', toUInt64(1), toDate('2019-05-15')); +SELECT dictGet('database_for_range_dict.range_dictionary_nullable', 'Tax', toUInt64(1), toDate('2019-05-29')); +SELECT dictGet('database_for_range_dict.range_dictionary_nullable', 'Tax', toUInt64(2), toDate('2019-05-29')); +SELECT dictGet('database_for_range_dict.range_dictionary_nullable', 'Tax', toUInt64(2), toDate('2019-05-31')); +SELECT dictGetOrDefault('database_for_range_dict.range_dictionary_nullable', 'Tax', toUInt64(2), toDate('2019-05-31'), 0.4); +SELECT 'dictHas'; +SELECT dictHas('database_for_range_dict.range_dictionary_nullable', toUInt64(1), toDate('2019-05-15')); +SELECT dictHas('database_for_range_dict.range_dictionary_nullable', toUInt64(1), toDate('2019-05-29')); +SELECT dictHas('database_for_range_dict.range_dictionary_nullable', toUInt64(2), toDate('2019-05-29')); +SELECT dictHas('database_for_range_dict.range_dictionary_nullable', toUInt64(2), toDate('2019-05-31')); +SELECT 'select columns from dictionary'; +SELECT 'allColumns'; +SELECT * FROM database_for_range_dict.range_dictionary_nullable; +SELECT 'noColumns'; +SELECT 1 FROM database_for_range_dict.range_dictionary_nullable; +SELECT 'onlySpecificColumns'; +SELECT CountryID, StartDate, Tax FROM database_for_range_dict.range_dictionary_nullable; +SELECT 'onlySpecificColumn'; +SELECT Tax FROM database_for_range_dict.range_dictionary_nullable; + +DROP TABLE database_for_range_dict.date_table; +DROP DICTIONARY database_for_range_dict.range_dictionary_nullable; + +DROP DATABASE database_for_range_dict; + diff --git a/tests/queries/0_stateless/01676_reinterpret_as.reference b/tests/queries/0_stateless/01676_reinterpret_as.reference index bbde2d5ed57..459ca166dc1 100644 --- a/tests/queries/0_stateless/01676_reinterpret_as.reference +++ b/tests/queries/0_stateless/01676_reinterpret_as.reference @@ -25,6 +25,17 @@ Integer and Float types 0.2 1045220557 0.2 4596373779694328218 Integer and String types -1 49 -1 49 -11 12593 +1 1 49 +1 1 49 +11 11 12593 +Dates +1970-01-01 1970-01-01 +1970-01-01 03:00:00 1970-01-01 03:00:00 +1970-01-01 03:00:00.000 1970-01-01 03:00:00.000 +Decimals +5.00 0.49 +5.00 0.49 +5.00 0.49 +5.00 0.49 +0.00 +ReinterpretErrors diff --git a/tests/queries/0_stateless/01676_reinterpret_as.sql b/tests/queries/0_stateless/01676_reinterpret_as.sql index 88dc6437043..5eb94ed0a13 100644 --- a/tests/queries/0_stateless/01676_reinterpret_as.sql +++ b/tests/queries/0_stateless/01676_reinterpret_as.sql @@ -1,30 +1,42 @@ SELECT 'Into String'; -SELECT reinterpretAs(49, 'String'); +SELECT reinterpret(49, 'String'); SELECT 'Into FixedString'; -SELECT reinterpretAs(49, 'FixedString(1)'); -SELECT reinterpretAs(49, 'FixedString(2)'); -SELECT reinterpretAs(49, 'FixedString(3)'); -SELECT reinterpretAs(49, 'FixedString(4)'); +SELECT reinterpret(49, 'FixedString(1)'); +SELECT reinterpret(49, 'FixedString(2)'); +SELECT reinterpret(49, 'FixedString(3)'); +SELECT reinterpret(49, 'FixedString(4)'); SELECT reinterpretAsFixedString(49); SELECT 'Into Numeric Representable'; SELECT 'Integer and Integer types'; -SELECT reinterpretAs(257, 'UInt8'), reinterpretAsUInt8(257); -SELECT reinterpretAs(257, 'Int8'), reinterpretAsInt8(257); -SELECT reinterpretAs(257, 'UInt16'), reinterpretAsUInt16(257); -SELECT reinterpretAs(257, 'Int16'), reinterpretAsInt16(257); -SELECT reinterpretAs(257, 'UInt32'), reinterpretAsUInt32(257); -SELECT reinterpretAs(257, 'Int32'), reinterpretAsInt32(257); -SELECT reinterpretAs(257, 'UInt64'), reinterpretAsUInt64(257); -SELECT reinterpretAs(257, 'Int64'), reinterpretAsInt64(257); -SELECT reinterpretAs(257, 'Int128'), reinterpretAsInt128(257); -SELECT reinterpretAs(257, 'UInt256'), reinterpretAsUInt256(257); -SELECT reinterpretAs(257, 'Int256'), reinterpretAsInt256(257); +SELECT reinterpret(257, 'UInt8'), reinterpretAsUInt8(257); +SELECT reinterpret(257, 'Int8'), reinterpretAsInt8(257); +SELECT reinterpret(257, 'UInt16'), reinterpretAsUInt16(257); +SELECT reinterpret(257, 'Int16'), reinterpretAsInt16(257); +SELECT reinterpret(257, 'UInt32'), reinterpretAsUInt32(257); +SELECT reinterpret(257, 'Int32'), reinterpretAsInt32(257); +SELECT reinterpret(257, 'UInt64'), reinterpretAsUInt64(257); +SELECT reinterpret(257, 'Int64'), reinterpretAsInt64(257); +SELECT reinterpret(257, 'Int128'), reinterpretAsInt128(257); +SELECT reinterpret(257, 'UInt256'), reinterpretAsUInt256(257); +SELECT reinterpret(257, 'Int256'), reinterpretAsInt256(257); SELECT 'Integer and Float types'; -SELECT reinterpretAs(toFloat32(0.2), 'UInt32'), reinterpretAsUInt32(toFloat32(0.2)); -SELECT reinterpretAs(toFloat64(0.2), 'UInt64'), reinterpretAsUInt64(toFloat64(0.2)); +SELECT reinterpret(toFloat32(0.2), 'UInt32'), reinterpretAsUInt32(toFloat32(0.2)); +SELECT reinterpret(toFloat64(0.2), 'UInt64'), reinterpretAsUInt64(toFloat64(0.2)); SELECT reinterpretAsFloat32(a), reinterpretAsUInt32(toFloat32(0.2)) as a; SELECT reinterpretAsFloat64(a), reinterpretAsUInt64(toFloat64(0.2)) as a; SELECT 'Integer and String types'; -SELECT reinterpretAsString(a), reinterpretAsUInt8('1') as a; -SELECT reinterpretAsString(a), reinterpretAsUInt8('11') as a; -SELECT reinterpretAsString(a), reinterpretAsUInt16('11') as a; +SELECT reinterpret(a, 'String'), reinterpretAsString(a), reinterpretAsUInt8('1') as a; +SELECT reinterpret(a, 'String'), reinterpretAsString(a), reinterpretAsUInt8('11') as a; +SELECT reinterpret(a, 'String'), reinterpretAsString(a), reinterpretAsUInt16('11') as a; +SELECT 'Dates'; +SELECT reinterpret(0, 'Date'), reinterpret('', 'Date'); +SELECT reinterpret(0, 'DateTime'), reinterpret('', 'DateTime'); +SELECT reinterpret(0, 'DateTime64'), reinterpret('', 'DateTime64'); +SELECT 'Decimals'; +SELECT reinterpret(toDecimal32(5, 2), 'Decimal32(2)'), reinterpret('1', 'Decimal32(2)'); +SELECT reinterpret(toDecimal64(5, 2), 'Decimal64(2)'), reinterpret('1', 'Decimal64(2)');; +SELECT reinterpret(toDecimal128(5, 2), 'Decimal128(2)'), reinterpret('1', 'Decimal128(2)'); +SELECT reinterpret(toDecimal256(5, 2), 'Decimal256(2)'), reinterpret('1', 'Decimal256(2)'); +SELECT reinterpret(toDateTime64(0, 0), 'Decimal64(2)'); +SELECT 'ReinterpretErrors'; +SELECT reinterpret('123', 'FixedString(1)'); -- {serverError 43} diff --git a/tests/queries/0_stateless/01681_cache_dictionary_simple_key.reference b/tests/queries/0_stateless/01681_cache_dictionary_simple_key.reference new file mode 100644 index 00000000000..b3258e36f74 --- /dev/null +++ b/tests/queries/0_stateless/01681_cache_dictionary_simple_key.reference @@ -0,0 +1,66 @@ +Dictionary cache_dictionary_simple_key_simple_attributes +dictGet existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 value_0 value_second_0 +1 value_1 value_second_1 +2 value_2 value_second_2 +Dictionary cache_dictionary_simple_key_complex_attributes +dictGet existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 value_0 value_second_0 +1 value_1 \N +2 value_2 value_second_2 +Dictionary cache_dictionary_simple_key_hierarchy +dictGet +0 +0 +1 +1 +2 +dictGetHierarchy +[1] +[4,2,1] diff --git a/tests/queries/0_stateless/01681_cache_dictionary_simple_key.sql b/tests/queries/0_stateless/01681_cache_dictionary_simple_key.sql new file mode 100644 index 00000000000..ee2cde963d7 --- /dev/null +++ b/tests/queries/0_stateless/01681_cache_dictionary_simple_key.sql @@ -0,0 +1,123 @@ +DROP DATABASE IF EXISTS 01681_database_for_cache_dictionary; +CREATE DATABASE 01681_database_for_cache_dictionary; + +CREATE TABLE 01681_database_for_cache_dictionary.simple_key_simple_attributes_source_table +( + id UInt64, + value_first String, + value_second String +) +ENGINE = TinyLog; + +INSERT INTO 01681_database_for_cache_dictionary.simple_key_simple_attributes_source_table VALUES(0, 'value_0', 'value_second_0'); +INSERT INTO 01681_database_for_cache_dictionary.simple_key_simple_attributes_source_table VALUES(1, 'value_1', 'value_second_1'); +INSERT INTO 01681_database_for_cache_dictionary.simple_key_simple_attributes_source_table VALUES(2, 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes +( + id UInt64, + value_first String DEFAULT 'value_first_default', + value_second String DEFAULT 'value_second_default' +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_simple_attributes_source_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(CACHE(SIZE_IN_CELLS 10)); + +SELECT 'Dictionary cache_dictionary_simple_key_simple_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_first', number) as value_first, + dictGet('01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_first', number) as value_first, + dictGet('01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', number) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes; + +DROP DICTIONARY 01681_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes; +DROP TABLE 01681_database_for_cache_dictionary.simple_key_simple_attributes_source_table; + +CREATE TABLE 01681_database_for_cache_dictionary.simple_key_complex_attributes_source_table +( + id UInt64, + value_first String, + value_second Nullable(String) +) +ENGINE = TinyLog; + +INSERT INTO 01681_database_for_cache_dictionary.simple_key_complex_attributes_source_table VALUES(0, 'value_0', 'value_second_0'); +INSERT INTO 01681_database_for_cache_dictionary.simple_key_complex_attributes_source_table VALUES(1, 'value_1', NULL); +INSERT INTO 01681_database_for_cache_dictionary.simple_key_complex_attributes_source_table VALUES(2, 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes +( + id UInt64, + value_first String DEFAULT 'value_first_default', + value_second Nullable(String) DEFAULT 'value_second_default' +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_complex_attributes_source_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(CACHE(SIZE_IN_CELLS 10)); + +SELECT 'Dictionary cache_dictionary_simple_key_complex_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_first', number) as value_first, + dictGet('01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_first', number) as value_first, + dictGet('01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', number) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes; + +DROP DICTIONARY 01681_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes; +DROP TABLE 01681_database_for_cache_dictionary.simple_key_complex_attributes_source_table; + +CREATE TABLE 01681_database_for_cache_dictionary.simple_key_hierarchy_table +( + id UInt64, + parent_id UInt64 +) ENGINE = TinyLog(); + +INSERT INTO 01681_database_for_cache_dictionary.simple_key_hierarchy_table VALUES (1, 0); +INSERT INTO 01681_database_for_cache_dictionary.simple_key_hierarchy_table VALUES (2, 1); +INSERT INTO 01681_database_for_cache_dictionary.simple_key_hierarchy_table VALUES (3, 1); +INSERT INTO 01681_database_for_cache_dictionary.simple_key_hierarchy_table VALUES (4, 2); + +CREATE DICTIONARY 01681_database_for_cache_dictionary.cache_dictionary_simple_key_hierarchy +( + id UInt64, + parent_id UInt64 HIERARCHICAL +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_hierarchy_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(CACHE(SIZE_IN_CELLS 10)); + +SELECT 'Dictionary cache_dictionary_simple_key_hierarchy'; +SELECT 'dictGet'; +SELECT dictGet('01681_database_for_cache_dictionary.cache_dictionary_simple_key_hierarchy', 'parent_id', number) FROM system.numbers LIMIT 5; +SELECT 'dictGetHierarchy'; +SELECT dictGetHierarchy('01681_database_for_cache_dictionary.cache_dictionary_simple_key_hierarchy', toUInt64(1)); +SELECT dictGetHierarchy('01681_database_for_cache_dictionary.cache_dictionary_simple_key_hierarchy', toUInt64(4)); + +DROP DICTIONARY 01681_database_for_cache_dictionary.cache_dictionary_simple_key_hierarchy; +DROP TABLE 01681_database_for_cache_dictionary.simple_key_hierarchy_table; + +DROP DATABASE 01681_database_for_cache_dictionary; diff --git a/tests/queries/0_stateless/01682_cache_dictionary_complex_key.reference b/tests/queries/0_stateless/01682_cache_dictionary_complex_key.reference new file mode 100644 index 00000000000..a0f99ca13cc --- /dev/null +++ b/tests/queries/0_stateless/01682_cache_dictionary_complex_key.reference @@ -0,0 +1,56 @@ +Dictionary cache_dictionary_complex_key_simple_attributes +dictGet existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 id_key_0 value_0 value_second_0 +1 id_key_1 value_1 value_second_1 +2 id_key_2 value_2 value_second_2 +Dictionary cache_dictionary_complex_key_complex_attributes +dictGet existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 id_key_0 value_0 value_second_0 +1 id_key_1 value_1 \N +2 id_key_2 value_2 value_second_2 diff --git a/tests/queries/0_stateless/01682_cache_dictionary_complex_key.sql b/tests/queries/0_stateless/01682_cache_dictionary_complex_key.sql new file mode 100644 index 00000000000..65c56090c47 --- /dev/null +++ b/tests/queries/0_stateless/01682_cache_dictionary_complex_key.sql @@ -0,0 +1,97 @@ +DROP DATABASE IF EXISTS 01682_database_for_cache_dictionary; +CREATE DATABASE 01682_database_for_cache_dictionary; + +CREATE TABLE 01682_database_for_cache_dictionary.complex_key_simple_attributes_source_table +( + id UInt64, + id_key String, + value_first String, + value_second String +) +ENGINE = TinyLog; + +INSERT INTO 01682_database_for_cache_dictionary.complex_key_simple_attributes_source_table VALUES(0, 'id_key_0', 'value_0', 'value_second_0'); +INSERT INTO 01682_database_for_cache_dictionary.complex_key_simple_attributes_source_table VALUES(1, 'id_key_1', 'value_1', 'value_second_1'); +INSERT INTO 01682_database_for_cache_dictionary.complex_key_simple_attributes_source_table VALUES(2, 'id_key_2', 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes +( + id UInt64, + id_key String, + value_first String DEFAULT 'value_first_default', + value_second String DEFAULT 'value_second_default' +) +PRIMARY KEY id, id_key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'complex_key_simple_attributes_source_table' DB '01682_database_for_cache_dictionary')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(COMPLEX_KEY_CACHE(SIZE_IN_CELLS 10)); + +SELECT 'Dictionary cache_dictionary_complex_key_simple_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', (number, concat('id_key_', toString(number)))) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes; + +DROP DICTIONARY 01682_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes; +DROP TABLE 01682_database_for_cache_dictionary.complex_key_simple_attributes_source_table; + +CREATE TABLE 01682_database_for_cache_dictionary.complex_key_complex_attributes_source_table +( + id UInt64, + id_key String, + value_first String, + value_second Nullable(String) +) +ENGINE = TinyLog; + +INSERT INTO 01682_database_for_cache_dictionary.complex_key_complex_attributes_source_table VALUES(0, 'id_key_0', 'value_0', 'value_second_0'); +INSERT INTO 01682_database_for_cache_dictionary.complex_key_complex_attributes_source_table VALUES(1, 'id_key_1', 'value_1', NULL); +INSERT INTO 01682_database_for_cache_dictionary.complex_key_complex_attributes_source_table VALUES(2, 'id_key_2', 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes +( + id UInt64, + id_key String, + + value_first String DEFAULT 'value_first_default', + value_second Nullable(String) DEFAULT 'value_second_default' +) +PRIMARY KEY id, id_key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'complex_key_complex_attributes_source_table' DB '01682_database_for_cache_dictionary')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(COMPLEX_KEY_CACHE(SIZE_IN_CELLS 10)); + +SELECT 'Dictionary cache_dictionary_complex_key_complex_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', (number, concat('id_key_', toString(number)))) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes; + +DROP DICTIONARY 01682_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes; +DROP TABLE 01682_database_for_cache_dictionary.complex_key_complex_attributes_source_table; + +DROP DATABASE 01682_database_for_cache_dictionary; diff --git a/tests/queries/0_stateless/01683_flat_dictionary.reference b/tests/queries/0_stateless/01683_flat_dictionary.reference new file mode 100644 index 00000000000..b2a24a01738 --- /dev/null +++ b/tests/queries/0_stateless/01683_flat_dictionary.reference @@ -0,0 +1,58 @@ +Dictionary flat_dictionary_simple_key_simple_attributes +dictGet existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +Dictionary flat_dictionary_simple_key_complex_attributes +dictGet existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +Dictionary flat_dictionary_simple_key_hierarchy +dictGet +0 +0 +1 +1 +2 +dictGetHierarchy +[1] +[4,2,1] diff --git a/tests/queries/0_stateless/01683_flat_dictionary.sql b/tests/queries/0_stateless/01683_flat_dictionary.sql new file mode 100644 index 00000000000..c9f864c6a16 --- /dev/null +++ b/tests/queries/0_stateless/01683_flat_dictionary.sql @@ -0,0 +1,119 @@ +DROP DATABASE IF EXISTS 01681_database_for_flat_dictionary; +CREATE DATABASE 01681_database_for_flat_dictionary; + +CREATE TABLE 01681_database_for_flat_dictionary.simple_key_simple_attributes_source_table +( + id UInt64, + value_first String, + value_second String +) +ENGINE = TinyLog; + +INSERT INTO 01681_database_for_flat_dictionary.simple_key_simple_attributes_source_table VALUES(0, 'value_0', 'value_second_0'); +INSERT INTO 01681_database_for_flat_dictionary.simple_key_simple_attributes_source_table VALUES(1, 'value_1', 'value_second_1'); +INSERT INTO 01681_database_for_flat_dictionary.simple_key_simple_attributes_source_table VALUES(2, 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes +( + id UInt64, + value_first String DEFAULT 'value_first_default', + value_second String DEFAULT 'value_second_default' +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_simple_attributes_source_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(FLAT()); + +SELECT 'Dictionary flat_dictionary_simple_key_simple_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes', 'value_first', number) as value_first, + dictGet('01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes', 'value_first', number) as value_first, + dictGet('01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes', number) FROM system.numbers LIMIT 4; + +DROP DICTIONARY 01681_database_for_flat_dictionary.flat_dictionary_simple_key_simple_attributes; +DROP TABLE 01681_database_for_flat_dictionary.simple_key_simple_attributes_source_table; + +CREATE TABLE 01681_database_for_flat_dictionary.simple_key_complex_attributes_source_table +( + id UInt64, + value_first String, + value_second Nullable(String) +) +ENGINE = TinyLog; + +INSERT INTO 01681_database_for_flat_dictionary.simple_key_complex_attributes_source_table VALUES(0, 'value_0', 'value_second_0'); +INSERT INTO 01681_database_for_flat_dictionary.simple_key_complex_attributes_source_table VALUES(1, 'value_1', NULL); +INSERT INTO 01681_database_for_flat_dictionary.simple_key_complex_attributes_source_table VALUES(2, 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes +( + id UInt64, + value_first String DEFAULT 'value_first_default', + value_second Nullable(String) DEFAULT 'value_second_default' +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_complex_attributes_source_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(FLAT()); + +SELECT 'Dictionary flat_dictionary_simple_key_complex_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes', 'value_first', number) as value_first, + dictGet('01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes', 'value_first', number) as value_first, + dictGet('01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes', number) FROM system.numbers LIMIT 4; + +DROP DICTIONARY 01681_database_for_flat_dictionary.flat_dictionary_simple_key_complex_attributes; +DROP TABLE 01681_database_for_flat_dictionary.simple_key_complex_attributes_source_table; + +CREATE TABLE 01681_database_for_flat_dictionary.simple_key_hierarchy_table +( + id UInt64, + parent_id UInt64 +) ENGINE = TinyLog(); + +INSERT INTO 01681_database_for_flat_dictionary.simple_key_hierarchy_table VALUES (1, 0); +INSERT INTO 01681_database_for_flat_dictionary.simple_key_hierarchy_table VALUES (2, 1); +INSERT INTO 01681_database_for_flat_dictionary.simple_key_hierarchy_table VALUES (3, 1); +INSERT INTO 01681_database_for_flat_dictionary.simple_key_hierarchy_table VALUES (4, 2); + +CREATE DICTIONARY 01681_database_for_flat_dictionary.flat_dictionary_simple_key_hierarchy +( + id UInt64, + parent_id UInt64 HIERARCHICAL +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_hierarchy_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(FLAT()); + +SELECT 'Dictionary flat_dictionary_simple_key_hierarchy'; +SELECT 'dictGet'; +SELECT dictGet('01681_database_for_flat_dictionary.flat_dictionary_simple_key_hierarchy', 'parent_id', number) FROM system.numbers LIMIT 5; +SELECT 'dictGetHierarchy'; +SELECT dictGetHierarchy('01681_database_for_flat_dictionary.flat_dictionary_simple_key_hierarchy', toUInt64(1)); +SELECT dictGetHierarchy('01681_database_for_flat_dictionary.flat_dictionary_simple_key_hierarchy', toUInt64(4)); + +DROP DICTIONARY 01681_database_for_flat_dictionary.flat_dictionary_simple_key_hierarchy; +DROP TABLE 01681_database_for_flat_dictionary.simple_key_hierarchy_table; + +DROP DATABASE 01681_database_for_flat_dictionary; diff --git a/tests/queries/0_stateless/01684_insert_specify_shard_id.sql b/tests/queries/0_stateless/01684_insert_specify_shard_id.sql index ce1c7807b59..712fbfcc506 100644 --- a/tests/queries/0_stateless/01684_insert_specify_shard_id.sql +++ b/tests/queries/0_stateless/01684_insert_specify_shard_id.sql @@ -28,8 +28,8 @@ INSERT INTO x_dist SELECT * FROM numbers(10); -- { serverError 55 } INSERT INTO y_dist SELECT * FROM numbers(10); -- { serverError 55 } -- invalid shard id -INSERT INTO x_dist SELECT * FROM numbers(10) settings insert_shard_id = 3; -- { serverError 1003 } -INSERT INTO y_dist SELECT * FROM numbers(10) settings insert_shard_id = 3; -- { serverError 1003 } +INSERT INTO x_dist SELECT * FROM numbers(10) settings insert_shard_id = 3; -- { serverError 577 } +INSERT INTO y_dist SELECT * FROM numbers(10) settings insert_shard_id = 3; -- { serverError 577 } DROP TABLE x; DROP TABLE x_dist; diff --git a/tests/queries/0_stateless/01684_ssd_cache_dictionary_simple_key.reference b/tests/queries/0_stateless/01684_ssd_cache_dictionary_simple_key.reference new file mode 100644 index 00000000000..b3258e36f74 --- /dev/null +++ b/tests/queries/0_stateless/01684_ssd_cache_dictionary_simple_key.reference @@ -0,0 +1,66 @@ +Dictionary cache_dictionary_simple_key_simple_attributes +dictGet existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 value_0 value_second_0 +1 value_1 value_second_1 +2 value_2 value_second_2 +Dictionary cache_dictionary_simple_key_complex_attributes +dictGet existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 value_0 value_second_0 +1 value_1 \N +2 value_2 value_second_2 +Dictionary cache_dictionary_simple_key_hierarchy +dictGet +0 +0 +1 +1 +2 +dictGetHierarchy +[1] +[4,2,1] diff --git a/tests/queries/0_stateless/01684_ssd_cache_dictionary_simple_key.sql b/tests/queries/0_stateless/01684_ssd_cache_dictionary_simple_key.sql new file mode 100644 index 00000000000..3b327257fc4 --- /dev/null +++ b/tests/queries/0_stateless/01684_ssd_cache_dictionary_simple_key.sql @@ -0,0 +1,123 @@ +DROP DATABASE IF EXISTS 01684_database_for_cache_dictionary; +CREATE DATABASE 01684_database_for_cache_dictionary; + +CREATE TABLE 01684_database_for_cache_dictionary.simple_key_simple_attributes_source_table +( + id UInt64, + value_first String, + value_second String +) +ENGINE = TinyLog; + +INSERT INTO 01684_database_for_cache_dictionary.simple_key_simple_attributes_source_table VALUES(0, 'value_0', 'value_second_0'); +INSERT INTO 01684_database_for_cache_dictionary.simple_key_simple_attributes_source_table VALUES(1, 'value_1', 'value_second_1'); +INSERT INTO 01684_database_for_cache_dictionary.simple_key_simple_attributes_source_table VALUES(2, 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes +( + id UInt64, + value_first String DEFAULT 'value_first_default', + value_second String DEFAULT 'value_second_default' +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_simple_attributes_source_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(SSD_CACHE(BLOCK_SIZE 4096 FILE_SIZE 8192 PATH '/var/lib/clickhouse/clickhouse_dicts/0d')); + +SELECT 'Dictionary cache_dictionary_simple_key_simple_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_first', number) as value_first, + dictGet('01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_first', number) as value_first, + dictGet('01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes', number) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes; + +DROP DICTIONARY 01684_database_for_cache_dictionary.cache_dictionary_simple_key_simple_attributes; +DROP TABLE 01684_database_for_cache_dictionary.simple_key_simple_attributes_source_table; + +CREATE TABLE 01684_database_for_cache_dictionary.simple_key_complex_attributes_source_table +( + id UInt64, + value_first String, + value_second Nullable(String) +) +ENGINE = TinyLog; + +INSERT INTO 01684_database_for_cache_dictionary.simple_key_complex_attributes_source_table VALUES(0, 'value_0', 'value_second_0'); +INSERT INTO 01684_database_for_cache_dictionary.simple_key_complex_attributes_source_table VALUES(1, 'value_1', NULL); +INSERT INTO 01684_database_for_cache_dictionary.simple_key_complex_attributes_source_table VALUES(2, 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes +( + id UInt64, + value_first String DEFAULT 'value_first_default', + value_second Nullable(String) DEFAULT 'value_second_default' +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_complex_attributes_source_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(SSD_CACHE(BLOCK_SIZE 4096 FILE_SIZE 8192 PATH '/var/lib/clickhouse/clickhouse_dicts/1d')); + +SELECT 'Dictionary cache_dictionary_simple_key_complex_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_first', number) as value_first, + dictGet('01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_first', number) as value_first, + dictGet('01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes', number) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes; + +DROP DICTIONARY 01684_database_for_cache_dictionary.cache_dictionary_simple_key_complex_attributes; +DROP TABLE 01684_database_for_cache_dictionary.simple_key_complex_attributes_source_table; + +CREATE TABLE 01684_database_for_cache_dictionary.simple_key_hierarchy_table +( + id UInt64, + parent_id UInt64 +) ENGINE = TinyLog(); + +INSERT INTO 01684_database_for_cache_dictionary.simple_key_hierarchy_table VALUES (1, 0); +INSERT INTO 01684_database_for_cache_dictionary.simple_key_hierarchy_table VALUES (2, 1); +INSERT INTO 01684_database_for_cache_dictionary.simple_key_hierarchy_table VALUES (3, 1); +INSERT INTO 01684_database_for_cache_dictionary.simple_key_hierarchy_table VALUES (4, 2); + +CREATE DICTIONARY 01684_database_for_cache_dictionary.cache_dictionary_simple_key_hierarchy +( + id UInt64, + parent_id UInt64 HIERARCHICAL +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_hierarchy_table')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(SSD_CACHE(BLOCK_SIZE 4096 FILE_SIZE 8192 PATH '/var/lib/clickhouse/clickhouse_dicts/2d')); + +SELECT 'Dictionary cache_dictionary_simple_key_hierarchy'; +SELECT 'dictGet'; +SELECT dictGet('01684_database_for_cache_dictionary.cache_dictionary_simple_key_hierarchy', 'parent_id', number) FROM system.numbers LIMIT 5; +SELECT 'dictGetHierarchy'; +SELECT dictGetHierarchy('01684_database_for_cache_dictionary.cache_dictionary_simple_key_hierarchy', toUInt64(1)); +SELECT dictGetHierarchy('01684_database_for_cache_dictionary.cache_dictionary_simple_key_hierarchy', toUInt64(4)); + +DROP DICTIONARY 01684_database_for_cache_dictionary.cache_dictionary_simple_key_hierarchy; +DROP TABLE 01684_database_for_cache_dictionary.simple_key_hierarchy_table; + +DROP DATABASE 01684_database_for_cache_dictionary; diff --git a/tests/queries/0_stateless/01685_ssd_cache_dictionary_complex_key.reference b/tests/queries/0_stateless/01685_ssd_cache_dictionary_complex_key.reference new file mode 100644 index 00000000000..a0f99ca13cc --- /dev/null +++ b/tests/queries/0_stateless/01685_ssd_cache_dictionary_complex_key.reference @@ -0,0 +1,56 @@ +Dictionary cache_dictionary_complex_key_simple_attributes +dictGet existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 id_key_0 value_0 value_second_0 +1 id_key_1 value_1 value_second_1 +2 id_key_2 value_2 value_second_2 +Dictionary cache_dictionary_complex_key_complex_attributes +dictGet existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 id_key_0 value_0 value_second_0 +1 id_key_1 value_1 \N +2 id_key_2 value_2 value_second_2 diff --git a/tests/queries/0_stateless/01685_ssd_cache_dictionary_complex_key.sql b/tests/queries/0_stateless/01685_ssd_cache_dictionary_complex_key.sql new file mode 100644 index 00000000000..1757b136d3e --- /dev/null +++ b/tests/queries/0_stateless/01685_ssd_cache_dictionary_complex_key.sql @@ -0,0 +1,98 @@ +DROP DATABASE IF EXISTS 01685_database_for_cache_dictionary; +CREATE DATABASE 01685_database_for_cache_dictionary; + +CREATE TABLE 01685_database_for_cache_dictionary.complex_key_simple_attributes_source_table +( + id UInt64, + id_key String, + value_first String, + value_second String +) +ENGINE = TinyLog; + +INSERT INTO 01685_database_for_cache_dictionary.complex_key_simple_attributes_source_table VALUES(0, 'id_key_0', 'value_0', 'value_second_0'); +INSERT INTO 01685_database_for_cache_dictionary.complex_key_simple_attributes_source_table VALUES(1, 'id_key_1', 'value_1', 'value_second_1'); +INSERT INTO 01685_database_for_cache_dictionary.complex_key_simple_attributes_source_table VALUES(2, 'id_key_2', 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes +( + id UInt64, + id_key String, + value_first String DEFAULT 'value_first_default', + value_second String DEFAULT 'value_second_default' +) +PRIMARY KEY id, id_key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'complex_key_simple_attributes_source_table' DB '01685_database_for_cache_dictionary')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(COMPLEX_KEY_SSD_CACHE(BLOCK_SIZE 4096 FILE_SIZE 8192 PATH '/var/lib/clickhouse/clickhouse_dicts/0d')); + +SELECT 'Dictionary cache_dictionary_complex_key_simple_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes', (number, concat('id_key_', toString(number)))) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes; + +DROP DICTIONARY 01685_database_for_cache_dictionary.cache_dictionary_complex_key_simple_attributes; +DROP TABLE 01685_database_for_cache_dictionary.complex_key_simple_attributes_source_table; + +CREATE TABLE 01685_database_for_cache_dictionary.complex_key_complex_attributes_source_table +( + id UInt64, + id_key String, + value_first String, + value_second Nullable(String) +) +ENGINE = TinyLog; + +INSERT INTO 01685_database_for_cache_dictionary.complex_key_complex_attributes_source_table VALUES(0, 'id_key_0', 'value_0', 'value_second_0'); +INSERT INTO 01685_database_for_cache_dictionary.complex_key_complex_attributes_source_table VALUES(1, 'id_key_1', 'value_1', NULL); +INSERT INTO 01685_database_for_cache_dictionary.complex_key_complex_attributes_source_table VALUES(2, 'id_key_2', 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes +( + id UInt64, + id_key String, + + value_first String DEFAULT 'value_first_default', + value_second Nullable(String) DEFAULT 'value_second_default' +) +PRIMARY KEY id, id_key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'complex_key_complex_attributes_source_table' DB '01685_database_for_cache_dictionary')) +LIFETIME(MIN 1 MAX 1000) +LAYOUT(COMPLEX_KEY_SSD_CACHE(BLOCK_SIZE 4096 FILE_SIZE 8192 PATH '/var/lib/clickhouse/clickhouse_dicts/1d')); + +SELECT 'Dictionary cache_dictionary_complex_key_complex_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes', (number, concat('id_key_', toString(number)))) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes; + +DROP DICTIONARY 01685_database_for_cache_dictionary.cache_dictionary_complex_key_complex_attributes; +DROP TABLE 01685_database_for_cache_dictionary.complex_key_complex_attributes_source_table; + +DROP DATABASE 01685_database_for_cache_dictionary; + diff --git a/tests/queries/0_stateless/01691_DateTime64_clamp.reference b/tests/queries/0_stateless/01691_DateTime64_clamp.reference index de72027334c..3adc9a17e5c 100644 --- a/tests/queries/0_stateless/01691_DateTime64_clamp.reference +++ b/tests/queries/0_stateless/01691_DateTime64_clamp.reference @@ -1,11 +1,17 @@ -- { echo } -SELECT toDateTime(-2, 2); +SELECT toTimeZone(toDateTime(-2, 2), 'Europe/Moscow'); 1970-01-01 03:00:00.00 -SELECT toDateTime64(-2, 2); +SELECT toDateTime64(-2, 2, 'Europe/Moscow'); 1970-01-01 03:00:00.00 -SELECT CAST(-1 AS DateTime64); -1970-01-01 03:00:00.000 -SELECT CAST('2020-01-01 00:00:00.3' AS DateTime64); -2020-01-01 00:00:00.300 -SELECT toDateTime64(bitShiftLeft(toUInt64(1),33), 2); -2106-02-07 09:28:15.00 +SELECT CAST(-1 AS DateTime64(0, 'Europe/Moscow')); +1970-01-01 03:00:00 +SELECT CAST('2020-01-01 00:00:00.3' AS DateTime64(0, 'Europe/Moscow')); +2020-01-01 00:00:00 +SELECT toDateTime64(bitShiftLeft(toUInt64(1), 33), 2, 'Europe/Moscow') FORMAT Null; +SELECT toTimeZone(toDateTime(-2., 2), 'Europe/Moscow'); +1970-01-01 03:00:00.00 +SELECT toDateTime64(-2., 2, 'Europe/Moscow'); +1970-01-01 03:00:00.00 +SELECT toDateTime64(toFloat32(bitShiftLeft(toUInt64(1),33)), 2, 'Europe/Moscow'); +2106-02-07 09:00:00.00 +SELECT toDateTime64(toFloat64(bitShiftLeft(toUInt64(1),33)), 2, 'Europe/Moscow') FORMAT Null; diff --git a/tests/queries/0_stateless/01691_DateTime64_clamp.sql b/tests/queries/0_stateless/01691_DateTime64_clamp.sql index 6b5a4815f37..92d5a33328f 100644 --- a/tests/queries/0_stateless/01691_DateTime64_clamp.sql +++ b/tests/queries/0_stateless/01691_DateTime64_clamp.sql @@ -1,6 +1,10 @@ -- { echo } -SELECT toDateTime(-2, 2); -SELECT toDateTime64(-2, 2); -SELECT CAST(-1 AS DateTime64); -SELECT CAST('2020-01-01 00:00:00.3' AS DateTime64); -SELECT toDateTime64(bitShiftLeft(toUInt64(1),33), 2); +SELECT toTimeZone(toDateTime(-2, 2), 'Europe/Moscow'); +SELECT toDateTime64(-2, 2, 'Europe/Moscow'); +SELECT CAST(-1 AS DateTime64(0, 'Europe/Moscow')); +SELECT CAST('2020-01-01 00:00:00.3' AS DateTime64(0, 'Europe/Moscow')); +SELECT toDateTime64(bitShiftLeft(toUInt64(1), 33), 2, 'Europe/Moscow') FORMAT Null; +SELECT toTimeZone(toDateTime(-2., 2), 'Europe/Moscow'); +SELECT toDateTime64(-2., 2, 'Europe/Moscow'); +SELECT toDateTime64(toFloat32(bitShiftLeft(toUInt64(1),33)), 2, 'Europe/Moscow'); +SELECT toDateTime64(toFloat64(bitShiftLeft(toUInt64(1),33)), 2, 'Europe/Moscow') FORMAT Null; diff --git a/tests/queries/0_stateless/01698_fix_toMinute.reference b/tests/queries/0_stateless/01698_fix_toMinute.reference new file mode 100644 index 00000000000..7675aad3a57 --- /dev/null +++ b/tests/queries/0_stateless/01698_fix_toMinute.reference @@ -0,0 +1,24 @@ +Check the bug causing situation: the special Australia/Lord_Howe time zone. toDateTime and toString functions are all tested at once +1554559200 2019-04-07 01:00:00 2019-04-07 01:00:00 +1554559800 2019-04-07 01:10:00 2019-04-07 01:10:00 +1554560400 2019-04-07 01:20:00 2019-04-07 01:20:00 +1554561000 2019-04-07 01:30:00 2019-04-07 01:30:00 +1554561600 2019-04-07 01:40:00 2019-04-07 01:40:00 +1554562200 2019-04-07 01:50:00 2019-04-07 01:50:00 +1554562800 2019-04-07 01:30:00 2019-04-07 01:30:00 +1554563400 2019-04-07 01:40:00 2019-04-07 01:40:00 +1554564000 2019-04-07 01:50:00 2019-04-07 01:50:00 +1554564600 2019-04-07 02:00:00 2019-04-07 02:00:00 +1554565200 2019-04-07 02:10:00 2019-04-07 02:10:00 +1554565800 2019-04-07 02:20:00 2019-04-07 02:20:00 +1554566400 2019-04-07 02:30:00 2019-04-07 02:30:00 +1554567000 2019-04-07 02:40:00 2019-04-07 02:40:00 +1554567600 2019-04-07 02:50:00 2019-04-07 02:50:00 +1554568200 2019-04-07 03:00:00 2019-04-07 03:00:00 +1554568800 2019-04-07 03:10:00 2019-04-07 03:10:00 +1554569400 2019-04-07 03:20:00 2019-04-07 03:20:00 +1554570000 2019-04-07 03:30:00 2019-04-07 03:30:00 +1554570600 2019-04-07 03:40:00 2019-04-07 03:40:00 +4 days test in batch comparing with manually computation result for Europe/Moscow whose timezone epoc is of whole hour: +4 days test in batch comparing with manually computation result for Asia/Tehran whose timezone epoc is of half hour: +4 days test in batch comparing with manually computation result for Australia/Lord_Howe whose timezone epoc is of half hour and also its DST offset is half hour: diff --git a/tests/queries/0_stateless/01698_fix_toMinute.sql b/tests/queries/0_stateless/01698_fix_toMinute.sql new file mode 100644 index 00000000000..f582806719d --- /dev/null +++ b/tests/queries/0_stateless/01698_fix_toMinute.sql @@ -0,0 +1,16 @@ +/* toDateTime or toString or other functions which should call the toMinute() function will all meet this bug. tests below will verify the toDateTime and toString. */ +SELECT 'Check the bug causing situation: the special Australia/Lord_Howe time zone. toDateTime and toString functions are all tested at once'; +SELECT toUnixTimestamp(x) as tt, (toDateTime('2019-04-07 01:00:00', 'Australia/Lord_Howe') + INTERVAL number * 600 SECOND) AS x, toString(x) as xx FROM numbers(20); + +/* The Batch Part. Test period is whole 4 days*/ +SELECT '4 days test in batch comparing with manually computation result for Europe/Moscow whose timezone epoc is of whole hour:'; +SELECT toUnixTimestamp(x) as tt, (toDateTime('1981-04-01 00:00:00', 'Europe/Moscow') + INTERVAL number * 600 SECOND) AS x, timezoneOffset(x) as res,(toDateTime(toString(x), 'UTC') - x ) AS calc FROM numbers(576) where res != calc; +SELECT toUnixTimestamp(x) as tt, (toDateTime('1981-09-30 00:00:00', 'Europe/Moscow') + INTERVAL number * 600 SECOND) AS x, timezoneOffset(x) as res,(toDateTime(toString(x), 'UTC') - x ) AS calc FROM numbers(576) where res != calc; + +SELECT '4 days test in batch comparing with manually computation result for Asia/Tehran whose timezone epoc is of half hour:'; +SELECT toUnixTimestamp(x) as tt, (toDateTime('2020-03-21 00:00:00', 'Asia/Tehran') + INTERVAL number * 600 SECOND) AS x, timezoneOffset(x) as res,(toDateTime(toString(x), 'UTC') - x ) AS calc FROM numbers(576) where res != calc; +SELECT toUnixTimestamp(x) as tt, (toDateTime('2020-09-20 00:00:00', 'Asia/Tehran') + INTERVAL number * 600 SECOND) AS x, timezoneOffset(x) as res,(toDateTime(toString(x), 'UTC') - x ) AS calc FROM numbers(576) where res != calc; + +SELECT '4 days test in batch comparing with manually computation result for Australia/Lord_Howe whose timezone epoc is of half hour and also its DST offset is half hour:'; +SELECT toUnixTimestamp(x) as tt, (toDateTime('2020-10-04 01:40:00', 'Australia/Lord_Howe') + INTERVAL number * 600 SECOND) AS x, timezoneOffset(x) as res,(toDateTime(toString(x), 'UTC') - x ) AS calc FROM numbers(576) where res != calc; +SELECT toUnixTimestamp(x) as tt, (toDateTime('2019-04-07 01:00:00', 'Australia/Lord_Howe') + INTERVAL number * 600 SECOND) AS x, timezoneOffset(x) as res,(toDateTime(toString(x), 'UTC') - x ) AS calc FROM numbers(576) where res != calc; diff --git a/tests/queries/0_stateless/01699_timezoneOffset.reference b/tests/queries/0_stateless/01699_timezoneOffset.reference index e70c5fa62ee..45f30314f5a 100644 --- a/tests/queries/0_stateless/01699_timezoneOffset.reference +++ b/tests/queries/0_stateless/01699_timezoneOffset.reference @@ -50,57 +50,29 @@ DST boundary test for Australia/Lord_Howe. This is a special timezone with DST o DST boundary test for Australia/Lord_Howe: 0 2020-10-04 01:40:00 37800 1601737800 1 2020-10-04 01:50:00 37800 1601738400 -2 2020-10-04 02:00:00 39600 1601739000 -3 2020-10-04 02:10:00 39600 1601739600 +2 2020-10-04 02:30:00 39600 1601739000 +3 2020-10-04 02:40:00 39600 1601739600 0 2019-04-07 01:00:00 39600 1554559200 1 2019-04-07 01:10:00 39600 1554559800 2 2019-04-07 01:20:00 39600 1554560400 3 2019-04-07 01:30:00 39600 1554561000 4 2019-04-07 01:40:00 39600 1554561600 5 2019-04-07 01:50:00 39600 1554562200 -6 2019-04-07 01:00:00 37800 1554562800 -7 2019-04-07 01:10:00 37800 1554563400 -8 2019-04-07 01:20:00 37800 1554564000 -9 2019-04-07 02:30:00 37800 1554564600 -10 2019-04-07 02:40:00 37800 1554565200 -11 2019-04-07 02:50:00 37800 1554565800 -12 2019-04-07 02:00:00 37800 1554566400 -13 2019-04-07 02:10:00 37800 1554567000 -14 2019-04-07 02:20:00 37800 1554567600 -15 2019-04-07 03:30:00 37800 1554568200 -16 2019-04-07 03:40:00 37800 1554568800 -17 2019-04-07 03:50:00 37800 1554569400 +6 2019-04-07 01:30:00 37800 1554562800 +7 2019-04-07 01:40:00 37800 1554563400 +8 2019-04-07 01:50:00 37800 1554564000 +9 2019-04-07 02:00:00 37800 1554564600 +10 2019-04-07 02:10:00 37800 1554565200 +11 2019-04-07 02:20:00 37800 1554565800 +12 2019-04-07 02:30:00 37800 1554566400 +13 2019-04-07 02:40:00 37800 1554567000 +14 2019-04-07 02:50:00 37800 1554567600 +15 2019-04-07 03:00:00 37800 1554568200 +16 2019-04-07 03:10:00 37800 1554568800 +17 2019-04-07 03:20:00 37800 1554569400 4 days test in batch comparing with manually computation result for Europe/Moscow: 4 days test in batch comparing with manually computation result for Asia/Tehran: -The result maybe wrong for toDateTime processing Australia/Lord_Howe -1601739000 2020-10-04 02:00:00 39600 37800 -1601739600 2020-10-04 02:10:00 39600 37800 -1601740200 2020-10-04 02:20:00 39600 37800 -1601740800 2020-10-04 03:30:00 39600 41400 -1601741400 2020-10-04 03:40:00 39600 41400 -1601742000 2020-10-04 03:50:00 39600 41400 -1601742600 2020-10-04 03:00:00 39600 37800 -1601743200 2020-10-04 03:10:00 39600 37800 -1601743800 2020-10-04 03:20:00 39600 37800 -1601744400 2020-10-04 04:30:00 39600 41400 -1601745000 2020-10-04 04:40:00 39600 41400 -1601745600 2020-10-04 04:50:00 39600 41400 -1601746200 2020-10-04 04:00:00 39600 37800 -1601746800 2020-10-04 04:10:00 39600 37800 -1601747400 2020-10-04 04:20:00 39600 37800 -1601748000 2020-10-04 05:30:00 39600 41400 -1554562800 2019-04-07 01:00:00 37800 36000 -1554563400 2019-04-07 01:10:00 37800 36000 -1554564000 2019-04-07 01:20:00 37800 36000 -1554564600 2019-04-07 02:30:00 37800 39600 -1554565200 2019-04-07 02:40:00 37800 39600 -1554565800 2019-04-07 02:50:00 37800 39600 -1554566400 2019-04-07 02:00:00 37800 36000 -1554567000 2019-04-07 02:10:00 37800 36000 -1554567600 2019-04-07 02:20:00 37800 36000 -1554568200 2019-04-07 03:30:00 37800 39600 -1554568800 2019-04-07 03:40:00 37800 39600 -1554569400 2019-04-07 03:50:00 37800 39600 +4 days test in batch comparing with manually computation result for Australia/Lord_Howe Moscow DST Years: 11 1981-06-01 00:00:00 14400 12 1982-06-01 00:00:00 14400 diff --git a/tests/queries/0_stateless/01699_timezoneOffset.sql b/tests/queries/0_stateless/01699_timezoneOffset.sql index 1b3f05ecdd7..8cabb23c4de 100644 --- a/tests/queries/0_stateless/01699_timezoneOffset.sql +++ b/tests/queries/0_stateless/01699_timezoneOffset.sql @@ -26,8 +26,7 @@ SELECT '4 days test in batch comparing with manually computation result for Asia SELECT toUnixTimestamp(x) as tt, (toDateTime('2020-03-21 00:00:00', 'Asia/Tehran') + INTERVAL number * 600 SECOND) AS x, timezoneOffset(x) as res,(toDateTime(toString(x), 'UTC') - x ) AS calc FROM numbers(576) where res != calc; SELECT toUnixTimestamp(x) as tt, (toDateTime('2020-09-20 00:00:00', 'Asia/Tehran') + INTERVAL number * 600 SECOND) AS x, timezoneOffset(x) as res,(toDateTime(toString(x), 'UTC') - x ) AS calc FROM numbers(576) where res != calc; -/* During this test we got unexpected result comes from the toDateTime() function when process the special time zone of 'Australia/Lord_Howe', which may be some kind of bugs. */ -SELECT 'The result maybe wrong for toDateTime processing Australia/Lord_Howe'; +SELECT '4 days test in batch comparing with manually computation result for Australia/Lord_Howe'; SELECT toUnixTimestamp(x) as tt, (toDateTime('2020-10-04 01:40:00', 'Australia/Lord_Howe') + INTERVAL number * 600 SECOND) AS x, timezoneOffset(x) as res,(toDateTime(toString(x), 'UTC') - x ) AS calc FROM numbers(18) where res != calc; SELECT toUnixTimestamp(x) as tt, (toDateTime('2019-04-07 01:00:00', 'Australia/Lord_Howe') + INTERVAL number * 600 SECOND) AS x, timezoneOffset(x) as res,(toDateTime(toString(x), 'UTC') - x ) AS calc FROM numbers(18) where res != calc; diff --git a/tests/queries/0_stateless/01700_point_in_polygon_ubsan.sql b/tests/queries/0_stateless/01700_point_in_polygon_ubsan.sql index 97db40ab65e..72317df5439 100644 --- a/tests/queries/0_stateless/01700_point_in_polygon_ubsan.sql +++ b/tests/queries/0_stateless/01700_point_in_polygon_ubsan.sql @@ -1 +1 @@ -SELECT pointInPolygon((0, 0), [[(0, 0), (10, 10), (256, -9223372036854775808)]]) FORMAT Null; +SELECT pointInPolygon((0, 0), [[(0, 0), (10, 10), (256, -9223372036854775808)]]) FORMAT Null ;-- { serverError 36 } diff --git a/tests/queries/0_stateless/01700_system_zookeeper_path_in.reference b/tests/queries/0_stateless/01700_system_zookeeper_path_in.reference index 78462f9fc0e..2fc177c812e 100644 --- a/tests/queries/0_stateless/01700_system_zookeeper_path_in.reference +++ b/tests/queries/0_stateless/01700_system_zookeeper_path_in.reference @@ -1,7 +1,16 @@ -clickhouse -task_queue -clickhouse -task_queue -clickhouse -task_queue -ddl +block_numbers +blocks +1 +======== +block_numbers +blocks +1 +======== +block_numbers +blocks +======== +1 +failed_parts +last_part +leader_election-0000000000 +parallel diff --git a/tests/queries/0_stateless/01700_system_zookeeper_path_in.sql b/tests/queries/0_stateless/01700_system_zookeeper_path_in.sql index a5c7488ef97..d4126098c7c 100644 --- a/tests/queries/0_stateless/01700_system_zookeeper_path_in.sql +++ b/tests/queries/0_stateless/01700_system_zookeeper_path_in.sql @@ -1,6 +1,19 @@ -SELECT name FROM system.zookeeper WHERE path = '/'; -SELECT name FROM system.zookeeper WHERE path = 'clickhouse'; -SELECT name FROM system.zookeeper WHERE path IN ('/'); -SELECT name FROM system.zookeeper WHERE path IN ('clickhouse'); -SELECT name FROM system.zookeeper WHERE path IN ('/','/clickhouse'); -SELECT name FROM system.zookeeper WHERE path IN (SELECT concat('/clickhouse/',name) FROM system.zookeeper WHERE (path = '/clickhouse/')); \ No newline at end of file +DROP TABLE IF EXISTS sample_table; + +CREATE TABLE sample_table ( + key UInt64 +) +ENGINE ReplicatedMergeTree('/clickhouse/01700_system_zookeeper_path_in', '1') +ORDER BY tuple(); + +SELECT name FROM system.zookeeper WHERE path = '/clickhouse/01700_system_zookeeper_path_in' AND name like 'block%' ORDER BY name; +SELECT name FROM system.zookeeper WHERE path = '/clickhouse/01700_system_zookeeper_path_in/replicas' ORDER BY name; +SELECT '========'; +SELECT name FROM system.zookeeper WHERE path IN ('/clickhouse/01700_system_zookeeper_path_in') AND name LIKE 'block%' ORDER BY name; +SELECT name FROM system.zookeeper WHERE path IN ('/clickhouse/01700_system_zookeeper_path_in/replicas') ORDER BY name; +SELECT '========'; +SELECT name FROM system.zookeeper WHERE path IN ('/clickhouse/01700_system_zookeeper_path_in','/clickhouse/01700_system_zookeeper_path_in/replicas') AND name LIKE 'block%' ORDER BY name; +SELECT '========'; +SELECT name FROM system.zookeeper WHERE path IN (SELECT concat('/clickhouse/01700_system_zookeeper_path_in/', name) FROM system.zookeeper WHERE (path = '/clickhouse/01700_system_zookeeper_path_in')) ORDER BY name; + +DROP TABLE IF EXISTS sample_table; diff --git a/tests/queries/0_stateless/01701_parallel_parsing_infinite_segmentation.reference b/tests/queries/0_stateless/01701_parallel_parsing_infinite_segmentation.reference new file mode 100644 index 00000000000..587579af915 --- /dev/null +++ b/tests/queries/0_stateless/01701_parallel_parsing_infinite_segmentation.reference @@ -0,0 +1 @@ +Ok. diff --git a/tests/queries/0_stateless/01701_parallel_parsing_infinite_segmentation.sh b/tests/queries/0_stateless/01701_parallel_parsing_infinite_segmentation.sh new file mode 100755 index 00000000000..d3e634eb560 --- /dev/null +++ b/tests/queries/0_stateless/01701_parallel_parsing_infinite_segmentation.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +${CLICKHOUSE_CLIENT} -q "create table insert_big_json(a String, b String) engine=MergeTree() order by tuple()"; + +python3 -c "[print('{{\"a\":\"{}\", \"b\":\"{}\"'.format('clickhouse'* 1000000, 'dbms' * 1000000)) for i in range(10)]; [print('{{\"a\":\"{}\", \"b\":\"{}\"}}'.format('clickhouse'* 100000, 'dbms' * 100000)) for i in range(10)]" 2>/dev/null | ${CLICKHOUSE_CLIENT} --input_format_parallel_parsing=1 --max_memory_usage=0 -q "insert into insert_big_json FORMAT JSONEachRow" 2>&1 | grep -q "min_chunk_bytes_for_parallel_parsing" && echo "Ok." || echo "FAIL" ||: \ No newline at end of file diff --git a/tests/queries/0_stateless/01702_system_query_log.reference b/tests/queries/0_stateless/01702_system_query_log.reference new file mode 100644 index 00000000000..6d8908249bf --- /dev/null +++ b/tests/queries/0_stateless/01702_system_query_log.reference @@ -0,0 +1,92 @@ +DROP queries and also a cleanup before the test +CREATE queries +SET queries +ALTER TABLE queries +SYSTEM queries +SHOW queries +GRANT queries +REVOKE queries +Misc queries +ACTUAL LOG CONTENT: +Select SELECT \'DROP queries and also a cleanup before the test\'; +Drop DROP DATABASE IF EXISTS sqllt SYNC; + DROP USER IF EXISTS sqllt_user; + DROP ROLE IF EXISTS sqllt_role; + DROP POLICY IF EXISTS sqllt_policy ON sqllt.table, sqllt.view, sqllt.dictionary; + DROP ROW POLICY IF EXISTS sqllt_row_policy ON sqllt.table, sqllt.view, sqllt.dictionary; + DROP QUOTA IF EXISTS sqllt_quota; + DROP SETTINGS PROFILE IF EXISTS sqllt_settings_profile; +Select SELECT \'CREATE queries\'; +Create CREATE DATABASE sqllt; +Create CREATE TABLE sqllt.table\n(\n i UInt8, s String\n)\nENGINE = MergeTree PARTITION BY tuple() ORDER BY tuple(); +Create CREATE VIEW sqllt.view AS SELECT i, s FROM sqllt.table; +Create CREATE DICTIONARY sqllt.dictionary (key UInt64, value UInt64) PRIMARY KEY key SOURCE(CLICKHOUSE(DB \'sqllt\' TABLE \'table\' HOST \'localhost\' PORT 9001)) LIFETIME(0) LAYOUT(FLAT()); + CREATE USER sqllt_user IDENTIFIED WITH PLAINTEXT_PASSWORD BY \'password\'; + CREATE ROLE sqllt_role; + CREATE POLICY sqllt_policy ON sqllt.table, sqllt.view, sqllt.dictionary AS PERMISSIVE TO ALL; + CREATE POLICY sqllt_row_policy ON sqllt.table, sqllt.view, sqllt.dictionary AS PERMISSIVE TO ALL; + CREATE QUOTA sqllt_quota KEYED BY user_name TO sqllt_role; + CREATE SETTINGS PROFILE sqllt_settings_profile SETTINGS interactive_delay = 200000; +Grant GRANT sqllt_role TO sqllt_user; +Select SELECT \'SET queries\'; + SET log_profile_events=false; + SET DEFAULT ROLE sqllt_role TO sqllt_user; +Select -- SET ROLE sqllt_role; -- tests are executed by user `default` which is defined in XML and is impossible to update.\n\nSELECT \'ALTER TABLE queries\'; +Alter ALTER TABLE sqllt.table ADD COLUMN new_col UInt32 DEFAULT 123456789; +Alter ALTER TABLE sqllt.table COMMENT COLUMN new_col \'dummy column with a comment\'; +Alter ALTER TABLE sqllt.table CLEAR COLUMN new_col; +Alter ALTER TABLE sqllt.table MODIFY COLUMN new_col DateTime DEFAULT \'2015-05-18 07:40:13\'; +Alter ALTER TABLE sqllt.table MODIFY COLUMN new_col REMOVE COMMENT; +Alter ALTER TABLE sqllt.table RENAME COLUMN new_col TO the_new_col; +Alter ALTER TABLE sqllt.table DROP COLUMN the_new_col; +Alter ALTER TABLE sqllt.table UPDATE i = i + 1 WHERE 1; +Alter ALTER TABLE sqllt.table DELETE WHERE i > 65535; +Select -- not done, seems to hard, so I\'ve skipped queries of ALTER-X, where X is:\n-- PARTITION\n-- ORDER BY\n-- SAMPLE BY\n-- INDEX\n-- CONSTRAINT\n-- TTL\n-- USER\n-- QUOTA\n-- ROLE\n-- ROW POLICY\n-- SETTINGS PROFILE\n\nSELECT \'SYSTEM queries\'; +System SYSTEM RELOAD EMBEDDED DICTIONARIES; +System SYSTEM RELOAD DICTIONARIES; +System SYSTEM DROP DNS CACHE; +System SYSTEM DROP MARK CACHE; +System SYSTEM DROP UNCOMPRESSED CACHE; +System SYSTEM FLUSH LOGS; +System SYSTEM RELOAD CONFIG; +System SYSTEM STOP MERGES; +System SYSTEM START MERGES; +System SYSTEM STOP TTL MERGES; +System SYSTEM START TTL MERGES; +System SYSTEM STOP MOVES; +System SYSTEM START MOVES; +System SYSTEM STOP FETCHES; +System SYSTEM START FETCHES; +System SYSTEM STOP REPLICATED SENDS; +System SYSTEM START REPLICATED SENDS; +Select -- SYSTEM RELOAD DICTIONARY sqllt.dictionary; -- temporary out of order: Code: 210, Connection refused (localhost:9001) (version 21.3.1.1)\n-- DROP REPLICA\n-- haha, no\n-- SYSTEM KILL;\n-- SYSTEM SHUTDOWN;\n\n-- Since we don\'t really care about the actual output, suppress it with `FORMAT Null`.\nSELECT \'SHOW queries\'; + SHOW CREATE TABLE sqllt.table FORMAT Null; + SHOW CREATE DICTIONARY sqllt.dictionary FORMAT Null; + SHOW DATABASES LIKE \'sqllt\' FORMAT Null; + SHOW TABLES FROM sqllt FORMAT Null; + SHOW DICTIONARIES FROM sqllt FORMAT Null; + SHOW GRANTS FORMAT Null; + SHOW GRANTS FOR sqllt_user FORMAT Null; + SHOW CREATE USER sqllt_user FORMAT Null; + SHOW CREATE ROLE sqllt_role FORMAT Null; + SHOW CREATE POLICY sqllt_policy FORMAT Null; + SHOW CREATE ROW POLICY sqllt_row_policy FORMAT Null; + SHOW CREATE QUOTA sqllt_quota FORMAT Null; + SHOW CREATE SETTINGS PROFILE sqllt_settings_profile FORMAT Null; +Select SELECT \'GRANT queries\'; +Grant GRANT SELECT ON sqllt.table TO sqllt_user; +Grant GRANT DROP ON sqllt.view TO sqllt_user; +Select SELECT \'REVOKE queries\'; +Revoke REVOKE SELECT ON sqllt.table FROM sqllt_user; +Revoke REVOKE DROP ON sqllt.view FROM sqllt_user; +Select SELECT \'Misc queries\'; + DESCRIBE TABLE sqllt.table FORMAT Null; + CHECK TABLE sqllt.table FORMAT Null; +Drop DETACH TABLE sqllt.table; +Create ATTACH TABLE sqllt.table; +Rename RENAME TABLE sqllt.table TO sqllt.table_new; +Rename RENAME TABLE sqllt.table_new TO sqllt.table; +Drop TRUNCATE TABLE sqllt.table; +Drop DROP TABLE sqllt.table SYNC; + SET log_comment=\'\'; +DROP queries and also a cleanup after the test diff --git a/tests/queries/0_stateless/01702_system_query_log.sql b/tests/queries/0_stateless/01702_system_query_log.sql new file mode 100644 index 00000000000..f31d8de3577 --- /dev/null +++ b/tests/queries/0_stateless/01702_system_query_log.sql @@ -0,0 +1,152 @@ +-- fire all kinds of queries and then check if those are present in the system.query_log +SET log_comment='system.query_log logging test'; + +SELECT 'DROP queries and also a cleanup before the test'; +DROP DATABASE IF EXISTS sqllt SYNC; +DROP USER IF EXISTS sqllt_user; +DROP ROLE IF EXISTS sqllt_role; +DROP POLICY IF EXISTS sqllt_policy ON sqllt.table, sqllt.view, sqllt.dictionary; +DROP ROW POLICY IF EXISTS sqllt_row_policy ON sqllt.table, sqllt.view, sqllt.dictionary; +DROP QUOTA IF EXISTS sqllt_quota; +DROP SETTINGS PROFILE IF EXISTS sqllt_settings_profile; + +SELECT 'CREATE queries'; +CREATE DATABASE sqllt; + +CREATE TABLE sqllt.table +( + i UInt8, s String +) +ENGINE = MergeTree PARTITION BY tuple() ORDER BY tuple(); + +CREATE VIEW sqllt.view AS SELECT i, s FROM sqllt.table; +CREATE DICTIONARY sqllt.dictionary (key UInt64, value UInt64) PRIMARY KEY key SOURCE(CLICKHOUSE(DB 'sqllt' TABLE 'table' HOST 'localhost' PORT 9001)) LIFETIME(0) LAYOUT(FLAT()); + +CREATE USER sqllt_user IDENTIFIED WITH PLAINTEXT_PASSWORD BY 'password'; +CREATE ROLE sqllt_role; + +CREATE POLICY sqllt_policy ON sqllt.table, sqllt.view, sqllt.dictionary AS PERMISSIVE TO ALL; +CREATE POLICY sqllt_row_policy ON sqllt.table, sqllt.view, sqllt.dictionary AS PERMISSIVE TO ALL; + +CREATE QUOTA sqllt_quota KEYED BY user_name TO sqllt_role; +CREATE SETTINGS PROFILE sqllt_settings_profile SETTINGS interactive_delay = 200000; + +GRANT sqllt_role TO sqllt_user; + + +SELECT 'SET queries'; +SET log_profile_events=false; +SET DEFAULT ROLE sqllt_role TO sqllt_user; +-- SET ROLE sqllt_role; -- tests are executed by user `default` which is defined in XML and is impossible to update. + +SELECT 'ALTER TABLE queries'; +ALTER TABLE sqllt.table ADD COLUMN new_col UInt32 DEFAULT 123456789; +ALTER TABLE sqllt.table COMMENT COLUMN new_col 'dummy column with a comment'; +ALTER TABLE sqllt.table CLEAR COLUMN new_col; +ALTER TABLE sqllt.table MODIFY COLUMN new_col DateTime DEFAULT '2015-05-18 07:40:13'; +ALTER TABLE sqllt.table MODIFY COLUMN new_col REMOVE COMMENT; +ALTER TABLE sqllt.table RENAME COLUMN new_col TO the_new_col; +ALTER TABLE sqllt.table DROP COLUMN the_new_col; +ALTER TABLE sqllt.table UPDATE i = i + 1 WHERE 1; +ALTER TABLE sqllt.table DELETE WHERE i > 65535; + +-- not done, seems to hard, so I've skipped queries of ALTER-X, where X is: +-- PARTITION +-- ORDER BY +-- SAMPLE BY +-- INDEX +-- CONSTRAINT +-- TTL +-- USER +-- QUOTA +-- ROLE +-- ROW POLICY +-- SETTINGS PROFILE + +SELECT 'SYSTEM queries'; +SYSTEM RELOAD EMBEDDED DICTIONARIES; +SYSTEM RELOAD DICTIONARIES; +SYSTEM DROP DNS CACHE; +SYSTEM DROP MARK CACHE; +SYSTEM DROP UNCOMPRESSED CACHE; +SYSTEM FLUSH LOGS; +SYSTEM RELOAD CONFIG; +SYSTEM STOP MERGES; +SYSTEM START MERGES; +SYSTEM STOP TTL MERGES; +SYSTEM START TTL MERGES; +SYSTEM STOP MOVES; +SYSTEM START MOVES; +SYSTEM STOP FETCHES; +SYSTEM START FETCHES; +SYSTEM STOP REPLICATED SENDS; +SYSTEM START REPLICATED SENDS; + +-- SYSTEM RELOAD DICTIONARY sqllt.dictionary; -- temporary out of order: Code: 210, Connection refused (localhost:9001) (version 21.3.1.1) +-- DROP REPLICA +-- haha, no +-- SYSTEM KILL; +-- SYSTEM SHUTDOWN; + +-- Since we don't really care about the actual output, suppress it with `FORMAT Null`. +SELECT 'SHOW queries'; + +SHOW CREATE TABLE sqllt.table FORMAT Null; +SHOW CREATE DICTIONARY sqllt.dictionary FORMAT Null; +SHOW DATABASES LIKE 'sqllt' FORMAT Null; +SHOW TABLES FROM sqllt FORMAT Null; +SHOW DICTIONARIES FROM sqllt FORMAT Null; +SHOW GRANTS FORMAT Null; +SHOW GRANTS FOR sqllt_user FORMAT Null; +SHOW CREATE USER sqllt_user FORMAT Null; +SHOW CREATE ROLE sqllt_role FORMAT Null; +SHOW CREATE POLICY sqllt_policy FORMAT Null; +SHOW CREATE ROW POLICY sqllt_row_policy FORMAT Null; +SHOW CREATE QUOTA sqllt_quota FORMAT Null; +SHOW CREATE SETTINGS PROFILE sqllt_settings_profile FORMAT Null; + +SELECT 'GRANT queries'; +GRANT SELECT ON sqllt.table TO sqllt_user; +GRANT DROP ON sqllt.view TO sqllt_user; + +SELECT 'REVOKE queries'; +REVOKE SELECT ON sqllt.table FROM sqllt_user; +REVOKE DROP ON sqllt.view FROM sqllt_user; + +SELECT 'Misc queries'; +DESCRIBE TABLE sqllt.table FORMAT Null; + +CHECK TABLE sqllt.table FORMAT Null; +DETACH TABLE sqllt.table; +ATTACH TABLE sqllt.table; + +RENAME TABLE sqllt.table TO sqllt.table_new; +RENAME TABLE sqllt.table_new TO sqllt.table; +TRUNCATE TABLE sqllt.table; +DROP TABLE sqllt.table SYNC; + +SET log_comment=''; +--------------------------------------------------------------------------------------------------- +-- Now get all logs related to this test +--------------------------------------------------------------------------------------------------- + +SYSTEM FLUSH LOGS; +SELECT 'ACTUAL LOG CONTENT:'; + +-- Try to filter out all possible previous junk events by excluding old log entries, +SELECT query_kind, query FROM system.query_log +WHERE + log_comment LIKE '%system.query_log%' AND type == 'QueryStart' AND event_time >= now() - 10 + AND current_database == currentDatabase() +ORDER BY event_time_microseconds; + + +-- cleanup +SELECT 'DROP queries and also a cleanup after the test'; +DROP DATABASE IF EXISTS sqllt; +DROP USER IF EXISTS sqllt_user; +DROP ROLE IF EXISTS sqllt_role; +DROP POLICY IF EXISTS sqllt_policy ON sqllt.table, sqllt.view, sqllt.dictionary; +DROP ROW POLICY IF EXISTS sqllt_row_policy ON sqllt.table, sqllt.view, sqllt.dictionary; +DROP QUOTA IF EXISTS sqllt_quota; +DROP SETTINGS PROFILE IF EXISTS sqllt_settings_profile; diff --git a/tests/queries/0_stateless/01702_toDateTime_from_string_clamping.reference b/tests/queries/0_stateless/01702_toDateTime_from_string_clamping.reference new file mode 100644 index 00000000000..228086615da --- /dev/null +++ b/tests/queries/0_stateless/01702_toDateTime_from_string_clamping.reference @@ -0,0 +1,9 @@ +-- { echo } +SELECT toString(toDateTime('-922337203.6854775808', 1)); +2106-02-07 15:41:33.6 +SELECT toString(toDateTime('9922337203.6854775808', 1)); +2104-12-30 00:50:11.6 +SELECT toDateTime64(CAST('10000000000.1' AS Decimal64(1)), 1); +2106-02-07 20:50:08.1 +SELECT toDateTime64(CAST('-10000000000.1' AS Decimal64(1)), 1); +2011-12-23 00:38:08.1 diff --git a/tests/queries/0_stateless/01702_toDateTime_from_string_clamping.sql b/tests/queries/0_stateless/01702_toDateTime_from_string_clamping.sql new file mode 100644 index 00000000000..d1f0416149a --- /dev/null +++ b/tests/queries/0_stateless/01702_toDateTime_from_string_clamping.sql @@ -0,0 +1,5 @@ +-- { echo } +SELECT toString(toDateTime('-922337203.6854775808', 1)); +SELECT toString(toDateTime('9922337203.6854775808', 1)); +SELECT toDateTime64(CAST('10000000000.1' AS Decimal64(1)), 1); +SELECT toDateTime64(CAST('-10000000000.1' AS Decimal64(1)), 1); diff --git a/tests/queries/0_stateless/01704_transform_with_float_key.reference b/tests/queries/0_stateless/01704_transform_with_float_key.reference new file mode 100644 index 00000000000..761e15c903c --- /dev/null +++ b/tests/queries/0_stateless/01704_transform_with_float_key.reference @@ -0,0 +1,30 @@ +- +Hello +- +World +- +- +- +- +- +- +- +- +Hello +- +World +- +- +- +- +- +- +- +Hello +- +World +- +- +- +- +- diff --git a/tests/queries/0_stateless/01704_transform_with_float_key.sql b/tests/queries/0_stateless/01704_transform_with_float_key.sql new file mode 100644 index 00000000000..690c73ee28a --- /dev/null +++ b/tests/queries/0_stateless/01704_transform_with_float_key.sql @@ -0,0 +1,3 @@ +SELECT transform(number / 2, [0.5, 1.5], ['Hello', 'World'], '-') FROM numbers(10); +SELECT transform(number / 2, [1.0, 2.0], ['Hello', 'World'], '-') FROM numbers(10); +SELECT transform(number / 2, [1, 2], ['Hello', 'World'], '-') FROM numbers(10); diff --git a/tests/queries/0_stateless/01705_normalize_case_insensitive_function_names.reference b/tests/queries/0_stateless/01705_normalize_case_insensitive_function_names.reference new file mode 100644 index 00000000000..5b0f7bdeb2d --- /dev/null +++ b/tests/queries/0_stateless/01705_normalize_case_insensitive_function_names.reference @@ -0,0 +1,66 @@ +SELECT + CAST(1, 'INT'), + ceil(1), + ceil(1), + char(49), + CHAR_LENGTH('1'), + CHARACTER_LENGTH('1'), + coalesce(1), + concat('1', '1'), + corr(1, 1), + cos(1), + count(), + covarPop(1, 1), + covarSamp(1, 1), + DATABASE(), + dateDiff('DAY', toDate('2020-10-24'), toDate('2019-10-24')), + exp(1), + arrayFlatten([[1]]), + floor(1), + FQDN(), + greatest(1), + 1, + ifNull(1, 1), + lower('A'), + least(1), + length('1'), + log(1), + position('1', '1'), + log(1), + log10(1), + log2(1), + lower('A'), + max(1), + substring('123', 1, 1), + min(1), + 1 % 1, + NOT 1, + now(), + now64(), + nullIf(1, 1), + pi(), + position('123', '2'), + pow(1, 1), + pow(1, 1), + rand(), + replaceAll('1', '1', '2'), + reverse('123'), + round(1), + sin(1), + sqrt(1), + stddevPop(1), + stddevSamp(1), + substring('123', 2), + substring('123', 2), + count(), + tan(1), + tanh(1), + trunc(1), + trunc(1), + upper('A'), + upper('A'), + currentUser(), + varPop(1), + varSamp(1), + toWeek(toDate('2020-10-24')), + toYearWeek(toDate('2020-10-24')) diff --git a/tests/queries/0_stateless/01705_normalize_case_insensitive_function_names.sql b/tests/queries/0_stateless/01705_normalize_case_insensitive_function_names.sql new file mode 100644 index 00000000000..9b35087182c --- /dev/null +++ b/tests/queries/0_stateless/01705_normalize_case_insensitive_function_names.sql @@ -0,0 +1 @@ +EXPLAIN SYNTAX SELECT CAST(1 AS INT), CEIL(1), CEILING(1), CHAR(49), CHAR_LENGTH('1'), CHARACTER_LENGTH('1'), COALESCE(1), CONCAT('1', '1'), CORR(1, 1), COS(1), COUNT(1), COVAR_POP(1, 1), COVAR_SAMP(1, 1), DATABASE(), DATEDIFF('DAY', toDate('2020-10-24'), toDate('2019-10-24')), EXP(1), FLATTEN([[1]]), FLOOR(1), FQDN(), GREATEST(1), IF(1, 1, 1), IFNULL(1, 1), LCASE('A'), LEAST(1), LENGTH('1'), LN(1), LOCATE('1', '1'), LOG(1), LOG10(1), LOG2(1), LOWER('A'), MAX(1), MID('123', 1, 1), MIN(1), MOD(1, 1), NOT(1), NOW(), NOW64(), NULLIF(1, 1), PI(), POSITION('123', '2'), POW(1, 1), POWER(1, 1), RAND(), REPLACE('1', '1', '2'), REVERSE('123'), ROUND(1), SIN(1), SQRT(1), STDDEV_POP(1), STDDEV_SAMP(1), SUBSTR('123', 2), SUBSTRING('123', 2), SUM(1), TAN(1), TANH(1), TRUNC(1), TRUNCATE(1), UCASE('A'), UPPER('A'), USER(), VAR_POP(1), VAR_SAMP(1), WEEK(toDate('2020-10-24')), YEARWEEK(toDate('2020-10-24')) format TSVRaw; diff --git a/tests/queries/0_stateless/01710_join_use_nulls.reference b/tests/queries/0_stateless/01710_join_use_nulls.reference index e69de29bb2d..069117803a7 100644 --- a/tests/queries/0_stateless/01710_join_use_nulls.reference +++ b/tests/queries/0_stateless/01710_join_use_nulls.reference @@ -0,0 +1,4 @@ +3 +3 +1 +1 diff --git a/tests/queries/0_stateless/01710_join_use_nulls.sql b/tests/queries/0_stateless/01710_join_use_nulls.sql index 2845af8b8ed..980ac48dd13 100644 --- a/tests/queries/0_stateless/01710_join_use_nulls.sql +++ b/tests/queries/0_stateless/01710_join_use_nulls.sql @@ -4,12 +4,18 @@ DROP TABLE IF EXISTS Y; CREATE TABLE X (id Int) ENGINE=Memory; CREATE TABLE Y (id Int) ENGINE=Memory; --- Type mismatch of columns to JOIN by: plus(id, 1) Int64 at left, Y.id Int32 at right. -SELECT - Y.id - 1 -FROM X -RIGHT JOIN Y ON (X.id + 1) = Y.id -SETTINGS join_use_nulls=1; -- { serverError 53 } +SELECT Y.id - 1 FROM X RIGHT JOIN Y ON (X.id + 1) = Y.id SETTINGS join_use_nulls=1; +SELECT Y.id - 1 FROM X RIGHT JOIN Y ON (X.id + 1) = toInt64(Y.id) SETTINGS join_use_nulls=1; + +-- Fix issue #20366 +-- Arguments of 'plus' have incorrect data types: '2' of type 'UInt8', '1' of type 'UInt8'. +-- Because 1 became toNullable(1), i.e.: +-- 2 UInt8 Const(size = 1, UInt8(size = 1)) +-- 1 UInt8 Const(size = 1, Nullable(size = 1, UInt8(size = 1), UInt8(size = 1))) +SELECT 2+1 FROM system.one X RIGHT JOIN system.one Y ON X.dummy+1 = Y.dummy SETTINGS join_use_nulls = 1; +SELECT 2+1 FROM system.one X RIGHT JOIN system.one Y ON X.dummy+1 = toUInt16(Y.dummy) SETTINGS join_use_nulls = 1; +SELECT X.dummy+1 FROM system.one X RIGHT JOIN system.one Y ON X.dummy = Y.dummy SETTINGS join_use_nulls = 1; +SELECT Y.dummy+1 FROM system.one X RIGHT JOIN system.one Y ON X.dummy = Y.dummy SETTINGS join_use_nulls = 1; DROP TABLE X; DROP TABLE Y; diff --git a/tests/queries/0_stateless/01715_table_function_view_fix.reference b/tests/queries/0_stateless/01715_table_function_view_fix.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01715_table_function_view_fix.sql b/tests/queries/0_stateless/01715_table_function_view_fix.sql new file mode 100644 index 00000000000..de5150b7b70 --- /dev/null +++ b/tests/queries/0_stateless/01715_table_function_view_fix.sql @@ -0,0 +1 @@ +SELECT view(SELECT 1); -- { clientError 62 } diff --git a/tests/queries/0_stateless/01715_tuple_insert_null_as_default.reference b/tests/queries/0_stateless/01715_tuple_insert_null_as_default.reference new file mode 100644 index 00000000000..20f0fadfdcf --- /dev/null +++ b/tests/queries/0_stateless/01715_tuple_insert_null_as_default.reference @@ -0,0 +1,15 @@ +Tuple +(0,1) +(0,1) +Tuple nested in Array +[(0,2),(3,0),(0,4)] +[(0,2),(3,0),(0,4)] +Tuple nested in Array nested in Tuple +(0,[(0,2),(3,0),(0,4)]) +(0,[(0,2),(3,0),(0,4)]) +Tuple nested in Map +{'test':(0,1)} +{'test':(0,1)} +Tuple nested in Map nested in Tuple +(0,{'test':(0,1)}) +(0,{'test':(0,1)}) diff --git a/tests/queries/0_stateless/01715_tuple_insert_null_as_default.sql b/tests/queries/0_stateless/01715_tuple_insert_null_as_default.sql new file mode 100644 index 00000000000..d5fd9af22bd --- /dev/null +++ b/tests/queries/0_stateless/01715_tuple_insert_null_as_default.sql @@ -0,0 +1,77 @@ +SELECT 'Tuple'; + +DROP TABLE IF EXISTS test_tuple; +CREATE TABLE test_tuple (value Tuple(UInt8, UInt8)) ENGINE=TinyLog; + +SET input_format_null_as_default = 1; +INSERT INTO test_tuple VALUES ((NULL, 1)); +SELECT * FROM test_tuple; + +SET input_format_null_as_default = 0; +INSERT INTO test_tuple VALUES ((NULL, 2)); -- { clientError 53 } +SELECT * FROM test_tuple; + +DROP TABLE test_tuple; + +SELECT 'Tuple nested in Array'; + +DROP TABLE IF EXISTS test_tuple_nested_in_array; +CREATE TABLE test_tuple_nested_in_array (value Array(Tuple(UInt8, UInt8))) ENGINE=TinyLog; + +SET input_format_null_as_default = 1; +INSERT INTO test_tuple_nested_in_array VALUES ([(NULL, 2), (3, NULL), (NULL, 4)]); +SELECT * FROM test_tuple_nested_in_array; + +SET input_format_null_as_default = 0; +INSERT INTO test_tuple_nested_in_array VALUES ([(NULL, 1)]); -- { clientError 53 } +SELECT * FROM test_tuple_nested_in_array; + +DROP TABLE test_tuple_nested_in_array; + +SELECT 'Tuple nested in Array nested in Tuple'; + +DROP TABLE IF EXISTS test_tuple_nested_in_array_nested_in_tuple; +CREATE TABLE test_tuple_nested_in_array_nested_in_tuple (value Tuple(UInt8, Array(Tuple(UInt8, UInt8)))) ENGINE=TinyLog; + +SET input_format_null_as_default = 1; +INSERT INTO test_tuple_nested_in_array_nested_in_tuple VALUES ( (NULL, [(NULL, 2), (3, NULL), (NULL, 4)]) ); +SELECT * FROM test_tuple_nested_in_array_nested_in_tuple; + +SET input_format_null_as_default = 0; +INSERT INTO test_tuple_nested_in_array_nested_in_tuple VALUES ( (NULL, [(NULL, 1)]) ); -- { clientError 53 } +SELECT * FROM test_tuple_nested_in_array_nested_in_tuple; + +DROP TABLE test_tuple_nested_in_array_nested_in_tuple; + +SELECT 'Tuple nested in Map'; + +SET allow_experimental_map_type = 1; + +DROP TABLE IF EXISTS test_tuple_nested_in_map; +CREATE TABLE test_tuple_nested_in_map (value Map(String, Tuple(UInt8, UInt8))) ENGINE=TinyLog; + +SET input_format_null_as_default = 1; +INSERT INTO test_tuple_nested_in_map VALUES (map('test', (NULL, 1))); + +SELECT * FROM test_tuple_nested_in_map; + +SET input_format_null_as_default = 0; +INSERT INTO test_tuple_nested_in_map VALUES (map('test', (NULL, 1))); -- { clientError 53 } +SELECT * FROM test_tuple_nested_in_map; + +DROP TABLE test_tuple_nested_in_map; + +SELECT 'Tuple nested in Map nested in Tuple'; + +DROP TABLE IF EXISTS test_tuple_nested_in_map_nested_in_tuple; +CREATE TABLE test_tuple_nested_in_map_nested_in_tuple (value Tuple(UInt8, Map(String, Tuple(UInt8, UInt8)))) ENGINE=TinyLog; + +SET input_format_null_as_default = 1; +INSERT INTO test_tuple_nested_in_map_nested_in_tuple VALUES ( (NULL, map('test', (NULL, 1))) ); +SELECT * FROM test_tuple_nested_in_map_nested_in_tuple; + +SET input_format_null_as_default = 0; +INSERT INTO test_tuple_nested_in_map_nested_in_tuple VALUES ( (NULL, map('test', (NULL, 1))) ); -- { clientError 53 } +SELECT * FROM test_tuple_nested_in_map_nested_in_tuple; + +DROP TABLE test_tuple_nested_in_map_nested_in_tuple; diff --git a/tests/queries/0_stateless/01716_array_difference_overflow.reference b/tests/queries/0_stateless/01716_array_difference_overflow.reference new file mode 100644 index 00000000000..5297534679e --- /dev/null +++ b/tests/queries/0_stateless/01716_array_difference_overflow.reference @@ -0,0 +1 @@ +[0,9223372036854710272] diff --git a/tests/queries/0_stateless/01716_array_difference_overflow.sql b/tests/queries/0_stateless/01716_array_difference_overflow.sql new file mode 100644 index 00000000000..3d153725294 --- /dev/null +++ b/tests/queries/0_stateless/01716_array_difference_overflow.sql @@ -0,0 +1,2 @@ +-- Overflow is Ok and behaves as the CPU does it. +SELECT arrayDifference([65536, -9223372036854775808]); diff --git a/tests/queries/0_stateless/01716_decimal_comparison_ubsan.reference b/tests/queries/0_stateless/01716_decimal_comparison_ubsan.reference new file mode 100644 index 00000000000..573541ac970 --- /dev/null +++ b/tests/queries/0_stateless/01716_decimal_comparison_ubsan.reference @@ -0,0 +1 @@ +0 diff --git a/tests/queries/0_stateless/01716_decimal_comparison_ubsan.sql b/tests/queries/0_stateless/01716_decimal_comparison_ubsan.sql new file mode 100644 index 00000000000..f68d9de1995 --- /dev/null +++ b/tests/queries/0_stateless/01716_decimal_comparison_ubsan.sql @@ -0,0 +1,2 @@ +SET decimal_check_overflow = 0; +SELECT toDecimal64(0, 8) = 9223372036854775807; diff --git a/tests/queries/0_stateless/01716_drop_rename_sign_column.reference b/tests/queries/0_stateless/01716_drop_rename_sign_column.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01716_drop_rename_sign_column.sql b/tests/queries/0_stateless/01716_drop_rename_sign_column.sql new file mode 100644 index 00000000000..c9119ee2b46 --- /dev/null +++ b/tests/queries/0_stateless/01716_drop_rename_sign_column.sql @@ -0,0 +1,14 @@ +DROP TABLE IF EXISTS signed_table; + +CREATE TABLE signed_table ( + k UInt32, + v String, + s Int8 +) ENGINE CollapsingMergeTree(s) ORDER BY k; + +INSERT INTO signed_table(k, v, s) VALUES (1, 'a', 1); + +ALTER TABLE signed_table DROP COLUMN s; --{serverError 524} +ALTER TABLE signed_table RENAME COLUMN s TO s1; --{serverError 524} + +DROP TABLE IF EXISTS signed_table; diff --git a/tests/queries/0_stateless/01717_global_with_subquery_fix.reference b/tests/queries/0_stateless/01717_global_with_subquery_fix.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01717_global_with_subquery_fix.sql b/tests/queries/0_stateless/01717_global_with_subquery_fix.sql new file mode 100644 index 00000000000..14c4ac3e4ca --- /dev/null +++ b/tests/queries/0_stateless/01717_global_with_subquery_fix.sql @@ -0,0 +1 @@ +WITH (SELECT count(distinct colU) from tabA) AS withA, (SELECT count(distinct colU) from tabA) AS withB SELECT withA / withB AS ratio FROM (SELECT date AS period, colX FROM (SELECT date, if(colA IN (SELECT colB FROM tabC), 0, colA) AS colX FROM tabB) AS tempB GROUP BY period, colX) AS main; -- {serverError 60} diff --git a/tests/queries/0_stateless/01717_int_div_float_too_large_ubsan.reference b/tests/queries/0_stateless/01717_int_div_float_too_large_ubsan.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01717_int_div_float_too_large_ubsan.sql b/tests/queries/0_stateless/01717_int_div_float_too_large_ubsan.sql new file mode 100644 index 00000000000..c4f26a079f0 --- /dev/null +++ b/tests/queries/0_stateless/01717_int_div_float_too_large_ubsan.sql @@ -0,0 +1,2 @@ +SELECT intDiv(9223372036854775807, 0.9998999834060669); -- { serverError 153 } +SELECT intDiv(9223372036854775807, 1.); -- { serverError 153 } diff --git a/tests/queries/0_stateless/01718_subtract_seconds_date.reference b/tests/queries/0_stateless/01718_subtract_seconds_date.reference new file mode 100644 index 00000000000..97e3da8cc48 --- /dev/null +++ b/tests/queries/0_stateless/01718_subtract_seconds_date.reference @@ -0,0 +1,2 @@ +2021-02-14 23:59:59 +10 diff --git a/tests/queries/0_stateless/01718_subtract_seconds_date.sql b/tests/queries/0_stateless/01718_subtract_seconds_date.sql new file mode 100644 index 00000000000..6bffcd4db5a --- /dev/null +++ b/tests/queries/0_stateless/01718_subtract_seconds_date.sql @@ -0,0 +1,2 @@ +SELECT subtractSeconds(toDate('2021-02-15'), 1); +SELECT subtractSeconds(today(), 1) - subtractSeconds(today(), 11); diff --git a/tests/queries/0_stateless/01719_join_timezone.reference b/tests/queries/0_stateless/01719_join_timezone.reference new file mode 100644 index 00000000000..c2702a38012 --- /dev/null +++ b/tests/queries/0_stateless/01719_join_timezone.reference @@ -0,0 +1,3 @@ +2020-05-13 13:38:45 2020-05-13 16:38:45 +2020-05-13 13:38:45 2020-05-13 16:38:45 +2020-05-13 13:38:45 2020-05-13 16:38:45 diff --git a/tests/queries/0_stateless/01719_join_timezone.sql b/tests/queries/0_stateless/01719_join_timezone.sql new file mode 100644 index 00000000000..cbf0c27fcfc --- /dev/null +++ b/tests/queries/0_stateless/01719_join_timezone.sql @@ -0,0 +1,45 @@ +DROP TABLE IF EXISTS test; + +CREATE TABLE test (timestamp DateTime('UTC'), i UInt8) Engine=MergeTree() PARTITION BY toYYYYMM(timestamp) ORDER BY (i); +INSERT INTO test values ('2020-05-13 16:38:45', 1); + +SELECT + toTimeZone(timestamp, 'America/Sao_Paulo') AS converted, + timestamp AS original +FROM test +LEFT JOIN (SELECT 2 AS x) AS anything ON x = i +WHERE timestamp >= toDateTime('2020-05-13T00:00:00', 'America/Sao_Paulo'); + +/* This was incorrect result in previous ClickHouse versions: +┌─converted───────────┬─original────────────┐ +│ 2020-05-13 16:38:45 │ 2020-05-13 16:38:45 │ <-- toTimeZone is ignored. +└─────────────────────┴─────────────────────┘ +*/ + +SELECT + toTimeZone(timestamp, 'America/Sao_Paulo') AS converted, + timestamp AS original +FROM test +-- LEFT JOIN (SELECT 2 AS x) AS anything ON x = i -- Removing the join fixes the issue. +WHERE timestamp >= toDateTime('2020-05-13T00:00:00', 'America/Sao_Paulo'); + +/* +┌─converted───────────┬─original────────────┐ +│ 2020-05-13 13:38:45 │ 2020-05-13 16:38:45 │ <-- toTimeZone works. +└─────────────────────┴─────────────────────┘ +*/ + +SELECT + toTimeZone(timestamp, 'America/Sao_Paulo') AS converted, + timestamp AS original +FROM test +LEFT JOIN (SELECT 2 AS x) AS anything ON x = i +WHERE timestamp >= '2020-05-13T00:00:00'; -- Not using toDateTime in the WHERE also fixes the issue. + +/* +┌─converted───────────┬─original────────────┐ +│ 2020-05-13 13:38:45 │ 2020-05-13 16:38:45 │ <-- toTimeZone works. +└─────────────────────┴─────────────────────┘ +*/ + +DROP TABLE test; diff --git a/tests/queries/0_stateless/01720_constraints_complex_types.reference b/tests/queries/0_stateless/01720_constraints_complex_types.reference new file mode 100644 index 00000000000..01e79c32a8c --- /dev/null +++ b/tests/queries/0_stateless/01720_constraints_complex_types.reference @@ -0,0 +1,3 @@ +1 +2 +3 diff --git a/tests/queries/0_stateless/01720_constraints_complex_types.sql b/tests/queries/0_stateless/01720_constraints_complex_types.sql new file mode 100644 index 00000000000..273f509b6eb --- /dev/null +++ b/tests/queries/0_stateless/01720_constraints_complex_types.sql @@ -0,0 +1,47 @@ +SET allow_suspicious_low_cardinality_types = 1; + +DROP TABLE IF EXISTS constraint_on_nullable_type; +CREATE TABLE constraint_on_nullable_type +( + `id` Nullable(UInt64), + CONSTRAINT `c0` CHECK `id` = 1 +) +ENGINE = TinyLog(); + +INSERT INTO constraint_on_nullable_type VALUES (0); -- {serverError 469} +INSERT INTO constraint_on_nullable_type VALUES (1); + +SELECT * FROM constraint_on_nullable_type; + +DROP TABLE constraint_on_nullable_type; + +DROP TABLE IF EXISTS constraint_on_low_cardinality_type; +CREATE TABLE constraint_on_low_cardinality_type +( + `id` LowCardinality(UInt64), + CONSTRAINT `c0` CHECK `id` = 2 +) +ENGINE = TinyLog; + +INSERT INTO constraint_on_low_cardinality_type VALUES (0); -- {serverError 469} +INSERT INTO constraint_on_low_cardinality_type VALUES (2); + +SELECT * FROM constraint_on_low_cardinality_type; + +DROP TABLE constraint_on_low_cardinality_type; + +DROP TABLE IF EXISTS constraint_on_low_cardinality_nullable_type; + +CREATE TABLE constraint_on_low_cardinality_nullable_type +( + `id` LowCardinality(Nullable(UInt64)), + CONSTRAINT `c0` CHECK `id` = 3 +) +ENGINE = TinyLog; + +INSERT INTO constraint_on_low_cardinality_nullable_type VALUES (0); -- {serverError 469} +INSERT INTO constraint_on_low_cardinality_nullable_type VALUES (3); + +SELECT * FROM constraint_on_low_cardinality_nullable_type; + +DROP TABLE constraint_on_low_cardinality_nullable_type; diff --git a/tests/queries/0_stateless/01720_country_intersection.reference b/tests/queries/0_stateless/01720_country_intersection.reference new file mode 100644 index 00000000000..5b7cee92bdc --- /dev/null +++ b/tests/queries/0_stateless/01720_country_intersection.reference @@ -0,0 +1,104 @@ +Dhekelia Sovereign Base Area Dhekelia Sovereign Base Area [[[(33.847423,34.94245),(33.819672,34.964748),(33.80421,34.972602),(33.781896,34.976212),(33.784945,34.976212),(33.788046,34.976988),(33.7928,34.977763),(33.79435,34.977763),(33.791146,34.982414),(33.786495,34.984687),(33.782568,34.984687),(33.777917,34.984687),(33.77399,34.988666),(33.766135,34.990268),(33.761484,34.990268),(33.75921,34.988666),(33.765411,34.985566),(33.769339,34.983964),(33.770889,34.980088),(33.77554,34.980088),(33.780191,34.979313),(33.780986,34.976338),(33.780935,34.976345),(33.760427,34.979682),(33.717296,34.977769),(33.70152,34.97289),(33.702935,34.987943),(33.711461,34.985566),(33.71544,34.997296),(33.699731,35.002722),(33.69663,35.008975),(33.705312,35.015228),(33.702211,35.022256),(33.685003,35.029284),(33.679444,35.033891),(33.679435,35.033899),(33.675649,35.037036),(33.674099,35.046441),(33.678853,35.055794),(33.69446,35.058171),(33.705312,35.06675),(33.714717,35.06675),(33.719368,35.06277),(33.711461,35.040963),(33.707585,35.029284),(33.718489,35.032385),(33.739677,35.047216),(33.766135,35.03161),(33.77554,35.040188),(33.786495,35.038534),(33.79435,35.040188),(33.798278,35.052642),(33.824012,35.06675),(33.834865,35.063597),(33.842719,35.056621),(33.853571,35.058171),(33.866904,35.06675),(33.871555,35.073054),(33.876929,35.076826),(33.871555,35.085456),(33.871555,35.100236),(33.876206,35.118994),(33.889435,35.118994),(33.891812,35.110468),(33.89884,35.108814),(33.903594,35.099512),(33.905868,35.09636),(33.905868,35.090882),(33.913619,35.090882),(33.921474,35.080702),(33.914446,35.073054),(33.908245,35.070729),(33.906524,35.069122),(33.906506,35.069105),(33.898116,35.061272),(33.880133,35.073054),(33.874655,35.067525),(33.867627,35.060497),(33.855122,35.053417),(33.841169,35.051092),(33.834865,35.056621),(33.827113,35.061272),(33.813781,35.055794),(33.804375,35.049541),(33.799001,35.038534),(33.822359,35.030059),(33.830214,35.023031),(33.829387,35.001176),(33.829387,35.001172),(33.840342,34.993369),(33.859049,34.991819),(33.859049,34.974662),(33.850471,34.973009),(33.838068,34.963707),(33.84582,34.959728),(33.864423,34.962983),(33.891841,34.958139),(33.8838,34.949123),(33.874522,34.94123),(33.862315,34.937893),(33.847423,34.94245)],[(33.746689,35.002711),(33.752063,35.004323),(33.752063,35.0144),(33.746151,35.015207),(33.741314,35.013729),(33.740239,35.010101),(33.738761,35.005264),(33.739702,35.002576),(33.742792,35.001233),(33.746689,35.002711)]]] +Dhekelia Sovereign Base Area Kyrgyzstan [] +Kyrgyzstan Dhekelia Sovereign Base Area [] +Kyrgyzstan Kyrgyzstan [[[(74.746683,40.336505),(74.724668,40.337539),(74.705755,40.331286),(74.654388,40.291547),(74.637645,40.281987),(74.598681,40.266174),(74.565402,40.24695),(74.476622,40.172433),(74.369858,40.105822),(74.333788,40.09373),(74.302885,40.090061),(74.272293,40.093833),(74.237876,40.10391),(74.20315,40.109853),(74.167596,40.10639),(74.13287,40.095332),(74.101244,40.078847),(74.069515,40.067788),(74.003989,40.060812),(73.976704,40.043603),(73.966368,40.033268),(73.957894,40.021434),(73.952106,40.008257),(73.949729,39.993684),(73.944044,39.970068),(73.927301,39.953325),(73.907561,39.937873),(73.893195,39.918133),(73.885443,39.876534),(73.880689,39.86501),(73.872937,39.856845),(73.844102,39.838086),(73.83201,39.82372),(73.823018,39.805685),(73.818574,39.786048),(73.819814,39.766721),(73.829529,39.746981),(73.843068,39.740366),(73.859915,39.737162),(73.879345,39.727912),(73.893505,39.710394),(73.899602,39.689465),(73.904253,39.64647),(73.926784,39.592882),(73.921617,39.582133),(73.899292,39.571539),(73.883066,39.561204000000004),(73.870457,39.546786),(73.859192,39.524255),(73.848029,39.489735),(73.838314,39.475679),(73.820744,39.468186),(73.632642,39.448343),(73.604323,39.459608),(73.512236,39.467411),(73.476889,39.464776),(73.367645,39.443795),(73.343151,39.430669),(73.335503,39.415166),(73.333332,39.40111),(73.326408,39.390878),(73.269357,39.382558),(73.167864,39.355377),(73.136032,39.353465),(73.100995,39.361164),(73.083425,39.367831),(73.071126,39.370725),(73.058414,39.368813),(73.009321,39.348607),(72.994335,39.347832),(72.976765,39.352224),(72.91434,39.362715),(72.893669,39.363903),(72.850468,39.35672),(72.835275,39.356204),(72.65048,39.393772),(72.633737,39.394496),(72.616373,39.390413),(72.606141,39.383489),(72.587021,39.364885),(72.575756,39.359304),(72.559426,39.359562),(72.534104,39.372327),(72.519015,39.375686),(72.50806,39.371965),(72.476744,39.346127),(72.460414,39.344111),(72.443567,39.344783),(72.410701,39.351346),(72.393234,39.350829),(72.355924,39.336101),(72.334117,39.333828),(72.31634,39.328815),(72.304248,39.31357),(72.281407,39.259724),(72.240272,39.189909),(72.228903,39.189237),(72.228668,39.189502),(72.218568,39.20089),(72.209163,39.217297),(72.206476,39.226883),(72.206373,39.234609),(72.203272,39.24081),(72.182395,39.249337),(72.167098,39.258742),(72.158623,39.262617),(72.115525,39.268147),(72.094751,39.275072),(72.08576,39.290109),(72.084106,39.311245),(72.078112,39.336618),(72.06695,39.358477),(72.049793,39.368864),(72.031499,39.366694),(71.996463,39.351863),(71.959152,39.345868),(71.942306,39.339047),(71.843501,39.285045),(71.807017,39.272849),(71.77043,39.269542),(71.751207,39.274245),(71.732913,39.285097),(71.71834,39.301065),(71.710899,39.32096),(71.712966,39.341527),(71.723198,39.353981),(71.736634,39.364575),(71.748106,39.379561),(71.751827,39.399663),(71.749243,39.425502),(71.740251,39.448343),(71.724438,39.459401),(71.704594,39.458988),(71.602792,39.442348),(71.554319,39.444157),(71.512875,39.458833),(71.492101,39.493663),(71.500576,39.509217),(71.526001,39.538156),(71.531375,39.553091),(71.52538,39.569162),(71.510911,39.584148),(71.509654,39.584998),(71.493031,39.596241),(71.459545,39.612105),(71.441251,39.610658),(71.406731,39.598153),(71.378309,39.594173),(71.368543,39.591486),(71.36161799999999,39.587559),(71.347872,39.576242),(71.340586,39.571694),(71.305911,39.557173),(71.291958,39.548957),(71.260074,39.520638),(71.249273,39.514385),(71.236923,39.514488),(71.179975,39.523015),(71.137446,39.521155),(71.095898,39.51237),(71.062928,39.495627),(71.042309,39.467876),(71.027581,39.435217),(71.009288,39.407622),(70.977145,39.394909),(70.949808,39.400749),(70.925159,39.412944),(70.903351,39.420851),(70.884489,39.413874),(70.872242,39.402971),(70.864181,39.400594),(70.855292,39.40173),(70.840099,39.40142),(70.828059,39.398578),(70.797621,39.385349),(70.770129,39.382093),(70.739744,39.386228),(70.713285,39.398423),(70.698092,39.41899),(70.698609,39.431393),(70.703053,39.444725),(70.705431,39.458523),(70.699746,39.472165),(70.690134,39.479193),(70.666725,39.486893),(70.655976,39.493663),(70.655976,39.493714),(70.655925,39.49387),(70.655598,39.494664),(70.635977,39.542497),(70.622128,39.563529),(70.59784,39.577792),(70.58027,39.579549),(70.54358,39.574278),(70.526113,39.575622),(70.513504,39.581513),(70.490973,39.596861),(70.477227,39.601201),(70.459967,39.599548),(70.427618,39.590091),(70.411082,39.587456),(70.40147,39.584768),(70.395372,39.579497),(70.390411,39.57402),(70.384313,39.570867),(70.374288,39.571022),(70.353462,39.575932),(70.343179,39.576862),(70.33026,39.573089),(70.241066,39.522395),(70.223289,39.519087999999996),(70.20603,39.5241),(70.204376,39.538156),(70.215021,39.574071),(70.214814,39.591125),(70.210267,39.609728),(70.200655,39.619495),(70.185204,39.610348),(70.15735,39.563891),(70.148979,39.554279),(70.132442,39.550042),(70.116268,39.554641),(70.08273,39.569782000000004),(70.062266,39.573451),(70.040355,39.573606),(70.019684,39.568594),(70.002734,39.556863),(69.987128,39.539603),(69.978757,39.534436),(69.948629,39.545081),(69.907753,39.548492),(69.830445,39.536244),(69.791585,39.545391),(69.74983,39.563839),(69.710349,39.574071),(69.669421,39.577792),(69.582295,39.573555),(69.564932,39.568129),(69.531445,39.545649),(69.514392,39.537588),(69.496099,39.532575),(69.477288,39.530405),(69.455274,39.530456),(69.412176,39.52503),(69.391454,39.530508),(69.367218,39.549938),(69.361637,39.552884),(69.352025,39.549628),(69.348407,39.543169),(69.345927,39.535366),(69.339726,39.528079),(69.300348,39.515625),(69.286189,39.539707),(69.29115,39.658872),(69.287533,39.677786),(69.280091,39.694271),(69.265932,39.707758),(69.248362,39.719385),(69.233324,39.732666),(69.226296,39.751011),(69.229552,39.790544),(69.240714,39.82894),(69.286447,39.935755),(69.305671,39.968621),(69.310064,39.978646),(69.310322,39.984796),(69.313991,39.986914),(69.32784,39.984744),(69.357296,39.959474),(69.405355,39.896119),(69.501576,39.922474),(69.500439,39.935703),(69.477288,39.968156),(69.478115,39.975029),(69.477288,39.981592),(69.475118,39.987741),(69.471191,39.993684),(69.463129,40.025413),(69.46964,40.050993),(69.485712,40.073731),(69.506331,40.096933),(69.509224,40.103445),(69.513462,40.120705),(69.518009,40.125097),(69.526071,40.123185),(69.536613,40.107889),(69.543021,40.103083),(69.558834,40.101739),(69.575474,40.1036),(69.969558,40.211603),(70.004595,40.208761),(70.14717,40.136983),(70.168822,40.13166),(70.218535,40.134141),(70.241531,40.132745),(70.263494,40.12427),(70.277808,40.112075),(70.290262,40.098174),(70.306282,40.08479),(70.324265,40.077503),(70.359509,40.074041),(70.397646,40.061225),(70.477227,40.052027),(70.502135,40.045981),(70.525493,40.033682),(70.535622,40.015957),(70.520946,39.993736),(70.505029,39.985106),(70.488493,39.978543),(70.473197,39.97012),(70.460226,39.956115),(70.450872,39.937408),(70.44803,39.919993),(70.455627,39.906816),(70.477227,39.900925),(70.485961,39.909606),(70.494177,39.931672),(70.500895,39.940561),(70.512574,39.94516),(70.555052,39.946245),(70.576601,39.952239),(70.5966,39.961955),(70.613963,39.975752),(70.627399,39.993891),(70.635977,40.028514),(70.634737,40.059313),(70.63944,40.084945),(70.66595,40.104168),(70.729822,40.120705),(70.743464,40.127113),(70.782532,40.152589),(70.788733,40.158997),(70.792144,40.161374),(70.797725,40.161942),(70.802686,40.160134),(70.806045,40.157653),(70.806716,40.156155),(70.824906,40.163544),(70.831831,40.168195),(70.845164,40.171813),(70.898545,40.162614),(70.929293,40.170624),(70.962883,40.189693),(70.979522,40.214084),(70.958955,40.238372),(70.995129,40.266587),(71.053213,40.274235),(71.169382,40.26142),(71.201008,40.263848),(71.215115,40.280747),(71.223952,40.302864),(71.239558,40.321106),(71.253821,40.324413),(71.263949,40.318212),(71.272838,40.307722),(71.283225,40.29842),(71.297074,40.293821),(71.313559,40.292684),(71.344926,40.295216),(71.365132,40.294131),(71.396551,40.271548),(71.441355,40.260903),(71.450966,40.248914),(71.458925,40.234134),(71.477115,40.220802),(71.498405,40.210518),(71.521246,40.203749),(71.568272,40.196566),(71.592973,40.198426),(71.601655,40.20995),(71.604032,40.227261),(71.61013,40.246382),(71.62832,40.258887),(71.645993,40.247105),(71.660153,40.224471),(71.667181,40.204162),(71.666871,40.163131),(71.673072,40.147886),(71.693329,40.141117),(71.707178,40.144269),(71.759785,40.168092),(71.775908,40.179926),(71.78676,40.193517),(71.805467,40.225298),(71.836473,40.249172),(71.872956,40.250774),(71.912334,40.243436),(71.951814,40.240904),(71.96339,40.243746),(71.969178,40.244418),(71.977033,40.243074),(71.989021,40.239302),(72.004834,40.237287),(72.01889,40.240026),(72.025402,40.250878),(72.019821,40.258732),(72.013239,40.262072),(72.005971,40.26576),(71.977033,40.276096),(71.958222,40.286534),(71.951091,40.30152),(71.951094,40.301529),(71.956672,40.31568),(72.043178,40.349321),(72.069637,40.369423),(72.084106,40.39738),(72.090101,40.416035),(72.099299,40.426371),(72.165858,40.454431),(72.182705,40.45779),(72.228328,40.459606),(72.235931,40.459909),(72.254225,40.458307),(72.263415,40.452651),(72.26363,40.452519),(72.259599,40.44239),(72.24513,40.438721),(72.228077,40.437533),(72.216501,40.434949),(72.211768,40.425836),(72.211644,40.425596),(72.224356,40.422443),(72.269624,40.424045),(72.284301,40.41986),(72.343418,40.393401),(72.370497,40.38565),(72.394061,40.389422),(72.414422,40.410713),(72.425171,40.435983),(72.426204,40.45934),(72.426096,40.459545),(72.420028,40.471027),(72.415662,40.479287),(72.415585,40.47933),(72.372254,40.503265),(72.363469,40.512309),(72.363467,40.51241),(72.363262,40.523573999999996),(72.36998,40.539852),(72.370083,40.557732),(72.369928,40.557930999999996),(72.348483,40.585379),(72.348509,40.585508),(72.351893,40.601967),(72.381556,40.612148),(72.414835,40.589875),(72.447908,40.560471),(72.476744,40.549567),(72.515294,40.54564),(72.585781,40.508743),(72.625468,40.5105),(72.640868,40.519853),(72.65048,40.532151999999996),(72.655131,40.546363),(72.656474,40.561143),(72.664226,40.577783),(72.682416,40.577679),(72.719209,40.564864),(72.748355,40.575096),(72.760034,40.641758),(72.783908,40.669663),(72.818945,40.681084),(72.890982,40.695088),(72.976765,40.736068),(73.070609,40.762474),(73.118048,40.782938),(73.148641,40.813686),(73.14337,40.833839),(73.143292,40.833853),(73.135042,40.835274),(73.112467,40.839162),(73.053556,40.83632),(73.033299,40.847224),(73.01945,40.8619),(73.00343,40.870168),(72.929429,40.844175),(72.883127,40.819628),(72.870311,40.818181),(72.872998,40.834821),(72.868658,40.864122),(72.830107,40.87208),(72.701226,40.863243),(72.658231,40.867171),(72.619474,40.88009),(72.588468,40.905825),(72.545577,40.956519),(72.52625,40.962204),(72.501445,40.963496),(72.483358,40.970575),(72.483565,40.99352),(72.485219,40.999566),(72.484702,41.004682),(72.481911,41.008816),(72.476744,41.011813),(72.423517,41.01574),(72.395198,41.022045),(72.374321,41.031967),(72.345692,41.06597),(72.33236,41.072843),(72.314066,41.061681),(72.308795,41.054446),(72.297323,41.028143),(72.289778,41.023544),(72.252985,41.019616),(72.195486,41.006358),(72.165135,40.999359),(72.178777,41.023182),(72.185599,41.041062),(72.185599,41.060647),(72.1764,41.112892),(72.174643,41.141418),(72.169889,41.168651),(72.158417,41.187875),(72.132889,41.199295),(72.108497,41.196401),(72.085243,41.184877),(72.063642,41.170201),(72.033773,41.15661),(72.016513,41.163535),(72.001217,41.18002),(71.977033,41.195213),(71.897658,41.184929),(71.871613,41.194489),(71.866342,41.236606),(71.868822,41.279239),(71.863034,41.312208),(71.847015,41.341819),(71.75317,41.44729),(71.745212,41.45282),(71.73684,41.455404),(71.730433,41.451166),(71.729709,41.430082),(71.721648,41.424759),(71.712242,41.428015),(71.706868,41.444086),(71.696119,41.447445),(71.691469,41.441916),(71.687334,41.431012),(71.681443,41.422847),(71.671935,41.425483),(71.671108,41.437627),(71.689505,41.493799),(71.689401,41.514625),(71.68413,41.534055),(71.671418,41.547388),(71.649507,41.54992),(71.62739,41.543202),(71.615297,41.532143),(71.595454,41.493799),(71.595454,41.493747),(71.595557,41.493696),(71.595557,41.493489),(71.605582,41.476849),(71.633694,41.449616),(71.637415,41.431271),(71.633074,41.411324),(71.618811,41.377786),(71.585532,41.323525),(71.557937,41.301718),(71.52383,41.296654),(71.480629,41.310761),(71.432466,41.344816),(71.418772,41.3474),(71.412571,41.334687),(71.421459,41.162088),(71.416085,41.127362),(71.393657,41.112737),(71.325238,41.157334),(71.300226,41.133046),(71.289478,41.113874),(71.276145,41.113151),(71.263381,41.123486),(71.253821,41.13749),(71.241522,41.175162),(71.230153,41.187255),(71.206382,41.188753),(71.185711,41.180227),(71.183024,41.166377),(71.187882,41.148446),(71.189949,41.127465),(71.18013,41.108138),(71.164421,41.116199),(71.139099,41.148394),(71.123079,41.158212),(71.085769,41.162036),(71.067579,41.169736),(71.047012,41.182035),(71.024688,41.189787),(70.977145,41.19635),(70.93415,41.19144),(70.914203,41.193042),(70.895962,41.206116),(70.882164,41.220482),(70.865731,41.233195),(70.847747,41.243065),(70.828524,41.249111),(70.805993,41.247458),(70.786563,41.24043),(70.770439,41.238518),(70.758037,41.25216),(70.75628,41.269627),(70.77106,41.331018),(70.769199,41.352102),(70.759691,41.372515),(70.70357,41.445482),(70.686724,41.462483),(70.66781,41.471372),(70.633807,41.467496),(70.511334,41.414476),(70.477227,41.404657),(70.470782,41.404879),(70.453198,41.405484),(70.438057,41.416078),(70.413614,41.450701),(70.398989,41.464964),(70.382246,41.476436),(70.344936,41.493489),(70.344729,41.493644),(70.344522,41.493696),(70.344419,41.493799),(70.203446,41.505633),(70.166549,41.520206),(70.148255,41.552452),(70.169288,41.578342),(70.33119,41.649629),(70.390824,41.685054),(70.423484,41.696913),(70.453663,41.71208),(70.477227,41.738435),(70.506476,41.78559),(70.550091,41.824063),(70.648948,41.887393),(70.679696,41.901113),(70.779328,41.909665),(70.814003,41.919535),(70.825113,41.93633),(70.828059,41.993743),(70.845474,42.030356),(70.886711,42.038495),(70.935907,42.036867),(70.977145,42.044231),(71.118429,42.122908),(71.201008,42.140788),(71.238215,42.160244),(71.253201,42.197555),(71.249868,42.198385),(71.217854,42.206365),(71.077604,42.281167),(71.045772,42.29096),(71.014042,42.287704),(70.9696,42.263468),(70.947793,42.248146),(70.918648,42.253365),(70.897822,42.261608),(70.858134,42.291063),(70.852657,42.306075),(70.864801,42.321552),(70.888825,42.338575),(70.900354,42.346744),(70.932703,42.3762),(70.939835,42.387827),(70.937354,42.394778),(70.931773,42.401496),(70.929913,42.412296),(70.936114,42.431623),(70.947586,42.451286),(70.961952,42.468107),(70.977145,42.478752),(71.024739,42.455963),(71.041017,42.4548),(71.054712,42.460381),(71.064168,42.470329),(71.066287,42.482137),(71.057864,42.493402),(71.057657,42.493402),(71.057554,42.493506),(71.057554,42.493609),(71.022724,42.51645),(71.012699,42.526036),(71.00319,42.563527),(71.040656,42.580529),(71.127007,42.590606),(71.142768,42.602543),(71.148091,42.6174),(71.146437,42.656855),(71.149021,42.677939),(71.157548,42.687938),(71.19522,42.69724),(71.211446,42.705224),(71.223849,42.717936),(71.245449,42.747133),(71.262502,42.753567),(71.284723,42.7484),(71.308495,42.740105),(71.329785,42.737031),(71.347562,42.742844),(71.363065,42.75411),(71.376294,42.768321),(71.386939,42.783074),(71.404613,42.794883),(71.428849,42.79558),(71.477115,42.78354),(71.493651,42.788914),(71.504193,42.789612),(71.51432199999999,42.78571),(71.553803,42.760905),(71.566308,42.757236),(71.583568,42.759639),(71.693536,42.811807),(71.726402,42.819660999999996),(71.796682,42.822297),(71.831408,42.831573),(71.847738,42.834053),(71.863241,42.829041),(71.878847,42.821341),(71.895384,42.816044),(71.956982,42.804598),(72.072737,42.757185),(72.10488,42.750337),(72.11997,42.75181),(72.148805,42.76199),(72.164101,42.765091),(72.292362,42.76106),(72.358405,42.741397),(72.476744,42.682564),(72.51178,42.677551),(72.583817,42.678275),(72.725824,42.652876),(72.756933,42.640215),(72.780601,42.620449),(72.815224,42.573036),(72.840752,42.555698),(72.874549,42.543993),(72.908345,42.536965),(72.942348,42.536035),(73.070609,42.551926),(73.115051,42.550841),(73.152671,42.539213),(73.172722,42.527845),(73.189052,42.520765),(73.206828,42.517173),(73.278348,42.513401),(73.301396,42.507071),(73.316589,42.493712),(73.313385,42.463171),(73.314419,42.441571),(73.326201,42.428677),(73.417461,42.41705),(73.476889,42.399067),(73.505105,42.402943),(73.505518,42.420926),(73.505077,42.421557),(73.432964,42.524847),(73.417565,42.556163),(73.41002,42.58965),(73.412707,42.627322),(73.423869,42.662772),(73.476889,42.75088),(73.503554,42.794082),(73.507068,42.809404),(73.504278,42.827594),(73.491979,42.861003),(73.489498,42.877823),(73.493012,42.894954),(73.501177,42.909346),(73.521744,42.936166),(73.559675,43.017298),(73.57094,43.031922),(73.58665,43.042283),(73.634089,43.062463),(73.805551,43.114734),(73.822811,43.117318),(73.864256,43.116103),(73.90167,43.13096),(73.935053,43.199716),(73.965335,43.216924),(73.985385,43.211679),(74.021456,43.186306),(74.039852,43.181861),(74.197362,43.195788),(74.213899,43.202635),(74.216586,43.216924),(74.206044,43.234106),(74.178759,43.261702),(74.207697,43.24979),(74.25865,43.215761),(74.286969,43.207209),(74.320042,43.201654),(74.348774,43.191034),(74.400554,43.159537),(74.420604,43.151837),(74.462772,43.148634),(74.498222,43.131115),(74.539253,43.122899),(74.558167,43.115044),(74.572016,43.102202),(74.597028,43.070344),(74.61129,43.058174),(74.71392,42.999883),(74.74875,42.990013),(74.862851,42.975828),(74.948531,42.944848),(74.976849,42.926477),(75.005375,42.9164),(75.066146,42.902602),(75.094258,42.890303),(75.118133,42.876531),(75.178594,42.84966),(75.204639,42.84519),(75.271198,42.845758000000004),(75.496611,42.823925),(75.535988,42.827025),(75.555936,42.825217),(75.620428,42.805295),(75.646163,42.806096),(75.675308,42.815371999999996),(75.703833,42.830488),(75.727605,42.848678),(75.73825,42.861571),(75.770599,42.92565),(75.782072,42.933324),(75.797161,42.936192),(75.807059,42.936771),(75.858966,42.939809),(75.898033,42.935701),(75.976582,42.918725),(75.999113,42.91764),(76.064535,42.93397),(76.09058,42.93428),(76.163754,42.921154),(76.254498,42.921154),(76.340487,42.901672),(76.351132,42.902886),(76.370976,42.909604),(76.382965,42.910069),(76.3933,42.905263),(76.404463,42.889244),(76.414074,42.885497),(76.432058,42.88958),(76.461927,42.910999),(76.48053,42.916968),(76.506885,42.914488),(76.558768,42.89821),(76.58502,42.894799),(76.605897,42.898494),(76.644345,42.911129),(76.688786,42.910328),(76.707907,42.913661),(76.74625,42.928879),(76.750385,42.932574),(76.751625,42.937096),(76.753899,42.940765),(76.76134,42.942057),(76.77953,42.939292),(76.785214,42.939654),(76.792966,42.943065),(76.814153,42.961487),(76.83348,42.971745),(76.853427,42.974122),(76.897662,42.974536),(76.93735,42.986034),(76.956884,42.988514),(76.976417,42.98221),(77.089899,42.968154),(77.124005,42.958904),(77.135064,42.951746),(77.163693,42.921981),(77.178679,42.913196),(77.195112,42.910069),(77.21189,42.909944),(77.229632,42.909811),(77.328127,42.897564),(77.36089,42.90454),(77.403265,42.919759),(77.418561,42.922239),(77.43396,42.921412),(77.461762,42.914384),(77.501553,42.914539),(77.520984,42.906917),(77.53845,42.896272),(77.557777,42.888133),(77.574417,42.887848),(77.62692,42.906555),(77.647797,42.909501),(77.71384,42.907589),(77.781226,42.895626),(77.787531,42.889709),(77.791665,42.883043),(77.798176,42.877513),(77.809958,42.871286),(77.83559,42.879839),(77.852229,42.887952),(77.861221,42.89082),(77.883855,42.893223),(77.907006,42.891285),(77.929331,42.885006),(77.986175,42.860202),(78.030616,42.854672),(78.137897,42.861984),(78.183579,42.86015),(78.229777,42.865007),(78.249104,42.862398),(78.290136,42.851442),(78.31122,42.850512),(78.328376,42.855292),(78.364653,42.872526),(78.38553,42.878237),(78.429559,42.880665),(78.496118,42.875601),(78.594303,42.850228),(78.635437,42.832477),(78.669957,42.811161),(78.687114,42.804598),(78.807933,42.79558),(78.888135,42.771215),(78.954281,42.768424),(78.992935,42.757133),(79.030866,42.756151),(79.108794,42.785348),(79.148274,42.790981),(79.173389,42.785632),(79.180831,42.77553),(79.175146,42.737031),(79.176076,42.713931),(79.181864,42.693597),(79.192199,42.674838),(79.206359,42.656467),(79.242119,42.629776),(79.321287,42.602181),(79.353016,42.577299),(79.398388,42.496942),(79.425673,42.469605),(79.47642,42.453973),(79.571918,42.449529),(79.652533,42.461053),(79.696458,42.459838),(79.917943,42.42444),(79.960111,42.403511),(79.97396,42.39147),(80.012098,42.349509),(80.077003,42.305765),(80.110076,42.273338),(80.136534,42.23887),(80.16661,42.208717),(80.210328,42.189519),(80.21653,42.174404),(80.219837,42.141873),(80.224591,42.125569),(80.235133,42.110945),(80.247432,42.098413),(80.256527,42.084357),(80.257561,42.065263),(80.231206,42.033689),(80.181906,42.020976),(79.930862,42.023276),(79.879496,42.013199),(79.842909,42.00183),(79.826786,41.992244),(79.812833,41.97762),(79.803842,41.959998),(79.792576,41.922817),(79.783274,41.905092),(79.747514,41.879745),(79.702969,41.874939),(79.655737,41.875843),(79.610985,41.867626),(79.554658,41.837602),(79.489856,41.819257),(79.410997,41.778588),(79.390844,41.772697),(79.367382,41.772387),(79.30413,41.787554),(79.282323,41.783497),(79.264856,41.774506),(79.217521,41.741226),(79.19592,41.729521),(79.174526,41.722622),(79.127914,41.714302),(79.088743,41.702546),(78.976192,41.6418),(78.915834,41.63317),(78.897437,41.626272),(78.807313,41.578445),(78.672128,41.538448),(78.658278,41.532453),(78.645049,41.52372),(78.637401,41.512868),(78.629133,41.48796),(78.619211,41.478089),(78.583968,41.465997),(78.51038,41.454422),(78.41757,41.400471),(78.377675,41.386622),(78.359899,41.377527),(78.343466,41.362024),(78.339332,41.344041),(78.356901,41.305542),(78.359692,41.287455),(78.34946,41.270402),(78.331477,41.258723),(78.291582,41.240791),(78.275356,41.228854),(78.250345,41.200535),(78.231335,41.172856),(78.204456,41.133718),(78.190503,41.11775),(78.176034,41.105502),(78.074955,41.039512),(78.057178,41.034344),(78.036508,41.036101),(77.997647,41.049795),(77.866699,41.064058),(77.831042,41.062973),(77.797556,41.054704),(77.665574,41.001271),(77.650278,40.997137),(77.631778,40.995793),(77.580721,40.997705),(77.503517,40.981066),(77.47488799999999,40.982047),(77.445226,40.993675),(77.388795,41.011658),(77.332985,41.02065),(77.301152,41.019306),(77.243171,41.005664),(77.118838,41.011658),(77.088555,41.019565),(77.035018,41.040338),(77.007733,41.044214),(76.900143,41.025766),(76.860972,41.013208),(76.834927,40.99352),(76.820871,40.97781),(76.783974,40.957139),(76.766818,40.944685),(76.757413,40.925772),(76.760927,40.9066),(76.768368,40.887014),(76.770848,40.867119),(76.762477,40.847017),(76.746871,40.83446),(76.707286,40.817613),(76.674214,40.795444),(76.647859,40.764851),(76.630805,40.728885),(76.624191,40.627547),(76.62078,40.611321),(76.609411,40.59711),(76.556391,40.565690000000004),(76.531173,40.534995),(76.498927,40.464611),(76.476499,40.436138),(76.449111,40.415519),(76.361984,40.371904),(76.330152,40.348081),(76.313512,40.343327),(76.299353,40.355677),(76.283333,40.417276),(76.273411,40.434122),(76.244162,40.441202),(76.21543,40.416552),(76.185044,40.384203),(76.151351,40.368131),(76.132541,40.371542),(76.095231,40.387355),(76.07611,40.391954),(76.051616,40.390197),(75.962422,40.357331),(75.949297,40.343068),(75.938031,40.326222),(75.921495,40.309117),(75.901858,40.298885),(75.880464,40.295268),(75.858553,40.296353),(75.79375,40.30891),(75.772046,40.31015),(75.750549,40.308342),(75.704454,40.293149),(75.681819,40.291702),(75.664869,40.305706),(75.656291,40.32307),(75.640168,40.367305),(75.638308,40.386115),(75.64636899999999,40.405338),(75.659598,40.419084),(75.669314,40.432365),(75.666936,40.450245),(75.657221,40.461097),(75.629006,40.481303),(75.617947,40.493964),(75.610816,40.512877),(75.605648,40.569411),(75.587665,40.611941),(75.559863,40.63287),(75.523793,40.63318),(75.481832,40.614111),(75.26324,40.480166),(75.253318,40.47598),(75.241536,40.474068),(75.229237,40.470347),(75.223966,40.462441),(75.220142,40.452984),(75.212494,40.444716),(75.19389,40.441254),(75.175287,40.448127),(75.15658,40.458152),(75.13808,40.463888),(75.113172,40.460787),(75.064389,40.443837),(75.039068,40.441099),(75.002378,40.4473),(74.966101,40.459289),(74.879181,40.505074),(74.856443,40.513187),(74.835359,40.511637),(74.832312,40.508116),(74.820063,40.493964),(74.816032,40.48368),(74.815102,40.480114),(74.807041,40.461769),(74.794638,40.440737),(74.787404,40.420738),(74.794638,40.405545),(74.841664,40.372059),(74.853859,40.35883),(74.862128,40.32617),(74.830915,40.319917),(74.746683,40.336505)],[(70.63298,39.79845),(70.661609,39.809819),(70.694527,39.814832),(70.70481,39.822067),(70.706412,39.839998),(70.698919,39.858447),(70.68662,39.860876),(70.654994,39.849765),(70.619906,39.850695),(70.498725,39.881908),(70.483739,39.882218),(70.482602,39.866767),(70.490147,39.850179),(70.503479,39.835502),(70.537379,39.817312),(70.547301,39.807649),(70.575878,39.77008),(70.581614,39.766566),(70.63298,39.79845)],[(71.007634,39.911157),(71.009288,39.885732),(71.021897,39.880823),(71.036056,39.887541),(71.049802,39.897979),(71.060964,39.904129),(71.079981,39.903405),(71.084787,39.894827),(71.087216,39.88382),(71.098895,39.8755),(71.113674,39.874466),(71.16101,39.884233),(71.1946,39.884802),(71.208449,39.888781),(71.219094,39.900925),(71.221058,39.931724),(71.17703,39.968156),(71.174704,39.993994),(71.190982,40.006241),(71.237284,40.031098),(71.244002,40.046756),(71.236354,40.056057),(71.223745,40.057866),(71.198217,40.052595),(71.192946,40.05027),(71.181887,40.043397),(71.176926,40.042001),(71.169382,40.042828),(71.165454,40.044637),(71.162043,40.046911),(71.105975,40.064946),(71.078844,40.07864),(71.06174,40.095176),(71.047942,40.122513),(71.031199,40.146905),(71.008564,40.157757),(70.977145,40.144579),(70.959885,40.113418),(70.954046,40.095797),(70.952961,40.079208),(70.958438,40.063085),(70.98314,40.021383),(70.994509,40.008877),(71.007634,40.003503),(71.034299,39.99911),(71.045823,39.99203),(71.050371,39.962885),(71.007634,39.911157)],[(71.757304,39.903095),(71.767123,39.915446),(71.789757,39.979318),(71.78552,39.989705),(71.760612,39.98371),(71.724128,39.962678),(71.706868,39.956115),(71.681753,39.955082),(71.665527,39.940199),(71.675346,39.925781),(71.696843,39.913844),(71.71617,39.906764),(71.741801,39.90077),(71.757304,39.903095)]]] +Aruba Aruba [[[(-69.936391,12.531724),(-69.924672,12.519232),(-69.915761,12.497016),(-69.88019800000001,12.453559),(-69.87682,12.427395),(-69.888092,12.41767),(-69.908803,12.417792),(-69.930531,12.425971),(-69.945139,12.440375),(-69.924672,12.440375),(-69.924672,12.447211),(-69.958567,12.463202),(-70.027659,12.522935),(-70.048085,12.531155),(-70.058095,12.537177),(-70.062408,12.54682),(-70.060374,12.556952),(-70.051096,12.574042),(-70.048736,12.583726),(-70.052642,12.600002),(-70.059641,12.614244),(-70.061106,12.625393),(-70.048736,12.632148),(-70.007151,12.585517),(-69.996938,12.577582),(-69.936391,12.531724)]]] +Aruba Afghanistan [] +Aruba Albania [] +Aruba Andorra [] +Aruba Ashmore and Cartier Islands [] +Aruba Austria [] +Aruba Burundi [] +Aruba Belgium [] +Aruba Benin [] +Aruba Burkina Faso [] +Aruba Bulgaria [] +Aruba Bahrain [] +Aruba Bosnia and Herzegovina [] +Aruba Bajo Nuevo Bank (Petrel Is.) [] +Aruba Saint Barthelemy [] +Aruba Belarus [] +Aruba Bolivia [] +Aruba Barbados [] +Aruba Bhutan [] +Aruba Botswana [] +Aruba Central African Republic [] +Aruba Switzerland [] +Aruba Clipperton Island [] +Aruba Cameroon [] +Aruba Republic of Congo [] +Aruba Coral Sea Islands [] +Aruba Curaçao [] +Aruba Czech Republic [] +Aruba Djibouti [] +Aruba Dominica [] +Aruba Algeria [] +Aruba Ethiopia [] +Aruba Georgia [] +Aruba Ghana [] +Aruba Gibraltar [] +Aruba Guinea [] +Aruba Gambia [] +Aruba Guatemala [] +Aruba Guam [] +Aruba Heard Island and McDonald Islands [] +Aruba Hungary [] +Aruba Isle of Man [] +Aruba Iraq [] +Aruba Israel [] +Aruba Jamaica [] +Aruba Jersey [] +Aruba Jordan [] +Aruba Baykonur Cosmodrome [] +Aruba Siachen Glacier [] +Aruba Kosovo [] +Aruba Laos [] +Aruba Lebanon [] +Aruba Liberia [] +Aruba Libya [] +Aruba Saint Lucia [] +Aruba Liechtenstein [] +Aruba Lesotho [] +Aruba Luxembourg [] +Aruba Latvia [] +Aruba Saint Martin [] +Aruba Morocco [] +Aruba Monaco [] +Aruba Moldova [] +Aruba Macedonia [] +Aruba Mali [] +Aruba Montenegro [] +Aruba Mongolia [] +Aruba Montserrat [] +Aruba Namibia [] +Aruba Niger [] +Aruba Norfolk Island [] +Aruba Niue [] +Aruba Nepal [] +Aruba Nauru [] +Aruba Poland [] +Aruba Paraguay [] +Aruba Qatar [] +Aruba Romania [] +Aruba Rwanda [] +Aruba Western Sahara [] +Aruba Scarborough Reef [] +Aruba South Sudan [] +Aruba Senegal [] +Aruba Serranilla Bank [] +Aruba Singapore [] +Aruba San Marino [] +Aruba Somaliland [] +Aruba Somalia [] +Aruba Republic of Serbia [] +Aruba Suriname [] +Aruba Slovakia [] +Aruba Slovenia [] +Aruba Swaziland [] +Aruba Sint Maarten [] +Aruba Syria [] +Aruba Chad [] +Aruba Togo [] +Aruba Uganda [] +Aruba Uruguay [] +Aruba Vatican [] diff --git a/tests/queries/0_stateless/01720_country_intersection.sh b/tests/queries/0_stateless/01720_country_intersection.sh new file mode 100755 index 00000000000..d7e0e67d351 --- /dev/null +++ b/tests/queries/0_stateless/01720_country_intersection.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +${CLICKHOUSE_CLIENT} -q "drop table if exists country_polygons;" +${CLICKHOUSE_CLIENT} -q "create table country_polygons(name String, p Array(Array(Tuple(Float64, Float64)))) engine=MergeTree() order by tuple();" +cat ${CURDIR}/country_polygons.tsv | ${CLICKHOUSE_CLIENT} -q "insert into country_polygons format TSV" +${CLICKHOUSE_CLIENT} -q "SELECT c, d, polygonsIntersectionSpherical(a, b) FROM (SELECT first.p AS a, second.p AS b, first.name AS c, second.name AS d FROM country_polygons AS first CROSS JOIN country_polygons AS second LIMIT 100) format TSV" +${CLICKHOUSE_CLIENT} -q "drop table if exists country_polygons;" + + +${CLICKHOUSE_CLIENT} -q "drop table if exists country_rings;" +${CLICKHOUSE_CLIENT} -q "create table country_rings(name String, p Array(Tuple(Float64, Float64))) engine=MergeTree() order by tuple();" +cat ${CURDIR}/country_rings.tsv | ${CLICKHOUSE_CLIENT} -q "insert into country_rings format TSV" +${CLICKHOUSE_CLIENT} -q "SELECT c, d, polygonsIntersectionSpherical(a, b) FROM (SELECT first.p AS a, second.p AS b, first.name AS c, second.name AS d FROM country_rings AS first CROSS JOIN country_rings AS second LIMIT 100) format TSV" +${CLICKHOUSE_CLIENT} -q "drop table if exists country_rings;" \ No newline at end of file diff --git a/tests/queries/0_stateless/01720_country_perimeter_and_area.reference b/tests/queries/0_stateless/01720_country_perimeter_and_area.reference new file mode 100644 index 00000000000..8a9690791c6 --- /dev/null +++ b/tests/queries/0_stateless/01720_country_perimeter_and_area.reference @@ -0,0 +1,214 @@ +Dhekelia Sovereign Base Area 0.0186259930051051 +Kyrgyzstan 0.5868323961091907 +------------------------------------- +Dhekelia Sovereign Base Area 0.000003139488070896512 +Kyrgyzstan 0.004895645023822883 +------------------------------------- +Aruba 0.011249330810410983 +Afghanistan 0.8199216326776404 +Albania 0.17108622597702605 +Andorra 0.015145740647213184 +Ashmore and Cartier Islands 0.001111472909012953 +Austria 0.3258464621357028 +Burundi 0.1409500621452211 +Belgium 0.1794463601873955 +Benin 0.31426073515874664 +Burkina Faso 0.5144381682226761 +Bulgaria 0.3083164214454252 +Bahrain 0.02137170357214413 +Bosnia and Herzegovina 0.20611959113245232 +Bajo Nuevo Bank (Petrel Is.) 0.0001254597070361587 +Saint Barthelemy 0.0032990108720812672 +Belarus 0.42899119772830474 +Bolivia 0.9279328001326348 +Barbados 0.014116142490651021 +Bhutan 0.1601735058766338 +Botswana 0.5896697538755427 +Central African Republic 0.7760222837198817 +Switzerland 0.2318851512510408 +Clipperton Island 0.0014072924221565273 +Cameroon 0.8001045813665599 +Republic of Congo 0.6904316055863188 +Coral Sea Islands 0.00011634674137689659 +Curaçao 0.02078862020307983 +Czech Republic 0.2708588915805718 +Djibouti 0.12937731543684822 +Dominica 0.020094439807419574 +Algeria 1.1549683948032776 +Ethiopia 0.8210654364815099 +Georgia 0.26823008017781313 +Ghana 0.4056578143818251 +Gibraltar 0.0014059440610631154 +Guinea 0.6350853755877334 +Gambia 0.19279774895359095 +Guatemala 0.3030953561509038 +Guam 0.020321390076536976 +Heard Island and McDonald Islands 0.017334896920453105 +Hungary 0.2617732480910806 +Isle of Man 0.01875803631141408 +Iraq 0.5469861219502402 +Israel 0.19353851895699914 +Jamaica 0.10055860979159512 +Jersey 0.008427337812134537 +Jordan 0.2642243503964102 +Baykonur Cosmodrome 0.04482995477542441 +Siachen Glacier 0.03872116827341272 +Kosovo 0.08773172991408161 +Laos 0.6899867972760174 +Lebanon 0.09676977254650951 +Liberia 0.2961649538030388 +Libya 0.9538430912224716 +Saint Lucia 0.016786201647759867 +Liechtenstein 0.009288582116863231 +Lesotho 0.12315874900320756 +Luxembourg 0.04125996057810259 +Latvia 0.24488610945731157 +Saint Martin 0.006547834154217771 +Morocco 0.8817924249630141 +Monaco 0.0026049777439637527 +Moldova 0.20765701819586885 +Macedonia 0.1128831074330059 +Mali 1.1385970015559317 +Montenegro 0.11756794062084858 +Mongolia 1.142306166871007 +Montserrat 0.006620100691409788 +Namibia 0.843464957679987 +Niger 0.8780744302377772 +Norfolk Island 0.004912027225339993 +Niue 0.009881892958363517 +Nepal 0.4076113675280835 +Nauru 0.0031205159769295255 +Poland 0.48922069488271314 +Paraguay 0.5475256537493991 +Qatar 0.09362771431858698 +Romania 0.44095021664473105 +Rwanda 0.1293663890297039 +Western Sahara 0.4691920993279596 +Scarborough Reef 0.00019842225207367386 +South Sudan 0.7584190842556537 +Senegal 0.5883247226863264 +Serranilla Bank 0.0002389083935906293 +Singapore 0.015233384733369614 +San Marino 0.004596873449598911 +Somaliland 0.3096791489207226 +Somalia 0.6879915318072617 +Republic of Serbia 0.29677234233404165 +Suriname 0.32255243342976203 +Slovakia 0.19843599488831584 +Slovenia 0.14713148471782736 +Swaziland 0.08434161089555517 +Sint Maarten 0.0037955305365309296 +Syria 0.35675522352394456 +Chad 0.9102578296637189 +Togo 0.2600585482954555 +Uganda 0.38301730108810556 +Uruguay 0.3083564407046887 +Vatican 0.00006702452496391445 +Akrotiri Sovereign Base Area 0.013376747415600219 +Zambia 0.8807923488623808 +Zimbabwe 0.4553903789902945 +------------------------------------- +Aruba 0.0000041986375296795025 +Afghanistan 0.015826481758320493 +Albania 0.0006971811189621746 +Andorra 0.00001112355564980348 +Ashmore and Cartier Islands 6.66668338977609e-8 +Austria 0.0020634744883290235 +Burundi 0.000669169243101558 +Belgium 0.0007529367590741593 +Benin 0.00287239734953164 +Burkina Faso 0.006746218025419332 +Bulgaria 0.0027733372191197786 +Bahrain 0.00001443842547561405 +Bosnia and Herzegovina 0.0012742491201009779 +Bajo Nuevo Bank (Petrel Is.) 8.864825701897049e-10 +Saint Barthelemy 6.036607210116289e-7 +Belarus 0.005090738074359067 +Bolivia 0.026865324735758436 +Barbados 0.0000109856680212211 +Bhutan 0.0009961026696220909 +Botswana 0.01430200501713062 +Central African Republic 0.015290667187215962 +Switzerland 0.0010181463734151514 +Clipperton Island 1.2373029819547803e-7 +Cameroon 0.011488908713113137 +Republic of Congo 0.008534881807187833 +Coral Sea Islands 5.121674593493771e-10 +Curaçao 0.000011457378136273848 +Czech Republic 0.0019339153549488386 +Djibouti 0.000540370985929321 +Dominica 0.000018056168258583246 +Algeria 0.05696762706232162 +Ethiopia 0.02789047634482515 +Georgia 0.0017113229913929072 +Ghana 0.0059048504621945965 +Gibraltar 9.095456688875715e-8 +Guinea 0.006043151808047173 +Gambia 0.0002596816395280707 +Guatemala 0.0026901925526205263 +Guam 0.000013952443476670549 +Heard Island and McDonald Islands 0.000009688375334192321 +Hungary 0.0022899094702118978 +Isle of Man 0.00001410012284549863 +Iraq 0.010780689598789812 +Israel 0.0005400181032289429 +Jamaica 0.00027268062650994383 +Jersey 0.0000029236161155167853 +Jordan 0.002191215069390572 +Baykonur Cosmodrome 0.00015978303781425133 +Siachen Glacier 0.0000513879615262916 +Kosovo 0.0002684178325412152 +Laos 0.005637555524983489 +Lebanon 0.0002464436461544738 +Liberia 0.002357973807538481 +Libya 0.040072512808839354 +Saint Lucia 0.000014963842166249258 +Liechtenstein 0.0000033722024322722466 +Lesotho 0.0007426290112070925 +Luxembourg 0.00006405006804909529 +Latvia 0.00158313668683266 +Saint Martin 0.00000168759530251474 +Morocco 0.014595589778269167 +Monaco 4.6325700981005285e-7 +Moldova 0.0008158639460823913 +Macedonia 0.0006245180554490506 +Mali 0.03096381132470007 +Montenegro 0.00033762445623993013 +Mongolia 0.038446609480001344 +Montserrat 0.0000024620326175206004 +Namibia 0.020320978539029165 +Niger 0.02919849042641136 +Norfolk Island 0.0000010150641235563077 +Niue 0.000005450796200539049 +Nepal 0.003629565673884544 +Nauru 7.119067469952887e-7 +Poland 0.0076921097527402876 +Paraguay 0.009875843128670564 +Qatar 0.0002752610716836153 +Romania 0.005809479702080411 +Rwanda 0.0006262235765421803 +Western Sahara 0.0022344529652030694 +Scarborough Reef 2.4176335726807567e-9 +South Sudan 0.015509656314462458 +Senegal 0.00485201810074574 +Serranilla Bank 2.6035559945372385e-9 +Singapore 0.000012633505579848072 +San Marino 0.0000014830814619737624 +Somaliland 0.0041412916217828406 +Somalia 0.011674654119996183 +Republic of Serbia 0.001907268740192651 +Suriname 0.0035911641359236534 +Slovakia 0.0011901587428922095 +Slovenia 0.0004995546076509384 +Swaziland 0.00042234053226485263 +Sint Maarten 5.772865969377286e-7 +Syria 0.004581243750467663 +Chad 0.0313064894302088 +Togo 0.0014067991034602252 +Uganda 0.005985159048654327 +Uruguay 0.0043716082436750115 +Vatican 3.002600504657064e-10 +Akrotiri Sovereign Base Area 0.0000024314362587592923 +Zambia 0.018594119224502336 +Zimbabwe 0.009621356779606268 +------------------------------------- diff --git a/tests/queries/0_stateless/01720_country_perimeter_and_area.sh b/tests/queries/0_stateless/01720_country_perimeter_and_area.sh new file mode 100755 index 00000000000..76dc403fb2f --- /dev/null +++ b/tests/queries/0_stateless/01720_country_perimeter_and_area.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +${CLICKHOUSE_CLIENT} -q "drop table if exists country_polygons;" +${CLICKHOUSE_CLIENT} -q "create table country_polygons(name String, p Array(Array(Tuple(Float64, Float64)))) engine=MergeTree() order by tuple();" +cat ${CURDIR}/country_polygons.tsv | ${CLICKHOUSE_CLIENT} -q "insert into country_polygons format TSV" + +${CLICKHOUSE_CLIENT} -q "SELECT name, polygonPerimeterSpherical(p) from country_polygons" +${CLICKHOUSE_CLIENT} -q "SELECT '-------------------------------------'" +${CLICKHOUSE_CLIENT} -q "SELECT name, polygonAreaSpherical(p) from country_polygons" +${CLICKHOUSE_CLIENT} -q "SELECT '-------------------------------------'" +${CLICKHOUSE_CLIENT} -q "drop table if exists country_rings;" + + +${CLICKHOUSE_CLIENT} -q "create table country_rings(name String, p Array(Tuple(Float64, Float64))) engine=MergeTree() order by tuple();" +cat ${CURDIR}/country_rings.tsv | ${CLICKHOUSE_CLIENT} -q "insert into country_rings format TSV" + +${CLICKHOUSE_CLIENT} -q "SELECT name, polygonPerimeterSpherical(p) from country_rings" +${CLICKHOUSE_CLIENT} -q "SELECT '-------------------------------------'" +${CLICKHOUSE_CLIENT} -q "SELECT name, polygonAreaSpherical(p) from country_rings" +${CLICKHOUSE_CLIENT} -q "SELECT '-------------------------------------'" +${CLICKHOUSE_CLIENT} -q "drop table if exists country_rings;" \ No newline at end of file diff --git a/tests/queries/0_stateless/01720_dictionary_create_source_with_functions.reference b/tests/queries/0_stateless/01720_dictionary_create_source_with_functions.reference new file mode 100644 index 00000000000..38abe3c9f52 --- /dev/null +++ b/tests/queries/0_stateless/01720_dictionary_create_source_with_functions.reference @@ -0,0 +1 @@ +1 First diff --git a/tests/queries/0_stateless/01720_dictionary_create_source_with_functions.sql b/tests/queries/0_stateless/01720_dictionary_create_source_with_functions.sql new file mode 100644 index 00000000000..a0a4fbbfab9 --- /dev/null +++ b/tests/queries/0_stateless/01720_dictionary_create_source_with_functions.sql @@ -0,0 +1,28 @@ +DROP DATABASE IF EXISTS 01720_dictionary_db; +CREATE DATABASE 01720_dictionary_db; + +CREATE TABLE 01720_dictionary_db.dictionary_source_table +( + key UInt8, + value String +) +ENGINE = TinyLog; + +INSERT INTO 01720_dictionary_db.dictionary_source_table VALUES (1, 'First'); + +CREATE DICTIONARY 01720_dictionary_db.dictionary +( + key UInt64, + value String +) +PRIMARY KEY key +SOURCE(CLICKHOUSE(DB '01720_dictionary_db' TABLE 'dictionary_source_table' HOST hostName() PORT tcpPort())) +LIFETIME(0) +LAYOUT(FLAT()); + +SELECT * FROM 01720_dictionary_db.dictionary; + +DROP DICTIONARY 01720_dictionary_db.dictionary; +DROP TABLE 01720_dictionary_db.dictionary_source_table; + +DROP DATABASE 01720_dictionary_db; diff --git a/tests/queries/0_stateless/01720_engine_file_empty_if_not_exists.reference b/tests/queries/0_stateless/01720_engine_file_empty_if_not_exists.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01720_engine_file_empty_if_not_exists.sql b/tests/queries/0_stateless/01720_engine_file_empty_if_not_exists.sql new file mode 100644 index 00000000000..d665dbc722f --- /dev/null +++ b/tests/queries/0_stateless/01720_engine_file_empty_if_not_exists.sql @@ -0,0 +1,16 @@ +DROP TABLE IF EXISTS file_engine_table; + +CREATE TABLE file_engine_table (id UInt32) ENGINE=File(TSV); + +SELECT * FROM file_engine_table; --{ serverError 107 } + +SET engine_file_empty_if_not_exists=0; + +SELECT * FROM file_engine_table; --{ serverError 107 } + +SET engine_file_empty_if_not_exists=1; + +SELECT * FROM file_engine_table; + +SET engine_file_empty_if_not_exists=0; +DROP TABLE file_engine_table; diff --git a/tests/queries/0_stateless/01720_join_implicit_cast.reference b/tests/queries/0_stateless/01720_join_implicit_cast.reference new file mode 100644 index 00000000000..3cca6a264fa --- /dev/null +++ b/tests/queries/0_stateless/01720_join_implicit_cast.reference @@ -0,0 +1,102 @@ +=== hash === += full = +1 1 +2 2 +-1 1 +1 \N +1 257 +1 -1 += left = +1 1 +2 2 += right = +1 1 +-1 1 +1 \N +1 257 +1 -1 += inner = +1 1 += full = +1 1 1 1 +2 2 0 \N +0 0 -1 1 +0 0 1 \N +0 0 1 257 +0 0 1 -1 += left = +1 1 1 1 +2 2 0 \N += right = +1 1 1 1 +0 0 -1 1 +0 0 1 \N +0 0 1 257 +0 0 1 -1 += inner = +1 1 1 1 += agg = +5 260 +3 3 +3 258 +1 1 +5 260 +3 3 +3 258 +1 1 += types = +1 +1 +1 +1 +=== partial_merge === += full = +1 1 +2 2 +-1 1 +1 \N +1 257 +1 -1 += left = +1 1 +2 2 += right = +1 1 +-1 1 +1 \N +1 257 +1 -1 += inner = +1 1 += full = +1 1 1 1 +2 2 0 \N +0 0 -1 1 +0 0 1 \N +0 0 1 257 +0 0 1 -1 += left = +1 1 1 1 +2 2 0 \N += right = +1 1 1 1 +0 0 -1 1 +0 0 1 \N +0 0 1 257 +0 0 1 -1 += inner = +1 1 1 1 += agg = +5 260 +3 3 +3 258 +1 1 +5 260 +3 3 +3 258 +1 1 += types = +1 +1 +1 +1 diff --git a/tests/queries/0_stateless/01720_join_implicit_cast.sql b/tests/queries/0_stateless/01720_join_implicit_cast.sql new file mode 100644 index 00000000000..cf4a3bdcef6 --- /dev/null +++ b/tests/queries/0_stateless/01720_join_implicit_cast.sql @@ -0,0 +1,96 @@ +DROP TABLE IF EXISTS t_ab1; +DROP TABLE IF EXISTS t_ab2; + +CREATE TABLE t_ab1 (id Nullable(Int32), a UInt16, b UInt8) ENGINE = TinyLog; +CREATE TABLE t_ab2 (id Nullable(Int32), a Int16, b Nullable(Int64)) ENGINE = TinyLog; +INSERT INTO t_ab1 VALUES (0, 1, 1), (1, 2, 2); +INSERT INTO t_ab2 VALUES (2, -1, 1), (3, 1, NULL), (4, 1, 257), (5, 1, -1), (6, 1, 1); + +SELECT '=== hash ==='; + +SET join_algorithm = 'hash'; + +SELECT '= full ='; +SELECT a, b FROM t_ab1 FULL JOIN t_ab2 USING (a, b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= left ='; +SELECT a, b FROM t_ab1 LEFT JOIN t_ab2 USING (a, b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= right ='; +SELECT a, b FROM t_ab1 RIGHT JOIN t_ab2 USING (a, b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= inner ='; +SELECT a, b FROM t_ab1 INNER JOIN t_ab2 USING (a, b) ORDER BY ifNull(t_ab1.id, t_ab2.id); + +SELECT '= full ='; +SELECT a, b, t_ab2.a, t_ab2.b FROM t_ab1 FULL JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= left ='; +SELECT a, b, t_ab2.a, t_ab2.b FROM t_ab1 LEFT JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= right ='; +SELECT a, b, t_ab2.a, t_ab2.b FROM t_ab1 RIGHT JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= inner ='; +SELECT a, b, t_ab2.a, t_ab2.b FROM t_ab1 INNER JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b) ORDER BY ifNull(t_ab1.id, t_ab2.id); + +SELECT '= agg ='; +SELECT sum(a), sum(b) FROM t_ab1 FULL JOIN t_ab2 USING (a, b); +SELECT sum(a), sum(b) FROM t_ab1 LEFT JOIN t_ab2 USING (a, b); +SELECT sum(a), sum(b) FROM t_ab1 RIGHT JOIN t_ab2 USING (a, b); +SELECT sum(a), sum(b) FROM t_ab1 INNER JOIN t_ab2 USING (a, b); + +SELECT sum(a) + sum(t_ab2.a) - 1, sum(b) + sum(t_ab2.b) - 1 FROM t_ab1 FULL JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b); +SELECT sum(a) + sum(t_ab2.a) - 1, sum(b) + sum(t_ab2.b) - 1 FROM t_ab1 LEFT JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b); +SELECT sum(a) + sum(t_ab2.a) - 1, sum(b) + sum(t_ab2.b) - 1 FROM t_ab1 RIGHT JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b); +SELECT sum(a) + sum(t_ab2.a) - 1, sum(b) + sum(t_ab2.b) - 1 FROM t_ab1 INNER JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b); + +SELECT '= types ='; + +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(b)) == 'Nullable(Int64)' FROM t_ab1 FULL JOIN t_ab2 USING (a, b); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(b)) == 'Nullable(Int64)' FROM t_ab1 LEFT JOIN t_ab2 USING (a, b); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(b)) == 'Nullable(Int64)' FROM t_ab1 RIGHT JOIN t_ab2 USING (a, b); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(b)) == 'Nullable(Int64)' FROM t_ab1 INNER JOIN t_ab2 USING (a, b); + +SELECT * FROM ( SELECT a, b as "CAST(a, Int32)" FROM t_ab1 ) t_ab1 FULL JOIN t_ab2 ON (t_ab1.a == t_ab2.a); -- { serverError 44 } +SELECT * FROM ( SELECT a, b as "CAST(a, Int32)" FROM t_ab1 ) t_ab1 FULL JOIN t_ab2 USING (a) FORMAT Null; + +SELECT '=== partial_merge ==='; + +SET join_algorithm = 'partial_merge'; + +SELECT '= full ='; +SELECT a, b FROM t_ab1 FULL JOIN t_ab2 USING (a, b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= left ='; +SELECT a, b FROM t_ab1 LEFT JOIN t_ab2 USING (a, b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= right ='; +SELECT a, b FROM t_ab1 RIGHT JOIN t_ab2 USING (a, b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= inner ='; +SELECT a, b FROM t_ab1 INNER JOIN t_ab2 USING (a, b) ORDER BY ifNull(t_ab1.id, t_ab2.id); + +SELECT '= full ='; +SELECT a, b, t_ab2.a, t_ab2.b FROM t_ab1 FULL JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= left ='; +SELECT a, b, t_ab2.a, t_ab2.b FROM t_ab1 LEFT JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= right ='; +SELECT a, b, t_ab2.a, t_ab2.b FROM t_ab1 RIGHT JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b) ORDER BY ifNull(t_ab1.id, t_ab2.id); +SELECT '= inner ='; +SELECT a, b, t_ab2.a, t_ab2.b FROM t_ab1 INNER JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b) ORDER BY ifNull(t_ab1.id, t_ab2.id); + +SELECT '= agg ='; +SELECT sum(a), sum(b) FROM t_ab1 FULL JOIN t_ab2 USING (a, b); +SELECT sum(a), sum(b) FROM t_ab1 LEFT JOIN t_ab2 USING (a, b); +SELECT sum(a), sum(b) FROM t_ab1 RIGHT JOIN t_ab2 USING (a, b); +SELECT sum(a), sum(b) FROM t_ab1 INNER JOIN t_ab2 USING (a, b); + +SELECT sum(a) + sum(t_ab2.a) - 1, sum(b) + sum(t_ab2.b) - 1 FROM t_ab1 FULL JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b); +SELECT sum(a) + sum(t_ab2.a) - 1, sum(b) + sum(t_ab2.b) - 1 FROM t_ab1 LEFT JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b); +SELECT sum(a) + sum(t_ab2.a) - 1, sum(b) + sum(t_ab2.b) - 1 FROM t_ab1 RIGHT JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b); +SELECT sum(a) + sum(t_ab2.a) - 1, sum(b) + sum(t_ab2.b) - 1 FROM t_ab1 INNER JOIN t_ab2 ON (t_ab1.a == t_ab2.a AND t_ab1.b == t_ab2.b); + +SELECT '= types ='; + +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(b)) == 'Nullable(Int64)' FROM t_ab1 FULL JOIN t_ab2 USING (a, b); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(b)) == 'Nullable(Int64)' FROM t_ab1 LEFT JOIN t_ab2 USING (a, b); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(b)) == 'Nullable(Int64)' FROM t_ab1 RIGHT JOIN t_ab2 USING (a, b); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(b)) == 'Nullable(Int64)' FROM t_ab1 INNER JOIN t_ab2 USING (a, b); + +SELECT * FROM ( SELECT a, b as "CAST(a, Int32)" FROM t_ab1 ) t_ab1 FULL JOIN t_ab2 ON (t_ab1.a == t_ab2.a); -- { serverError 44 } +SELECT * FROM ( SELECT a, b as "CAST(a, Int32)" FROM t_ab1 ) t_ab1 FULL JOIN t_ab2 USING (a) FORMAT Null; + +DROP TABLE IF EXISTS t_ab1; +DROP TABLE IF EXISTS t_ab2; diff --git a/tests/queries/0_stateless/01720_type_map_and_casts.reference b/tests/queries/0_stateless/01720_type_map_and_casts.reference new file mode 100644 index 00000000000..1ceb4d78f81 --- /dev/null +++ b/tests/queries/0_stateless/01720_type_map_and_casts.reference @@ -0,0 +1,40 @@ +Map(Int8, Int8) +{127:1,0:1,-1:1} +{} +1 0 1 1 +0 0 0 0 +0 +1 +1 +0 +0 +0 +0 +0 +0 +0 +1 +Map(Int32, UInt16) +{-1:1,2147483647:2,-2147483648:3} +1 2 3 +0 +1 +0 +0 +0 +Map(Date, Int32) +{'2020-01-01':1,'2020-01-02':2,'1970-01-02':3} +1 2 0 +0 +3 +0 +Map(UUID, UInt16) +{'00001192-0000-4000-8000-000000000001':1,'00001192-0000-4000-7000-000000000001':2} +0 2 1 +Map(Int128, Int32) +{-1:'a',0:'b',1234567898765432193024000:'c',-1234567898765432193024000:'d'} +a b c d + +a +b + diff --git a/tests/queries/0_stateless/01720_type_map_and_casts.sql b/tests/queries/0_stateless/01720_type_map_and_casts.sql new file mode 100644 index 00000000000..2f333373dba --- /dev/null +++ b/tests/queries/0_stateless/01720_type_map_and_casts.sql @@ -0,0 +1,79 @@ +SET allow_experimental_map_type = 1; + +DROP TABLE IF EXISTS table_map_with_key_integer; + +CREATE TABLE table_map_with_key_integer (d DATE, m Map(Int8, Int8)) +ENGINE = MergeTree() ORDER BY d; + +INSERT INTO table_map_with_key_integer VALUES ('2020-01-01', map(127, 1, 0, 1, -1, 1)) ('2020-01-01', map()); + +SELECT 'Map(Int8, Int8)'; + +SELECT m FROM table_map_with_key_integer; +SELECT m[127], m[1], m[0], m[-1] FROM table_map_with_key_integer; +SELECT m[toInt8(number - 2)] FROM table_map_with_key_integer ARRAY JOIN range(5) AS number; + +SELECT count() FROM table_map_with_key_integer WHERE m = map(); + +DROP TABLE IF EXISTS table_map_with_key_integer; + +CREATE TABLE table_map_with_key_integer (d DATE, m Map(Int32, UInt16)) +ENGINE = MergeTree() ORDER BY d; + +INSERT INTO table_map_with_key_integer VALUES ('2020-01-01', map(-1, 1, 2147483647, 2, -2147483648, 3)); + +SELECT 'Map(Int32, UInt16)'; + +SELECT m FROM table_map_with_key_integer; +SELECT m[-1], m[2147483647], m[-2147483648] FROM table_map_with_key_integer; +SELECT m[toInt32(number - 2)] FROM table_map_with_key_integer ARRAY JOIN range(5) AS number; + +DROP TABLE IF EXISTS table_map_with_key_integer; + +CREATE TABLE table_map_with_key_integer (d DATE, m Map(Date, Int32)) +ENGINE = MergeTree() ORDER BY d; + +INSERT INTO table_map_with_key_integer VALUES ('2020-01-01', map('2020-01-01', 1, '2020-01-02', 2, '1970-01-02', 3)); + +SELECT 'Map(Date, Int32)'; + +SELECT m FROM table_map_with_key_integer; +SELECT m[toDate('2020-01-01')], m[toDate('2020-01-02')], m[toDate('2020-01-03')] FROM table_map_with_key_integer; +SELECT m[toDate(number)] FROM table_map_with_key_integer ARRAY JOIN range(3) AS number; + +DROP TABLE IF EXISTS table_map_with_key_integer; + +CREATE TABLE table_map_with_key_integer (d DATE, m Map(UUID, UInt16)) +ENGINE = MergeTree() ORDER BY d; + +INSERT INTO table_map_with_key_integer VALUES ('2020-01-01', map('00001192-0000-4000-8000-000000000001', 1, '00001192-0000-4000-7000-000000000001', 2)); + +SELECT 'Map(UUID, UInt16)'; + +SELECT m FROM table_map_with_key_integer; +SELECT + m[toUUID('00001192-0000-4000-6000-000000000001')], + m[toUUID('00001192-0000-4000-7000-000000000001')], + m[toUUID('00001192-0000-4000-8000-000000000001')] +FROM table_map_with_key_integer; + +DROP TABLE IF EXISTS table_map_with_key_integer; + +CREATE TABLE table_map_with_key_integer (d DATE, m Map(Int128, String)) +ENGINE = MergeTree() ORDER BY d; + + +INSERT INTO table_map_with_key_integer SELECT '2020-01-01', map(-1, 'a', 0, 'b', toInt128(1234567898765432123456789), 'c', toInt128(-1234567898765432123456789), 'd'); + +SELECT 'Map(Int128, Int32)'; + +SELECT m FROM table_map_with_key_integer; +SELECT m[toInt128(-1)], m[toInt128(0)], m[toInt128(1234567898765432123456789)], m[toInt128(-1234567898765432123456789)] FROM table_map_with_key_integer; +SELECT m[toInt128(number - 2)] FROM table_map_with_key_integer ARRAY JOIN range(4) AS number; + +DROP TABLE IF EXISTS table_map_with_key_integer; + + +CREATE TABLE table_map_with_key_integer (m Map(Float32, String)) ENGINE = MergeTree() ORDER BY tuple(); -- { serverError 36} +CREATE TABLE table_map_with_key_integer (m Map(Nullable(String), String)) ENGINE = MergeTree() ORDER BY tuple(); -- { serverError 36} +CREATE TABLE table_map_with_key_integer (m Map(Array(UInt32), String)) ENGINE = MergeTree() ORDER BY tuple(); -- { serverError 36} diff --git a/tests/queries/0_stateless/01720_union_distinct_with_limit.reference b/tests/queries/0_stateless/01720_union_distinct_with_limit.reference new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/tests/queries/0_stateless/01720_union_distinct_with_limit.reference @@ -0,0 +1 @@ +1 diff --git a/tests/queries/0_stateless/01720_union_distinct_with_limit.sql b/tests/queries/0_stateless/01720_union_distinct_with_limit.sql new file mode 100644 index 00000000000..9fc5b3eafd2 --- /dev/null +++ b/tests/queries/0_stateless/01720_union_distinct_with_limit.sql @@ -0,0 +1,8 @@ +SELECT x +FROM +( + SELECT 1 AS x + UNION DISTINCT + SELECT 1 +) +LIMIT 1; diff --git a/tests/queries/0_stateless/01721_constraints_constant_expressions.reference b/tests/queries/0_stateless/01721_constraints_constant_expressions.reference new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/tests/queries/0_stateless/01721_constraints_constant_expressions.reference @@ -0,0 +1 @@ +1 diff --git a/tests/queries/0_stateless/01721_constraints_constant_expressions.sql b/tests/queries/0_stateless/01721_constraints_constant_expressions.sql new file mode 100644 index 00000000000..d70c0cd4dc0 --- /dev/null +++ b/tests/queries/0_stateless/01721_constraints_constant_expressions.sql @@ -0,0 +1,40 @@ +DROP TABLE IF EXISTS constraint_constant_number_expression; +CREATE TABLE constraint_constant_number_expression +( + id UInt64, + CONSTRAINT `c0` CHECK 1, + CONSTRAINT `c1` CHECK 1 < 2, + CONSTRAINT `c2` CHECK isNull(cast(NULL, 'Nullable(UInt8)')) +) ENGINE = TinyLog(); + +INSERT INTO constraint_constant_number_expression VALUES (1); + +SELECT * FROM constraint_constant_number_expression; + +DROP TABLE constraint_constant_number_expression; + +DROP TABLE IF EXISTS constraint_constant_number_expression_non_uint8; +CREATE TABLE constraint_constant_number_expression_non_uint8 +( + id UInt64, + CONSTRAINT `c0` CHECK toUInt64(1) +) ENGINE = TinyLog(); + +INSERT INTO constraint_constant_number_expression_non_uint8 VALUES (2); -- {serverError 1} + +SELECT * FROM constraint_constant_number_expression_non_uint8; + +DROP TABLE constraint_constant_number_expression_non_uint8; + +DROP TABLE IF EXISTS constraint_constant_nullable_expression_that_contains_null; +CREATE TABLE constraint_constant_nullable_expression_that_contains_null +( + id UInt64, + CONSTRAINT `c0` CHECK nullIf(1 % 2, 1) +) ENGINE = TinyLog(); + +INSERT INTO constraint_constant_nullable_expression_that_contains_null VALUES (3); -- {serverError 469} + +SELECT * FROM constraint_constant_nullable_expression_that_contains_null; + +DROP TABLE constraint_constant_nullable_expression_that_contains_null; diff --git a/tests/queries/0_stateless/01721_dictionary_decimal_p_s.reference b/tests/queries/0_stateless/01721_dictionary_decimal_p_s.reference new file mode 100644 index 00000000000..066b4bd1d97 --- /dev/null +++ b/tests/queries/0_stateless/01721_dictionary_decimal_p_s.reference @@ -0,0 +1,10 @@ +-------- 42 -------- +42 14.0000 14.00000000 14.00000000 14.0000000000000000618637523926765281280 +42 14.0000 14.00000000 14.00000000 +14.0000 14.00000000 14.00000000 +-------- 4999 -------- +4999 1666.3333 1666.33333333 1666.33333333 1633.3553612205046244471093725648757194800 +4999 1666.3333 1666.33333333 1666.33333333 +1666.3333 1666.33333333 1666.33333333 +-------- 5000 -------- +0.1100 0.11000000 0.11000000 diff --git a/tests/queries/0_stateless/01721_dictionary_decimal_p_s.sql b/tests/queries/0_stateless/01721_dictionary_decimal_p_s.sql new file mode 100644 index 00000000000..0451d455009 --- /dev/null +++ b/tests/queries/0_stateless/01721_dictionary_decimal_p_s.sql @@ -0,0 +1,78 @@ +set allow_experimental_bigint_types=1; +drop database if exists db_01721; +drop table if exists db_01721.table_decimal_dict; +drop dictionary if exists db_01721.decimal_dict; + + +create database db_01721; + +CREATE TABLE db_01721.table_decimal_dict( +KeyField UInt64, +Decimal32_ Decimal(5,4), +Decimal64_ Decimal(18,8), +Decimal128_ Decimal(25,8), +Decimal256_ Decimal(76,37) +) +ENGINE = Memory; + +insert into db_01721.table_decimal_dict +select number, + number / 3, + number / 3, + number / 3, + number / 3 +from numbers(5000); + + +CREATE DICTIONARY IF NOT EXISTS db_01721.decimal_dict ( + KeyField UInt64 DEFAULT 9999999, + Decimal32_ Decimal(5,4) DEFAULT 0.11, + Decimal64_ Decimal(18,8) DEFAULT 0.11, + Decimal128_ Decimal(25,8) DEFAULT 0.11 +-- ,Decimal256_ Decimal256(37) DEFAULT 0.11 +) +PRIMARY KEY KeyField +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'table_decimal_dict' DB 'db_01721')) +LIFETIME(0) LAYOUT(SPARSE_HASHED); + +select '-------- 42 --------'; + +SELECT * from db_01721.table_decimal_dict where KeyField = 42; + +SELECT * from db_01721.decimal_dict where KeyField = 42; + +SELECT dictGet('db_01721.decimal_dict', 'Decimal32_', toUInt64(42)), + dictGet('db_01721.decimal_dict', 'Decimal64_', toUInt64(42)), + dictGet('db_01721.decimal_dict', 'Decimal128_', toUInt64(42)) + -- ,dictGet('db_01721.decimal_dict', 'Decimal256_', toUInt64(42)) +; + + +select '-------- 4999 --------'; + +SELECT * from db_01721.table_decimal_dict where KeyField = 4999; + +SELECT * from db_01721.decimal_dict where KeyField = 4999; + +SELECT dictGet('db_01721.decimal_dict', 'Decimal32_', toUInt64(4999)), + dictGet('db_01721.decimal_dict', 'Decimal64_', toUInt64(4999)), + dictGet('db_01721.decimal_dict', 'Decimal128_', toUInt64(4999)) + --,dictGet('db_01721.decimal_dict', 'Decimal256_', toUInt64(4999)) +; + +select '-------- 5000 --------'; + +SELECT * from db_01721.table_decimal_dict where KeyField = 5000; + +SELECT * from db_01721.decimal_dict where KeyField = 5000; + +SELECT dictGet('db_01721.decimal_dict', 'Decimal32_', toUInt64(5000)), + dictGet('db_01721.decimal_dict', 'Decimal64_', toUInt64(5000)), + dictGet('db_01721.decimal_dict', 'Decimal128_', toUInt64(5000)) + --,dictGet('db_01721.decimal_dict', 'Decimal256_', toUInt64(5000)) +; + +drop table if exists table_decimal_dict; +drop dictionary if exists cache_dict; +drop database if exists db_01721; + diff --git a/tests/queries/0_stateless/01721_engine_file_truncate_on_insert.reference b/tests/queries/0_stateless/01721_engine_file_truncate_on_insert.reference new file mode 100644 index 00000000000..578661c9194 --- /dev/null +++ b/tests/queries/0_stateless/01721_engine_file_truncate_on_insert.reference @@ -0,0 +1,13 @@ +1 +2 +3 +4 +1 +2 +3 +4 +5 +6 +0 +1 +2 diff --git a/tests/queries/0_stateless/01721_engine_file_truncate_on_insert.sql b/tests/queries/0_stateless/01721_engine_file_truncate_on_insert.sql new file mode 100644 index 00000000000..079b2546a20 --- /dev/null +++ b/tests/queries/0_stateless/01721_engine_file_truncate_on_insert.sql @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS test; + +INSERT INTO TABLE FUNCTION file('01721_file/test/data.TSV', 'TSV', 'id UInt32') VALUES (1); +ATTACH TABLE test FROM '01721_file/test' (id UInt8) ENGINE=File(TSV); + +INSERT INTO test VALUES (2), (3); +INSERT INTO test VALUES (4); +SELECT * FROM test; + +SET engine_file_truncate_on_insert=0; + +INSERT INTO test VALUES (5), (6); +SELECT * FROM test; + +SET engine_file_truncate_on_insert=1; + +INSERT INTO test VALUES (0), (1), (2); +SELECT * FROM test; + +SET engine_file_truncate_on_insert=0; +DROP TABLE test; diff --git a/tests/queries/0_stateless/01721_join_implicit_cast_long.reference b/tests/queries/0_stateless/01721_join_implicit_cast_long.reference new file mode 100644 index 00000000000..d78307175f9 --- /dev/null +++ b/tests/queries/0_stateless/01721_join_implicit_cast_long.reference @@ -0,0 +1,804 @@ +=== hash === += full = +-4 0 196 +-3 0 197 +-2 0 198 +-1 0 199 +0 0 200 +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 +6 106 \N +7 107 \N +8 108 \N +9 109 \N +10 110 \N += left = +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 +6 106 \N +7 107 \N +8 108 \N +9 109 \N +10 110 \N += right = +-4 0 196 +-3 0 197 +-2 0 198 +-1 0 199 +0 0 200 +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 += inner = +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 += full = +0 0 -4 +0 0 -3 +0 0 -2 +0 0 -1 +0 0 0 +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 0 +7 7 0 +8 8 0 +9 9 0 +10 10 0 += left = +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 0 +7 7 0 +8 8 0 +9 9 0 +10 10 0 += right = +0 0 -4 +0 0 -3 +0 0 -2 +0 0 -1 +0 0 0 +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 += inner = +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 += join on = += full = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += left = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += right = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += inner = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += full = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += left = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += right = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += inner = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += agg = +1 +1 +1 +1 +1 +1 +0 -10 0 +1 55 1055 +0 0 -10 0 990 +1 55 15 1055 1015 += types = +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +=== partial_merge === += full = +-4 0 196 +-3 0 197 +-2 0 198 +-1 0 199 +0 0 200 +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 +6 106 \N +7 107 \N +8 108 \N +9 109 \N +10 110 \N += left = +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 +6 106 \N +7 107 \N +8 108 \N +9 109 \N +10 110 \N += right = +-4 0 196 +-3 0 197 +-2 0 198 +-1 0 199 +0 0 200 +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 += inner = +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 += full = +0 0 -4 +0 0 -3 +0 0 -2 +0 0 -1 +0 0 0 +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 0 +7 7 0 +8 8 0 +9 9 0 +10 10 0 += left = +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 0 +7 7 0 +8 8 0 +9 9 0 +10 10 0 += right = +0 0 -4 +0 0 -3 +0 0 -2 +0 0 -1 +0 0 0 +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 += inner = +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 += join on = += full = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += left = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += right = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += inner = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += full = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += left = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += right = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += inner = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += agg = +1 +1 +1 +1 +1 +1 +0 -10 0 +1 55 1055 +0 0 -10 0 990 +1 55 15 1055 1015 += types = +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +=== switch === += full = +-4 0 196 +-3 0 197 +-2 0 198 +-1 0 199 +0 0 200 +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 +6 106 \N +7 107 \N +8 108 \N +9 109 \N +10 110 \N += left = +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 +6 106 \N +7 107 \N +8 108 \N +9 109 \N +10 110 \N += right = +-4 0 196 +-3 0 197 +-2 0 198 +-1 0 199 +0 0 200 +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 += inner = +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 += full = +0 0 -4 +0 0 -3 +0 0 -2 +0 0 -1 +0 0 0 +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 0 +7 7 0 +8 8 0 +9 9 0 +10 10 0 += left = +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 0 +7 7 0 +8 8 0 +9 9 0 +10 10 0 += right = +0 0 -4 +0 0 -3 +0 0 -2 +0 0 -1 +0 0 0 +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 += inner = +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 += join on = += full = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += left = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += right = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += inner = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += full = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += left = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 0 \N +7 107 0 \N +8 108 0 \N +9 109 0 \N +10 110 0 \N += right = +0 0 -4 196 +0 0 -3 197 +0 0 -2 198 +0 0 -1 199 +0 0 0 200 +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += inner = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += agg = +1 +1 +1 +1 +1 +1 +0 -10 0 +1 55 1055 +0 0 -10 0 990 +1 55 15 1055 1015 += types = +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +=== join use nulls === += full = +-4 \N 196 +-3 \N 197 +-2 \N 198 +-1 \N 199 +0 \N 200 +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 +6 106 \N +7 107 \N +8 108 \N +9 109 \N +10 110 \N += left = +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 +6 106 \N +7 107 \N +8 108 \N +9 109 \N +10 110 \N += right = +-4 \N 196 +-3 \N 197 +-2 \N 198 +-1 \N 199 +0 \N 200 +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 += inner = +1 101 201 +2 102 202 +3 103 203 +4 104 204 +5 105 205 += full = +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 \N +7 7 \N +8 8 \N +9 9 \N +10 10 \N +\N \N -4 +\N \N -3 +\N \N -2 +\N \N -1 +\N \N 0 += left = +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 \N +7 7 \N +8 8 \N +9 9 \N +10 10 \N += right = +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +\N \N -4 +\N \N -3 +\N \N -2 +\N \N -1 +\N \N 0 += inner = +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 += join on = += full = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 \N \N +7 107 \N \N +8 108 \N \N +9 109 \N \N +10 110 \N \N +\N \N -4 196 +\N \N -3 197 +\N \N -2 198 +\N \N -1 199 +\N \N 0 200 += left = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 \N \N +7 107 \N \N +8 108 \N \N +9 109 \N \N +10 110 \N \N += right = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +\N \N -4 196 +\N \N -3 197 +\N \N -2 198 +\N \N -1 199 +\N \N 0 200 += inner = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += full = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 \N \N +7 107 \N \N +8 108 \N \N +9 109 \N \N +10 110 \N \N +\N \N -4 196 +\N \N -3 197 +\N \N -2 198 +\N \N -1 199 +\N \N 0 200 += left = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +6 106 \N \N +7 107 \N \N +8 108 \N \N +9 109 \N \N +10 110 \N \N += right = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 +\N \N -4 196 +\N \N -3 197 +\N \N -2 198 +\N \N -1 199 +\N \N 0 200 += inner = +1 101 1 201 +2 102 2 202 +3 103 3 203 +4 104 4 204 +5 105 5 205 += agg = +1 +1 +1 +1 +1 +1 +0 -10 \N +1 55 1055 +1 55 15 1055 1015 +\N \N -10 \N 990 += types = +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 diff --git a/tests/queries/0_stateless/01721_join_implicit_cast_long.sql b/tests/queries/0_stateless/01721_join_implicit_cast_long.sql new file mode 100644 index 00000000000..a6b411fadde --- /dev/null +++ b/tests/queries/0_stateless/01721_join_implicit_cast_long.sql @@ -0,0 +1,316 @@ +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; + +CREATE TABLE t1 (a UInt16, b UInt16) ENGINE = TinyLog; +CREATE TABLE t2 (a Int16, b Nullable(Int64)) ENGINE = TinyLog; + +INSERT INTO t1 SELECT number as a, 100 + number as b FROM system.numbers LIMIT 1, 10; +INSERT INTO t2 SELECT number - 5 as a, 200 + number - 5 as b FROM system.numbers LIMIT 1, 10; + +SELECT '=== hash ==='; +SET join_algorithm = 'hash'; + +SELECT '= full ='; +SELECT a, b, t2.b FROM t1 FULL JOIN t2 USING (a) ORDER BY (a); +SELECT '= left ='; +SELECT a, b, t2.b FROM t1 LEFT JOIN t2 USING (a) ORDER BY (a); +SELECT '= right ='; +SELECT a, b, t2.b FROM t1 RIGHT JOIN t2 USING (a) ORDER BY (a); +SELECT '= inner ='; +SELECT a, b, t2.b FROM t1 INNER JOIN t2 USING (a) ORDER BY (a); + +SELECT '= full ='; +SELECT a, t1.a, t2.a FROM t1 FULL JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT a, t1.a, t2.a FROM t1 LEFT JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT a, t1.a, t2.a FROM t1 RIGHT JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT a, t1.a, t2.a FROM t1 INNER JOIN t2 USING (a) ORDER BY (t1.a, t2.a); + +SELECT '= join on ='; +SELECT '= full ='; +SELECT a, b, t2.a, t2.b FROM t1 FULL JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT a, b, t2.a, t2.b FROM t1 LEFT JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT a, b, t2.a, t2.b FROM t1 RIGHT JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT a, b, t2.a, t2.b FROM t1 INNER JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); + +SELECT '= full ='; +SELECT * FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT * FROM t1 LEFT JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT * FROM t1 INNER JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); + +-- Int64 and UInt64 has no supertype +SELECT * FROM t1 FULL JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 LEFT JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 INNER JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } + +SELECT '= agg ='; +SELECT sum(a) == 7 FROM t1 FULL JOIN t2 USING (a) WHERE b > 102 AND t2.b <= 204; +SELECT sum(a) == 7 FROM t1 INNER JOIN t2 USING (a) WHERE b > 102 AND t2.b <= 204; + +SELECT sum(b) = 103 FROM t1 LEFT JOIN t2 USING (a) WHERE b > 102 AND t2.b < 204; +SELECT sum(t2.b) = 203 FROM t1 RIGHT JOIN t2 USING (a) WHERE b > 102 AND t2.b < 204; + +SELECT sum(a) == 2 + 3 + 4 FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) WHERE t1.b < 105 AND t2.b > 201; +SELECT sum(a) == 55 FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) WHERE 1; + +SELECT a > 0, sum(a), sum(b) FROM t1 FULL JOIN t2 USING (a) GROUP BY (a > 0) ORDER BY a > 0; +SELECT a > 0, sum(a), sum(t2.a), sum(b), sum(t2.b) FROM t1 FULL JOIN t2 ON (t1.a == t2.a) GROUP BY (a > 0) ORDER BY a > 0; + +SELECT '= types ='; +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 FULL JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 LEFT JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 RIGHT JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 INNER JOIN t2 USING (a); + +SELECT toTypeName(any(a)) == 'Int32' AND toTypeName(any(t2.a)) == 'Int32' FROM t1 FULL JOIN t2 USING (a); +SELECT min(toTypeName(a) == 'Int32' AND toTypeName(t2.a) == 'Int32') FROM t1 FULL JOIN t2 USING (a); + +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 FULL JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 LEFT JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 RIGHT JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 INNER JOIN t2 ON (t1.a == t2.a); +SELECT toTypeName(any(a)) == 'UInt16' AND toTypeName(any(t2.a)) == 'Int16' FROM t1 FULL JOIN t2 ON (t1.a == t2.a); + +SELECT '=== partial_merge ==='; + +SET join_algorithm = 'partial_merge'; + +SELECT '= full ='; +SELECT a, b, t2.b FROM t1 FULL JOIN t2 USING (a) ORDER BY (a); +SELECT '= left ='; +SELECT a, b, t2.b FROM t1 LEFT JOIN t2 USING (a) ORDER BY (a); +SELECT '= right ='; +SELECT a, b, t2.b FROM t1 RIGHT JOIN t2 USING (a) ORDER BY (a); +SELECT '= inner ='; +SELECT a, b, t2.b FROM t1 INNER JOIN t2 USING (a) ORDER BY (a); + +SELECT '= full ='; +SELECT a, t1.a, t2.a FROM t1 FULL JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT a, t1.a, t2.a FROM t1 LEFT JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT a, t1.a, t2.a FROM t1 RIGHT JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT a, t1.a, t2.a FROM t1 INNER JOIN t2 USING (a) ORDER BY (t1.a, t2.a); + +SELECT '= join on ='; +SELECT '= full ='; +SELECT a, b, t2.a, t2.b FROM t1 FULL JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT a, b, t2.a, t2.b FROM t1 LEFT JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT a, b, t2.a, t2.b FROM t1 RIGHT JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT a, b, t2.a, t2.b FROM t1 INNER JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); + +SELECT '= full ='; +SELECT * FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT * FROM t1 LEFT JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT * FROM t1 INNER JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); + +-- Int64 and UInt64 has no supertype +SELECT * FROM t1 FULL JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 LEFT JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 INNER JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } + +SELECT '= agg ='; +SELECT sum(a) == 7 FROM t1 FULL JOIN t2 USING (a) WHERE b > 102 AND t2.b <= 204; +SELECT sum(a) == 7 FROM t1 INNER JOIN t2 USING (a) WHERE b > 102 AND t2.b <= 204; + +SELECT sum(b) = 103 FROM t1 LEFT JOIN t2 USING (a) WHERE b > 102 AND t2.b < 204; +SELECT sum(t2.b) = 203 FROM t1 RIGHT JOIN t2 USING (a) WHERE b > 102 AND t2.b < 204; + +SELECT sum(a) == 2 + 3 + 4 FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) WHERE t1.b < 105 AND t2.b > 201; +SELECT sum(a) == 55 FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) WHERE 1; + +SELECT a > 0, sum(a), sum(b) FROM t1 FULL JOIN t2 USING (a) GROUP BY (a > 0) ORDER BY a > 0; +SELECT a > 0, sum(a), sum(t2.a), sum(b), sum(t2.b) FROM t1 FULL JOIN t2 ON (t1.a == t2.a) GROUP BY (a > 0) ORDER BY a > 0; + +SELECT '= types ='; +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 FULL JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 LEFT JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 RIGHT JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 INNER JOIN t2 USING (a); + +SELECT toTypeName(any(a)) == 'Int32' AND toTypeName(any(t2.a)) == 'Int32' FROM t1 FULL JOIN t2 USING (a); +SELECT min(toTypeName(a) == 'Int32' AND toTypeName(t2.a) == 'Int32') FROM t1 FULL JOIN t2 USING (a); + +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 FULL JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 LEFT JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 RIGHT JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 INNER JOIN t2 ON (t1.a == t2.a); +SELECT toTypeName(any(a)) == 'UInt16' AND toTypeName(any(t2.a)) == 'Int16' FROM t1 FULL JOIN t2 ON (t1.a == t2.a); + +SELECT '=== switch ==='; + +SET join_algorithm = 'auto'; +SET max_bytes_in_join = 100; + +SELECT '= full ='; +SELECT a, b, t2.b FROM t1 FULL JOIN t2 USING (a) ORDER BY (a); +SELECT '= left ='; +SELECT a, b, t2.b FROM t1 LEFT JOIN t2 USING (a) ORDER BY (a); +SELECT '= right ='; +SELECT a, b, t2.b FROM t1 RIGHT JOIN t2 USING (a) ORDER BY (a); +SELECT '= inner ='; +SELECT a, b, t2.b FROM t1 INNER JOIN t2 USING (a) ORDER BY (a); + +SELECT '= full ='; +SELECT a, t1.a, t2.a FROM t1 FULL JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT a, t1.a, t2.a FROM t1 LEFT JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT a, t1.a, t2.a FROM t1 RIGHT JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT a, t1.a, t2.a FROM t1 INNER JOIN t2 USING (a) ORDER BY (t1.a, t2.a); + +SELECT '= join on ='; +SELECT '= full ='; +SELECT a, b, t2.a, t2.b FROM t1 FULL JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT a, b, t2.a, t2.b FROM t1 LEFT JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT a, b, t2.a, t2.b FROM t1 RIGHT JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT a, b, t2.a, t2.b FROM t1 INNER JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); + +SELECT '= full ='; +SELECT * FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT * FROM t1 LEFT JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT * FROM t1 INNER JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); + +-- Int64 and UInt64 has no supertype +SELECT * FROM t1 FULL JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 LEFT JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 INNER JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } + +SELECT '= agg ='; +SELECT sum(a) == 7 FROM t1 FULL JOIN t2 USING (a) WHERE b > 102 AND t2.b <= 204; +SELECT sum(a) == 7 FROM t1 INNER JOIN t2 USING (a) WHERE b > 102 AND t2.b <= 204; + +SELECT sum(b) = 103 FROM t1 LEFT JOIN t2 USING (a) WHERE b > 102 AND t2.b < 204; +SELECT sum(t2.b) = 203 FROM t1 RIGHT JOIN t2 USING (a) WHERE b > 102 AND t2.b < 204; + +SELECT sum(a) == 2 + 3 + 4 FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) WHERE t1.b < 105 AND t2.b > 201; +SELECT sum(a) == 55 FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) WHERE 1; + +SELECT a > 0, sum(a), sum(b) FROM t1 FULL JOIN t2 USING (a) GROUP BY (a > 0) ORDER BY a > 0; +SELECT a > 0, sum(a), sum(t2.a), sum(b), sum(t2.b) FROM t1 FULL JOIN t2 ON (t1.a == t2.a) GROUP BY (a > 0) ORDER BY a > 0; + +SELECT '= types ='; +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 FULL JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 LEFT JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 RIGHT JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 INNER JOIN t2 USING (a); + +SELECT toTypeName(any(a)) == 'Int32' AND toTypeName(any(t2.a)) == 'Int32' FROM t1 FULL JOIN t2 USING (a); +SELECT min(toTypeName(a) == 'Int32' AND toTypeName(t2.a) == 'Int32') FROM t1 FULL JOIN t2 USING (a); + +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 FULL JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 LEFT JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 RIGHT JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 INNER JOIN t2 ON (t1.a == t2.a); +SELECT toTypeName(any(a)) == 'UInt16' AND toTypeName(any(t2.a)) == 'Int16' FROM t1 FULL JOIN t2 ON (t1.a == t2.a); + +SET max_bytes_in_join = 0; + +SELECT '=== join use nulls ==='; + +SET join_use_nulls = 1; + + +SELECT '= full ='; +SELECT a, b, t2.b FROM t1 FULL JOIN t2 USING (a) ORDER BY (a); +SELECT '= left ='; +SELECT a, b, t2.b FROM t1 LEFT JOIN t2 USING (a) ORDER BY (a); +SELECT '= right ='; +SELECT a, b, t2.b FROM t1 RIGHT JOIN t2 USING (a) ORDER BY (a); +SELECT '= inner ='; +SELECT a, b, t2.b FROM t1 INNER JOIN t2 USING (a) ORDER BY (a); + +SELECT '= full ='; +SELECT a, t1.a, t2.a FROM t1 FULL JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT a, t1.a, t2.a FROM t1 LEFT JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT a, t1.a, t2.a FROM t1 RIGHT JOIN t2 USING (a) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT a, t1.a, t2.a FROM t1 INNER JOIN t2 USING (a) ORDER BY (t1.a, t2.a); + +SELECT '= join on ='; +SELECT '= full ='; +SELECT a, b, t2.a, t2.b FROM t1 FULL JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT a, b, t2.a, t2.b FROM t1 LEFT JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT a, b, t2.a, t2.b FROM t1 RIGHT JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT a, b, t2.a, t2.b FROM t1 INNER JOIN t2 ON (t1.a == t2.a) ORDER BY (t1.a, t2.a); + +SELECT '= full ='; +SELECT * FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= left ='; +SELECT * FROM t1 LEFT JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= right ='; +SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); +SELECT '= inner ='; +SELECT * FROM t1 INNER JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) ORDER BY (t1.a, t2.a); + +-- Int64 and UInt64 has no supertype +SELECT * FROM t1 FULL JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 LEFT JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } +SELECT * FROM t1 INNER JOIN t2 ON (t1.a + t1.b + 100 = t2.a + t2.b) ORDER BY (t1.a, t2.a); -- { serverError 53 } + +SELECT '= agg ='; +SELECT sum(a) == 7 FROM t1 FULL JOIN t2 USING (a) WHERE b > 102 AND t2.b <= 204; +SELECT sum(a) == 7 FROM t1 INNER JOIN t2 USING (a) WHERE b > 102 AND t2.b <= 204; + +SELECT sum(b) = 103 FROM t1 LEFT JOIN t2 USING (a) WHERE b > 102 AND t2.b < 204; +SELECT sum(t2.b) = 203 FROM t1 RIGHT JOIN t2 USING (a) WHERE b > 102 AND t2.b < 204; + +SELECT sum(a) == 2 + 3 + 4 FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) WHERE t1.b < 105 AND t2.b > 201; +SELECT sum(a) == 55 FROM t1 FULL JOIN t2 ON (t1.a + t1.b = t2.a + t2.b - 100) WHERE 1; + +SELECT a > 0, sum(a), sum(b) FROM t1 FULL JOIN t2 USING (a) GROUP BY (a > 0) ORDER BY a > 0; +SELECT a > 0, sum(a), sum(t2.a), sum(b), sum(t2.b) FROM t1 FULL JOIN t2 ON (t1.a == t2.a) GROUP BY (a > 0) ORDER BY a > 0; + +SELECT '= types ='; +SELECT any(toTypeName(a)) == 'Nullable(Int32)' AND any(toTypeName(t2.a)) == 'Nullable(Int32)' FROM t1 FULL JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Nullable(Int32)' FROM t1 LEFT JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Nullable(Int32)' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 RIGHT JOIN t2 USING (a); +SELECT any(toTypeName(a)) == 'Int32' AND any(toTypeName(t2.a)) == 'Int32' FROM t1 INNER JOIN t2 USING (a); + +SELECT toTypeName(any(a)) == 'Nullable(Int32)' AND toTypeName(any(t2.a)) == 'Nullable(Int32)' FROM t1 FULL JOIN t2 USING (a); +SELECT min(toTypeName(a) == 'Nullable(Int32)' AND toTypeName(t2.a) == 'Nullable(Int32)') FROM t1 FULL JOIN t2 USING (a); + +SELECT any(toTypeName(a)) == 'Nullable(UInt16)' AND any(toTypeName(t2.a)) == 'Nullable(Int16)' FROM t1 FULL JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Nullable(Int16)' FROM t1 LEFT JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'Nullable(UInt16)' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 RIGHT JOIN t2 ON (t1.a == t2.a); +SELECT any(toTypeName(a)) == 'UInt16' AND any(toTypeName(t2.a)) == 'Int16' FROM t1 INNER JOIN t2 ON (t1.a == t2.a); +SELECT toTypeName(any(a)) == 'Nullable(UInt16)' AND toTypeName(any(t2.a)) == 'Nullable(Int16)' FROM t1 FULL JOIN t2 ON (t1.a == t2.a); + +SET join_use_nulls = 0; + +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; diff --git a/tests/queries/0_stateless/01722_long_brotli_http_compression_json_format.reference b/tests/queries/0_stateless/01722_long_brotli_http_compression_json_format.reference new file mode 100644 index 00000000000..7c089a2fd05 --- /dev/null +++ b/tests/queries/0_stateless/01722_long_brotli_http_compression_json_format.reference @@ -0,0 +1,23 @@ + }, + { + "datetime": "2020-12-12", + "pipeline": "test-pipeline", + "host": "clickhouse-test-host-001.clickhouse.com", + "home": "clickhouse", + "detail": "clickhouse", + "row_number": "999998" + }, + { + "datetime": "2020-12-12", + "pipeline": "test-pipeline", + "host": "clickhouse-test-host-001.clickhouse.com", + "home": "clickhouse", + "detail": "clickhouse", + "row_number": "999999" + } + ], + + "rows": 1000000, + + "rows_before_limit_at_least": 1048080, + diff --git a/tests/queries/0_stateless/01722_long_brotli_http_compression_json_format.sh b/tests/queries/0_stateless/01722_long_brotli_http_compression_json_format.sh new file mode 100755 index 00000000000..a187d778fdb --- /dev/null +++ b/tests/queries/0_stateless/01722_long_brotli_http_compression_json_format.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +${CLICKHOUSE_CURL} -sS -H 'Accept-Encoding: br' "${CLICKHOUSE_URL}&enable_http_compression=1" -d "SELECT toDate('2020-12-12') as datetime, 'test-pipeline' as pipeline, 'clickhouse-test-host-001.clickhouse.com' as host, 'clickhouse' as home, 'clickhouse' as detail, number as row_number FROM numbers(1000000) FORMAT JSON" | brotli -d | tail -n30 | head -n23 diff --git a/tests/queries/0_stateless/01730_distributed_group_by_no_merge_order_by_long.reference b/tests/queries/0_stateless/01730_distributed_group_by_no_merge_order_by_long.reference new file mode 100644 index 00000000000..02ae8a37e52 --- /dev/null +++ b/tests/queries/0_stateless/01730_distributed_group_by_no_merge_order_by_long.reference @@ -0,0 +1,20 @@ +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 diff --git a/tests/queries/0_stateless/01730_distributed_group_by_no_merge_order_by_long.sql b/tests/queries/0_stateless/01730_distributed_group_by_no_merge_order_by_long.sql new file mode 100644 index 00000000000..e43b81dca48 --- /dev/null +++ b/tests/queries/0_stateless/01730_distributed_group_by_no_merge_order_by_long.sql @@ -0,0 +1,20 @@ +drop table if exists data_01730; + +-- does not use 127.1 due to prefer_localhost_replica + +select * from remote('127.{2..11}', view(select * from numbers(1e6))) group by number order by number limit 20 settings distributed_group_by_no_merge=0, max_memory_usage='100Mi'; -- { serverError 241 } +-- no memory limit error, because with distributed_group_by_no_merge=2 remote servers will do ORDER BY and will cut to the LIMIT +select * from remote('127.{2..11}', view(select * from numbers(1e6))) group by number order by number limit 20 settings distributed_group_by_no_merge=2, max_memory_usage='100Mi'; + +-- since the MergingSortedTransform will start processing only when all ports (remotes) will have some data, +-- and the query with GROUP BY on remote servers will first do GROUP BY and then send the block, +-- so the initiator will first receive all blocks from remotes and only after start merging, +-- and will hit the memory limit. +select * from remote('127.{2..11}', view(select * from numbers(1e6))) group by number order by number limit 1e6 settings distributed_group_by_no_merge=2, max_memory_usage='100Mi'; -- { serverError 241 } + +-- with optimize_aggregation_in_order=1 remote servers will produce blocks more frequently, +-- since they don't need to wait until the aggregation will be finished, +-- and so the query will not hit the memory limit error. +create table data_01730 engine=MergeTree() order by key as select number key from numbers(1e6); +select * from remote('127.{2..11}', currentDatabase(), data_01730) group by key order by key limit 1e6 settings distributed_group_by_no_merge=2, max_memory_usage='100Mi', optimize_aggregation_in_order=1 format Null; +drop table data_01730; diff --git a/tests/queries/0_stateless/01731_async_task_queue_wait.reference b/tests/queries/0_stateless/01731_async_task_queue_wait.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01731_async_task_queue_wait.sh b/tests/queries/0_stateless/01731_async_task_queue_wait.sh new file mode 100755 index 00000000000..e0babf3c6ff --- /dev/null +++ b/tests/queries/0_stateless/01731_async_task_queue_wait.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +# regression for 'Empty task was returned from async task queue' during query +# cancellation with async_socket_for_remote=1 (that ignores +# max_distributed_connections) +timeout --signal=SIGINT 1 ${CLICKHOUSE_CLIENT} --max_distributed_connections=1 --max_block_size=2 --interactive_delay=900000 -q "select number + sleep(0.3) as x from remote('127.{2,3}', system.numbers) settings max_block_size = 2" 2>&1 | grep "Empty task was returned from async task queue" || true diff --git a/tests/queries/0_stateless/01732_alters_bad_conversions.reference b/tests/queries/0_stateless/01732_alters_bad_conversions.reference new file mode 100644 index 00000000000..5f570c78579 --- /dev/null +++ b/tests/queries/0_stateless/01732_alters_bad_conversions.reference @@ -0,0 +1,4 @@ +CREATE TABLE default.bad_conversions\n(\n `a` UInt32\n)\nENGINE = MergeTree\nORDER BY tuple()\nSETTINGS index_granularity = 8192 +0 +CREATE TABLE default.bad_conversions_2\n(\n `e` Enum8(\'foo\' = 1, \'bar\' = 2)\n)\nENGINE = MergeTree\nORDER BY tuple()\nSETTINGS index_granularity = 8192 +0 diff --git a/tests/queries/0_stateless/01732_alters_bad_conversions.sql b/tests/queries/0_stateless/01732_alters_bad_conversions.sql new file mode 100644 index 00000000000..27da5242368 --- /dev/null +++ b/tests/queries/0_stateless/01732_alters_bad_conversions.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS bad_conversions; +DROP TABLE IF EXISTS bad_conversions_2; + +CREATE TABLE bad_conversions (a UInt32) ENGINE = MergeTree ORDER BY tuple(); +INSERT INTO bad_conversions VALUES (1); +ALTER TABLE bad_conversions MODIFY COLUMN a Array(String); -- { serverError 53 } +SHOW CREATE TABLE bad_conversions; +SELECT count() FROM system.mutations WHERE table = 'bad_conversions' AND database = currentDatabase(); + +CREATE TABLE bad_conversions_2 (e Enum('foo' = 1, 'bar' = 2)) ENGINE = MergeTree ORDER BY tuple(); +INSERT INTO bad_conversions_2 VALUES (1); +ALTER TABLE bad_conversions_2 MODIFY COLUMN e Enum('bar' = 1, 'foo' = 2); -- { serverError 70 } +SHOW CREATE TABLE bad_conversions_2; +SELECT count() FROM system.mutations WHERE table = 'bad_conversions_2' AND database = currentDatabase(); + +DROP TABLE IF EXISTS bad_conversions; +DROP TABLE IF EXISTS bad_conversions_2; diff --git a/tests/queries/0_stateless/01732_bigint_ubsan.reference b/tests/queries/0_stateless/01732_bigint_ubsan.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01732_bigint_ubsan.sql b/tests/queries/0_stateless/01732_bigint_ubsan.sql new file mode 100644 index 00000000000..238a5d99d30 --- /dev/null +++ b/tests/queries/0_stateless/01732_bigint_ubsan.sql @@ -0,0 +1,11 @@ +CREATE TEMPORARY TABLE decimal +( + f dec(38, 38) +); + +INSERT INTO decimal VALUES (0); +INSERT INTO decimal VALUES (0.42); +INSERT INTO decimal VALUES (-0.42); + +SELECT f + 1048575, f - 21, f - 84, f * 21, f * -21, f / 21, f / 84 FROM decimal WHERE f > 0; -- { serverError 407 } +SELECT f + -2, f - 21, f - 84, f * 21, f * -21, f / 9223372036854775807, f / 84 FROM decimal WHERE f > 0; -- { serverError 407 } diff --git a/tests/queries/0_stateless/01732_explain_syntax_union_query.reference b/tests/queries/0_stateless/01732_explain_syntax_union_query.reference new file mode 100644 index 00000000000..fe5eb01a7ed --- /dev/null +++ b/tests/queries/0_stateless/01732_explain_syntax_union_query.reference @@ -0,0 +1,66 @@ +SELECT 1 +UNION ALL +SELECT 1 +UNION ALL +SELECT 1 +UNION ALL +SELECT 1 +UNION ALL +SELECT 1 + +SELECT 1 +UNION ALL +( + SELECT 1 + UNION DISTINCT + SELECT 1 + UNION DISTINCT + SELECT 1 +) +UNION ALL +SELECT 1 + +SELECT x +FROM +( + SELECT 1 AS x + UNION ALL + ( + SELECT 1 + UNION DISTINCT + SELECT 1 + UNION DISTINCT + SELECT 1 + ) + UNION ALL + SELECT 1 +) + +SELECT x +FROM +( + SELECT 1 AS x + UNION ALL + SELECT 1 + UNION ALL + SELECT 1 +) + +SELECT 1 +UNION DISTINCT +SELECT 1 +UNION DISTINCT +SELECT 1 + +SELECT 1 + + +( + SELECT 1 + UNION DISTINCT + SELECT 1 + UNION DISTINCT + SELECT 1 +) +UNION ALL +SELECT 1 diff --git a/tests/queries/0_stateless/01732_explain_syntax_union_query.sql b/tests/queries/0_stateless/01732_explain_syntax_union_query.sql new file mode 100644 index 00000000000..0dd1e19e765 --- /dev/null +++ b/tests/queries/0_stateless/01732_explain_syntax_union_query.sql @@ -0,0 +1,86 @@ +EXPLAIN SYNTAX +SELECT 1 +UNION ALL +( + SELECT 1 + UNION ALL + ( + SELECT 1 + UNION ALL + SELECT 1 + ) + UNION ALL + SELECT 1 +); + +SELECT ' '; + +EXPLAIN SYNTAX +SELECT 1 +UNION ALL +( + SELECT 1 + UNION DISTINCT + ( + SELECT 1 + UNION ALL + SELECT 1 + ) + UNION ALL + SELECT 1 +); + +SELECT ' '; + +EXPLAIN SYNTAX +SELECT x +FROM +( + SELECT 1 AS x + UNION ALL + ( + SELECT 1 + UNION DISTINCT + ( + SELECT 1 + UNION ALL + SELECT 1 + ) + UNION ALL + SELECT 1 + ) +); + +SELECT ' '; + +EXPLAIN SYNTAX +SELECT x +FROM +( + SELECT 1 AS x + UNION ALL + ( + SELECT 1 + UNION ALL + SELECT 1 + ) +); + +SELECT ' '; + +EXPLAIN SYNTAX +SELECT 1 +UNION ALL +SELECT 1 +UNION DISTINCT +SELECT 1; + +SELECT ' '; + +EXPLAIN SYNTAX +(((((((((((((((SELECT 1))))))))))))))); + +SELECT ' '; + +EXPLAIN SYNTAX +(((((((((((((((SELECT 1 UNION DISTINCT SELECT 1))) UNION DISTINCT SELECT 1)))) UNION ALL SELECT 1)))))))); diff --git a/tests/queries/0_stateless/01732_more_consistent_datetime64_parsing.reference b/tests/queries/0_stateless/01732_more_consistent_datetime64_parsing.reference new file mode 100644 index 00000000000..4f3181ecce0 --- /dev/null +++ b/tests/queries/0_stateless/01732_more_consistent_datetime64_parsing.reference @@ -0,0 +1,8 @@ +1 2005-03-18 01:58:31.222 +2 2005-03-18 01:58:31.222 +3 2005-03-18 01:58:31.222 +4 2005-03-18 01:58:31.222 +2005-03-18 04:58:31.222 +2005-03-18 04:58:31.222 +2005-03-18 04:58:31.222 +0 diff --git a/tests/queries/0_stateless/01732_more_consistent_datetime64_parsing.sql b/tests/queries/0_stateless/01732_more_consistent_datetime64_parsing.sql new file mode 100644 index 00000000000..dcd874f8c45 --- /dev/null +++ b/tests/queries/0_stateless/01732_more_consistent_datetime64_parsing.sql @@ -0,0 +1,11 @@ +CREATE TEMPORARY TABLE t (i UInt8, x DateTime64(3, 'UTC')); +INSERT INTO t VALUES (1, 1111111111222); +INSERT INTO t VALUES (2, 1111111111.222); +INSERT INTO t VALUES (3, '1111111111222'); +INSERT INTO t VALUES (4, '1111111111.222'); +SELECT * FROM t ORDER BY i; + +SELECT toDateTime64(1111111111.222, 3); +SELECT toDateTime64('1111111111.222', 3); +SELECT toDateTime64('1111111111222', 3); +SELECT ignore(toDateTime64(1111111111222, 3)); -- This gives somewhat correct but unexpected result diff --git a/tests/queries/0_stateless/01732_race_condition_storage_join_long.reference b/tests/queries/0_stateless/01732_race_condition_storage_join_long.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01732_race_condition_storage_join_long.sh b/tests/queries/0_stateless/01732_race_condition_storage_join_long.sh new file mode 100755 index 00000000000..b7dd76760d4 --- /dev/null +++ b/tests/queries/0_stateless/01732_race_condition_storage_join_long.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +unset CLICKHOUSE_LOG_COMMENT + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +set -o errexit +set -o pipefail + +echo " + DROP TABLE IF EXISTS storage_join_race; + CREATE TABLE storage_join_race (x UInt64, y UInt64) Engine = Join(ALL, FULL, x); +" | $CLICKHOUSE_CLIENT -n + +function read_thread_big() +{ + while true; do + echo " + SELECT * FROM ( SELECT number AS x FROM numbers(100000) ) AS t1 ALL FULL JOIN storage_join_race USING (x) FORMAT Null; + " | $CLICKHOUSE_CLIENT -n + done +} + +function read_thread_small() +{ + while true; do + echo " + SELECT * FROM ( SELECT number AS x FROM numbers(10) ) AS t1 ALL FULL JOIN storage_join_race USING (x) FORMAT Null; + " | $CLICKHOUSE_CLIENT -n + done +} + +function read_thread_select() +{ + while true; do + echo " + SELECT * FROM storage_join_race FORMAT Null; + " | $CLICKHOUSE_CLIENT -n + done +} + +# https://stackoverflow.com/questions/9954794/execute-a-shell-function-with-timeout +export -f read_thread_big; +export -f read_thread_small; +export -f read_thread_select; + +TIMEOUT=20 + +timeout $TIMEOUT bash -c read_thread_big 2> /dev/null & +timeout $TIMEOUT bash -c read_thread_small 2> /dev/null & +timeout $TIMEOUT bash -c read_thread_select 2> /dev/null & + +echo " + INSERT INTO storage_join_race SELECT number AS x, number AS y FROM numbers (10000000); +" | $CLICKHOUSE_CLIENT -n + +wait + +$CLICKHOUSE_CLIENT -q "DROP TABLE storage_join_race" diff --git a/tests/queries/0_stateless/01732_union_and_union_all.reference b/tests/queries/0_stateless/01732_union_and_union_all.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01732_union_and_union_all.sql b/tests/queries/0_stateless/01732_union_and_union_all.sql new file mode 100644 index 00000000000..2de6daa5bb9 --- /dev/null +++ b/tests/queries/0_stateless/01732_union_and_union_all.sql @@ -0,0 +1 @@ +select 1 UNION select 1 UNION ALL select 1; -- { serverError 558 } diff --git a/tests/queries/0_stateless/01733_transform_ubsan.reference b/tests/queries/0_stateless/01733_transform_ubsan.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01733_transform_ubsan.sql b/tests/queries/0_stateless/01733_transform_ubsan.sql new file mode 100644 index 00000000000..256603e9087 --- /dev/null +++ b/tests/queries/0_stateless/01733_transform_ubsan.sql @@ -0,0 +1,4 @@ +SELECT arrayStringConcat(arrayMap(x -> transform(x, [1025, -9223372036854775808, 65537, 257, 1048576, 10, 7, 1048575, 65536], ['yandex', 'googlegooglegooglegoogle', 'test', '', '', 'hello', 'world', '', 'xyz'], ''), arrayMap(x -> (x % -inf), range(number))), '') +FROM system.numbers +LIMIT 1025 +FORMAT Null; diff --git a/tests/queries/0_stateless/01734_datetime64_from_float.reference b/tests/queries/0_stateless/01734_datetime64_from_float.reference new file mode 100644 index 00000000000..32e7d2736c6 --- /dev/null +++ b/tests/queries/0_stateless/01734_datetime64_from_float.reference @@ -0,0 +1,7 @@ +-- { echo } +SELECT CAST(1111111111.222 AS DateTime64(3)); +2005-03-18 04:58:31.222 +SELECT toDateTime(1111111111.222, 3); +2005-03-18 04:58:31.222 +SELECT toDateTime64(1111111111.222, 3); +2005-03-18 04:58:31.222 diff --git a/tests/queries/0_stateless/01734_datetime64_from_float.sql b/tests/queries/0_stateless/01734_datetime64_from_float.sql new file mode 100644 index 00000000000..b6be65cb7c2 --- /dev/null +++ b/tests/queries/0_stateless/01734_datetime64_from_float.sql @@ -0,0 +1,4 @@ +-- { echo } +SELECT CAST(1111111111.222 AS DateTime64(3)); +SELECT toDateTime(1111111111.222, 3); +SELECT toDateTime64(1111111111.222, 3); diff --git a/tests/queries/0_stateless/01735_join_get_low_card_fix.reference b/tests/queries/0_stateless/01735_join_get_low_card_fix.reference new file mode 100644 index 00000000000..0b20aead00e --- /dev/null +++ b/tests/queries/0_stateless/01735_join_get_low_card_fix.reference @@ -0,0 +1 @@ +yyy diff --git a/tests/queries/0_stateless/01735_join_get_low_card_fix.sql b/tests/queries/0_stateless/01735_join_get_low_card_fix.sql new file mode 100644 index 00000000000..bdc979bc11e --- /dev/null +++ b/tests/queries/0_stateless/01735_join_get_low_card_fix.sql @@ -0,0 +1,9 @@ +drop table if exists join_tbl; + +create table join_tbl (`id` String, `name` String) engine Join(any, left, id); + +insert into join_tbl values ('xxx', 'yyy'); + +select joinGet('join_tbl', 'name', toLowCardinality('xxx')); + +drop table if exists join_tbl; diff --git a/tests/queries/0_stateless/01735_to_datetime64.reference b/tests/queries/0_stateless/01735_to_datetime64.reference new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/tests/queries/0_stateless/01735_to_datetime64.reference @@ -0,0 +1 @@ +1 diff --git a/tests/queries/0_stateless/01735_to_datetime64.sql b/tests/queries/0_stateless/01735_to_datetime64.sql new file mode 100644 index 00000000000..fe4eb521148 --- /dev/null +++ b/tests/queries/0_stateless/01735_to_datetime64.sql @@ -0,0 +1 @@ +SELECT toDate(toDateTime64(today(), 0, 'UTC')) = toDate(toDateTime(today(), 'UTC')); diff --git a/tests/queries/0_stateless/01736_null_as_default.reference b/tests/queries/0_stateless/01736_null_as_default.reference new file mode 100644 index 00000000000..baf83eb21d7 --- /dev/null +++ b/tests/queries/0_stateless/01736_null_as_default.reference @@ -0,0 +1,2 @@ +A +\N diff --git a/tests/queries/0_stateless/01736_null_as_default.sql b/tests/queries/0_stateless/01736_null_as_default.sql new file mode 100644 index 00000000000..f9a4bc69acf --- /dev/null +++ b/tests/queries/0_stateless/01736_null_as_default.sql @@ -0,0 +1,5 @@ +drop table if exists test_num; +create table test_enum (c Nullable(Enum16('A' = 1, 'B' = 2))) engine Log; +insert into test_enum values (1), (NULL); +select * from test_enum; +drop table if exists test_num; diff --git a/tests/queries/0_stateless/01744_tuple_cast_to_map_bugfix.reference b/tests/queries/0_stateless/01744_tuple_cast_to_map_bugfix.reference new file mode 100644 index 00000000000..c5143f7c4e9 --- /dev/null +++ b/tests/queries/0_stateless/01744_tuple_cast_to_map_bugfix.reference @@ -0,0 +1,3 @@ +{1:'Ready',2:'Steady',3:'Go'} +{1:'Ready',2:'Steady',3:'Go'} +{1:'Ready',2:'Steady',3:'Go'} diff --git a/tests/queries/0_stateless/01744_tuple_cast_to_map_bugfix.sql b/tests/queries/0_stateless/01744_tuple_cast_to_map_bugfix.sql new file mode 100644 index 00000000000..c5c50c5b039 --- /dev/null +++ b/tests/queries/0_stateless/01744_tuple_cast_to_map_bugfix.sql @@ -0,0 +1,3 @@ +SELECT CAST((['1', '2', '3'], ['Ready', 'Steady', 'Go']), 'Map(UInt8, String)') AS map; +SELECT CAST((['1', '2', '3'], ['Ready', 'Steady', 'Go']), 'Map(UInt8, String)') AS map; +SELECT CAST((['1', '2', '3'], ['Ready', 'Steady', 'Go']), 'Map(UInt8, String)') AS map; diff --git a/tests/queries/0_stateless/01745_alter_delete_view.reference b/tests/queries/0_stateless/01745_alter_delete_view.reference new file mode 100644 index 00000000000..dc3ab50ab0d --- /dev/null +++ b/tests/queries/0_stateless/01745_alter_delete_view.reference @@ -0,0 +1,4 @@ +1 1 +2 1 +1 1 +2 1 diff --git a/tests/queries/0_stateless/01745_alter_delete_view.sql b/tests/queries/0_stateless/01745_alter_delete_view.sql new file mode 100644 index 00000000000..c242f1be63e --- /dev/null +++ b/tests/queries/0_stateless/01745_alter_delete_view.sql @@ -0,0 +1,28 @@ +DROP VIEW IF EXISTS test_view; +DROP TABLE IF EXISTS test_table; + +CREATE TABLE test_table +( + f1 Int32, + f2 Int32, + pk Int32 +) +ENGINE = MergeTree() +ORDER BY f1 +PARTITION BY pk; + +CREATE VIEW test_view AS +SELECT f1, f2 +FROM test_table +WHERE pk = 2; + +INSERT INTO test_table (f1, f2, pk) VALUES (1,1,1), (1,1,2), (2,1,1), (2,1,2); + +SELECT * FROM test_view ORDER BY f1, f2; + +ALTER TABLE test_view DELETE WHERE pk = 2; --{serverError 48} + +SELECT * FROM test_view ORDER BY f1, f2; + +DROP VIEW IF EXISTS test_view; +DROP TABLE IF EXISTS test_table; diff --git a/tests/queries/0_stateless/01746_executable_pool_dictionary.reference b/tests/queries/0_stateless/01746_executable_pool_dictionary.reference new file mode 100644 index 00000000000..cf79a75e3f1 --- /dev/null +++ b/tests/queries/0_stateless/01746_executable_pool_dictionary.reference @@ -0,0 +1,10 @@ +executable_pool_simple +1 a +1 b +2 a +2 b +executable_pool_complex +value a +value b +value a +value b diff --git a/tests/queries/0_stateless/01746_executable_pool_dictionary.sql b/tests/queries/0_stateless/01746_executable_pool_dictionary.sql new file mode 100644 index 00000000000..aa59d209b51 --- /dev/null +++ b/tests/queries/0_stateless/01746_executable_pool_dictionary.sql @@ -0,0 +1,15 @@ +SELECT 'executable_pool_simple'; + +SELECT dictGet('executable_pool_simple', 'a', toUInt64(1)); +SELECT dictGet('executable_pool_simple', 'b', toUInt64(1)); + +SELECT dictGet('executable_pool_simple', 'a', toUInt64(2)); +SELECT dictGet('executable_pool_simple', 'b', toUInt64(2)); + +SELECT 'executable_pool_complex'; + +SELECT dictGet('executable_pool_complex', 'a', ('First_1', 'Second_1')); +SELECT dictGet('executable_pool_complex', 'b', ('First_1', 'Second_1')); + +SELECT dictGet('executable_pool_complex', 'a', ('First_2', 'Second_2')); +SELECT dictGet('executable_pool_complex', 'b', ('First_2', 'Second_2')); diff --git a/tests/queries/0_stateless/01746_extract_text_from_html.reference b/tests/queries/0_stateless/01746_extract_text_from_html.reference new file mode 100644 index 00000000000..ee05e085ba4 --- /dev/null +++ b/tests/queries/0_stateless/01746_extract_text_from_html.reference @@ -0,0 +1,120 @@ +-- { echo } + +SELECT extractTextFromHTML(''); + +SELECT extractTextFromHTML(' '); + +SELECT extractTextFromHTML(' '); + +SELECT extractTextFromHTML('Hello'); +Hello +SELECT extractTextFromHTML('Hello, world'); +Hello, world +SELECT extractTextFromHTML('Hello, world'); +Hello, world +SELECT extractTextFromHTML(' Hello, world'); +Hello, world +SELECT extractTextFromHTML(' Hello, world '); +Hello, world +SELECT extractTextFromHTML(' \t Hello,\rworld \n '); +Hello, world +SELECT extractTextFromHTML('Hello world'); +Hello > world +SELECT extractTextFromHTML('Hello'); +Hello +SELECT extractTextFromHTML('Hello<>world'); +Hello world +SELECT extractTextFromHTML('Helloworld'); +Hello world +SELECT extractTextFromHTML('Helloworld'); +Hello world +SELECT extractTextFromHTML('Helloworld'); +Hello world +SELECT extractTextFromHTML('Helloworld'); +Hello world +SELECT extractTextFromHTML('Helloworld'); +Hello world +SELECT extractTextFromHTML('Hello World'); +Hello World +SELECT extractTextFromHTML('Hello World'); +Hello World +SELECT extractTextFromHTML('HelloWorld'); +Hello World +SELECT extractTextFromHTML('Hello World'); +Hello World +SELECT extractTextFromHTML('Hello World'); +Hello World +SELECT extractTextFromHTML('Hello World'); +Hello World +SELECT extractTextFromHTML('HelloWorld'); +Hello World +SELECT extractTextFromHTML('Hello World'); +Hello World +SELECT extractTextFromHTML(''); + \t Hello,\rworld \n +SELECT extractTextFromHTML('Hello world!'); +HelloHello\tworld world! +SELECT extractTextFromHTML('Helloworld!'); +HelloHello\tworld world! +SELECT extractTextFromHTML('Hello world]]> world!'); +HelloHello world world! +SELECT extractTextFromHTML('John Smith]]>'); +John Smith +SELECT extractTextFromHTML('John ]]>'); +John +SELECT extractTextFromHTML('John Smith]]>'); +John +SELECT extractTextFromHTML('John ]]>]]>'); +John Smith +SELECT extractTextFromHTML('John ]]> ]]>'); +John Smith +SELECT extractTextFromHTML('John]]> ]]>'); +JohnSmith +SELECT extractTextFromHTML('John ]]>]]>]]>'); +John ]]>Smith +SELECT extractTextFromHTML('Hello goodbye'); +Hello goodbye +SELECT extractTextFromHTML('Hello goodbye'); +Hello goodbye +SELECT extractTextFromHTML('HelloWorld goodbye'); +Hello World goodbye +SELECT extractTextFromHTML('Hello goodbye'); +Hello goodbye +SELECT extractTextFromHTML('Hello goodbye'); +Hello goodbye +SELECT extractTextFromHTML('HelloWorld goodbye'); +Hello World goodbye +SELECT extractTextFromHTML('HelloWorld goodbye'); +Hello World goodbye +SELECT extractTextFromHTML('Hello goodbye'); +Hello goodbye +SELECT extractTextFromHTML('Hello goodbye'); +Hello goodbye +SELECT extractTextFromHTML('Hello]]> goodbye'); +Hello +SELECT extractTextFromHTML('Hello]]> goodbye'); +Hello goodbye +SELECT extractTextFromHTML('Hello]]> goodbye'); +Hello ]]> goodbye +SELECT extractTextFromHTML('Hello goodbye'); +Hello goodbye +SELECT extractTextFromHTML('Hello goodbye'); +Hello goodbye +SELECT extractTextFromHTML(']]>'); +]]> +SELECT extractTextFromHTML(' + +
xkcd.com + +'); +xkcd.com diff --git a/tests/queries/0_stateless/01746_extract_text_from_html.sql b/tests/queries/0_stateless/01746_extract_text_from_html.sql new file mode 100644 index 00000000000..b4ccc775bef --- /dev/null +++ b/tests/queries/0_stateless/01746_extract_text_from_html.sql @@ -0,0 +1,72 @@ +-- { echo } + +SELECT extractTextFromHTML(''); +SELECT extractTextFromHTML(' '); +SELECT extractTextFromHTML(' '); +SELECT extractTextFromHTML('Hello'); +SELECT extractTextFromHTML('Hello, world'); +SELECT extractTextFromHTML('Hello, world'); +SELECT extractTextFromHTML(' Hello, world'); +SELECT extractTextFromHTML(' Hello, world '); +SELECT extractTextFromHTML(' \t Hello,\rworld \n '); + +SELECT extractTextFromHTML('Hello world'); +SELECT extractTextFromHTML('Hello'); +SELECT extractTextFromHTML('Hello<>world'); +SELECT extractTextFromHTML('Helloworld'); +SELECT extractTextFromHTML('Helloworld'); +SELECT extractTextFromHTML('Helloworld'); +SELECT extractTextFromHTML('Helloworld'); +SELECT extractTextFromHTML('Helloworld'); + +SELECT extractTextFromHTML('Hello World'); +SELECT extractTextFromHTML('Hello World'); +SELECT extractTextFromHTML('HelloWorld'); +SELECT extractTextFromHTML('Hello World'); +SELECT extractTextFromHTML('Hello World'); +SELECT extractTextFromHTML('Hello World'); +SELECT extractTextFromHTML('HelloWorld'); +SELECT extractTextFromHTML('Hello World'); + +SELECT extractTextFromHTML(''); +SELECT extractTextFromHTML('Hello world!'); +SELECT extractTextFromHTML('Helloworld!'); + +SELECT extractTextFromHTML('Hello world]]> world!'); +SELECT extractTextFromHTML('John Smith
]]>'); +SELECT extractTextFromHTML('John ]]>'); +SELECT extractTextFromHTML('John Smith]]>'); +SELECT extractTextFromHTML('John ]]>]]>'); +SELECT extractTextFromHTML('John ]]> ]]>'); +SELECT extractTextFromHTML('John]]> ]]>'); +SELECT extractTextFromHTML('John ]]>]]>]]>'); + +SELECT extractTextFromHTML('Hello goodbye'); +SELECT extractTextFromHTML('Hello goodbye'); +SELECT extractTextFromHTML('HelloWorld goodbye'); +SELECT extractTextFromHTML('Hello goodbye'); +SELECT extractTextFromHTML('Hello goodbye'); +SELECT extractTextFromHTML('HelloWorld goodbye'); +SELECT extractTextFromHTML('HelloWorld goodbye'); + +SELECT extractTextFromHTML('Hello goodbye'); +SELECT extractTextFromHTML('Hello goodbye'); +SELECT extractTextFromHTML('Hello]]> goodbye'); +SELECT extractTextFromHTML('Hello]]> goodbye'); +SELECT extractTextFromHTML('Hello]]> goodbye'); +SELECT extractTextFromHTML('Hello goodbye'); +SELECT extractTextFromHTML('Hello goodbye'); + +SELECT extractTextFromHTML(']]>'); + +SELECT extractTextFromHTML(' + +
xkcd.com + +'); diff --git a/tests/queries/0_stateless/01746_forbid_drop_column_referenced_by_mv.reference b/tests/queries/0_stateless/01746_forbid_drop_column_referenced_by_mv.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01746_forbid_drop_column_referenced_by_mv.sql b/tests/queries/0_stateless/01746_forbid_drop_column_referenced_by_mv.sql new file mode 100644 index 00000000000..f084cae7780 --- /dev/null +++ b/tests/queries/0_stateless/01746_forbid_drop_column_referenced_by_mv.sql @@ -0,0 +1,172 @@ +-- MergeTree +DROP TABLE IF EXISTS `01746_merge_tree`; +CREATE TABLE `01746_merge_tree` +( + `n1` Int8, + `n2` Int8, + `n3` Int8, + `n4` Int8 +) +ENGINE = MergeTree +ORDER BY n1; + +DROP TABLE IF EXISTS `01746_merge_tree_mv`; +CREATE MATERIALIZED VIEW `01746_merge_tree_mv` +ENGINE = Memory AS +SELECT + n2, + n3 +FROM `01746_merge_tree`; + +ALTER TABLE `01746_merge_tree` + DROP COLUMN n3; -- { serverError 524 } + +ALTER TABLE `01746_merge_tree` + DROP COLUMN n2; -- { serverError 524 } + +-- ok +ALTER TABLE `01746_merge_tree` + DROP COLUMN n4; + +DROP TABLE `01746_merge_tree`; +DROP TABLE `01746_merge_tree_mv`; + +-- Null +DROP TABLE IF EXISTS `01746_null`; +CREATE TABLE `01746_null` +( + `n1` Int8, + `n2` Int8, + `n3` Int8 +) +ENGINE = Null; + +DROP TABLE IF EXISTS `01746_null_mv`; +CREATE MATERIALIZED VIEW `01746_null_mv` +ENGINE = Memory AS +SELECT + n1, + n2 +FROM `01746_null`; + +ALTER TABLE `01746_null` + DROP COLUMN n1; -- { serverError 524 } + +ALTER TABLE `01746_null` + DROP COLUMN n2; -- { serverError 524 } + +-- ok +ALTER TABLE `01746_null` + DROP COLUMN n3; + +DROP TABLE `01746_null`; +DROP TABLE `01746_null_mv`; + +-- Distributed + +DROP TABLE IF EXISTS `01746_local`; +CREATE TABLE `01746_local` +( + `n1` Int8, + `n2` Int8, + `n3` Int8 +) +ENGINE = Memory; + +DROP TABLE IF EXISTS `01746_dist`; +CREATE TABLE `01746_dist` AS `01746_local` +ENGINE = Distributed('test_shard_localhost', currentDatabase(), `01746_local`, rand()); + +DROP TABLE IF EXISTS `01746_dist_mv`; +CREATE MATERIALIZED VIEW `01746_dist_mv` +ENGINE = Memory AS +SELECT + n1, + n2 +FROM `01746_dist`; + +ALTER TABLE `01746_dist` + DROP COLUMN n1; -- { serverError 524 } + +ALTER TABLE `01746_dist` + DROP COLUMN n2; -- { serverError 524 } + +-- ok +ALTER TABLE `01746_dist` + DROP COLUMN n3; + +DROP TABLE `01746_local`; +DROP TABLE `01746_dist`; +DROP TABLE `01746_dist_mv`; + +-- Merge +DROP TABLE IF EXISTS `01746_merge_t`; +CREATE TABLE `01746_merge_t` +( + `n1` Int8, + `n2` Int8, + `n3` Int8 +) +ENGINE = Memory; + +DROP TABLE IF EXISTS `01746_merge`; +CREATE TABLE `01746_merge` AS `01746_merge_t` +ENGINE = Merge(currentDatabase(), '01746_merge_t'); + +DROP TABLE IF EXISTS `01746_merge_mv`; +CREATE MATERIALIZED VIEW `01746_merge_mv` +ENGINE = Memory AS +SELECT + n1, + n2 +FROM `01746_merge`; + +ALTER TABLE `01746_merge` + DROP COLUMN n1; -- { serverError 524 } + +ALTER TABLE `01746_merge` + DROP COLUMN n2; -- { serverError 524 } + +-- ok +ALTER TABLE `01746_merge` + DROP COLUMN n3; + +DROP TABLE `01746_merge_t`; +DROP TABLE `01746_merge`; +DROP TABLE `01746_merge_mv`; + +-- Buffer +DROP TABLE IF EXISTS `01746_buffer_t`; +CREATE TABLE `01746_buffer_t` +( + `n1` Int8, + `n2` Int8, + `n3` Int8 +) +ENGINE = Memory; + +DROP TABLE IF EXISTS `01746_buffer`; +CREATE TABLE `01746_buffer` AS `01746_buffer_t` +ENGINE = Buffer(currentDatabase(), `01746_buffer_t`, 16, 10, 100, 10000, 1000000, 10000000, 100000000); + +DROP TABLE IF EXISTS `01746_buffer_mv`; +CREATE MATERIALIZED VIEW `01746_buffer_mv` +ENGINE = Memory AS +SELECT + n1, + n2 +FROM `01746_buffer`; + +ALTER TABLE `01746_buffer` + DROP COLUMN n1; -- { serverError 524 } + +ALTER TABLE `01746_buffer` + DROP COLUMN n2; -- { serverError 524 } + +-- ok +ALTER TABLE `01746_buffer` + DROP COLUMN n3; + +DROP TABLE `01746_buffer_t`; +DROP TABLE `01746_buffer`; +DROP TABLE `01746_buffer_mv`; diff --git a/tests/queries/0_stateless/01746_lc_values_format_bug.reference b/tests/queries/0_stateless/01746_lc_values_format_bug.reference new file mode 100644 index 00000000000..78981922613 --- /dev/null +++ b/tests/queries/0_stateless/01746_lc_values_format_bug.reference @@ -0,0 +1 @@ +a diff --git a/tests/queries/0_stateless/01746_lc_values_format_bug.sql b/tests/queries/0_stateless/01746_lc_values_format_bug.sql new file mode 100644 index 00000000000..6717b9ae5e3 --- /dev/null +++ b/tests/queries/0_stateless/01746_lc_values_format_bug.sql @@ -0,0 +1,14 @@ +drop table if exists lc_test; + +CREATE TABLE lc_test +( + `id` LowCardinality(String) +) +ENGINE = MergeTree +PARTITION BY tuple() +ORDER BY id; + +insert into lc_test values (toString('a')); + +select id from lc_test; +drop table if exists lc_test; diff --git a/tests/queries/0_stateless/01746_long_zlib_http_compression_json_format.reference b/tests/queries/0_stateless/01746_long_zlib_http_compression_json_format.reference new file mode 100644 index 00000000000..7c089a2fd05 --- /dev/null +++ b/tests/queries/0_stateless/01746_long_zlib_http_compression_json_format.reference @@ -0,0 +1,23 @@ + }, + { + "datetime": "2020-12-12", + "pipeline": "test-pipeline", + "host": "clickhouse-test-host-001.clickhouse.com", + "home": "clickhouse", + "detail": "clickhouse", + "row_number": "999998" + }, + { + "datetime": "2020-12-12", + "pipeline": "test-pipeline", + "host": "clickhouse-test-host-001.clickhouse.com", + "home": "clickhouse", + "detail": "clickhouse", + "row_number": "999999" + } + ], + + "rows": 1000000, + + "rows_before_limit_at_least": 1048080, + diff --git a/tests/queries/0_stateless/01746_long_zlib_http_compression_json_format.sh b/tests/queries/0_stateless/01746_long_zlib_http_compression_json_format.sh new file mode 100755 index 00000000000..e663b329660 --- /dev/null +++ b/tests/queries/0_stateless/01746_long_zlib_http_compression_json_format.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +${CLICKHOUSE_CURL} -sS -H 'Accept-Encoding: gzip' "${CLICKHOUSE_URL}&enable_http_compression=1&http_zlib_compression_level=1" -d "SELECT toDate('2020-12-12') as datetime, 'test-pipeline' as pipeline, 'clickhouse-test-host-001.clickhouse.com' as host, 'clickhouse' as home, 'clickhouse' as detail, number as row_number FROM numbers(1000000) FORMAT JSON" | gzip -d | tail -n30 | head -n23 diff --git a/tests/queries/0_stateless/01746_long_zstd_http_compression_json_format.reference b/tests/queries/0_stateless/01746_long_zstd_http_compression_json_format.reference new file mode 100644 index 00000000000..7c089a2fd05 --- /dev/null +++ b/tests/queries/0_stateless/01746_long_zstd_http_compression_json_format.reference @@ -0,0 +1,23 @@ + }, + { + "datetime": "2020-12-12", + "pipeline": "test-pipeline", + "host": "clickhouse-test-host-001.clickhouse.com", + "home": "clickhouse", + "detail": "clickhouse", + "row_number": "999998" + }, + { + "datetime": "2020-12-12", + "pipeline": "test-pipeline", + "host": "clickhouse-test-host-001.clickhouse.com", + "home": "clickhouse", + "detail": "clickhouse", + "row_number": "999999" + } + ], + + "rows": 1000000, + + "rows_before_limit_at_least": 1048080, + diff --git a/tests/queries/0_stateless/01746_long_zstd_http_compression_json_format.sh b/tests/queries/0_stateless/01746_long_zstd_http_compression_json_format.sh new file mode 100755 index 00000000000..f520a21e9b3 --- /dev/null +++ b/tests/queries/0_stateless/01746_long_zstd_http_compression_json_format.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +${CLICKHOUSE_CURL} -sS -H 'Accept-Encoding: zstd' "${CLICKHOUSE_URL}&enable_http_compression=1" -d "SELECT toDate('2020-12-12') as datetime, 'test-pipeline' as pipeline, 'clickhouse-test-host-001.clickhouse.com' as host, 'clickhouse' as home, 'clickhouse' as detail, number as row_number FROM numbers(1000000) FORMAT JSON" | zstd -d | tail -n30 | head -n23 diff --git a/tests/queries/0_stateless/01746_test_for_tupleElement_must_be_constant_issue.reference b/tests/queries/0_stateless/01746_test_for_tupleElement_must_be_constant_issue.reference new file mode 100644 index 00000000000..6592226b0ac --- /dev/null +++ b/tests/queries/0_stateless/01746_test_for_tupleElement_must_be_constant_issue.reference @@ -0,0 +1,2 @@ +[('a',10)] +[('a',10)] diff --git a/tests/queries/0_stateless/01746_test_for_tupleElement_must_be_constant_issue.sql b/tests/queries/0_stateless/01746_test_for_tupleElement_must_be_constant_issue.sql new file mode 100644 index 00000000000..72ba6a036df --- /dev/null +++ b/tests/queries/0_stateless/01746_test_for_tupleElement_must_be_constant_issue.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS ttt01746; +CREATE TABLE ttt01746 (d Date, n UInt64) ENGINE = MergeTree() PARTITION BY toMonday(d) ORDER BY n; +INSERT INTO ttt01746 SELECT toDate('2021-02-14') + (number % 30) AS d, number AS n FROM numbers(1500000); +set optimize_move_to_prewhere=0; +SELECT arraySort(x -> x.2, [tuple('a', 10)]) AS X FROM ttt01746 WHERE d >= toDate('2021-03-03') - 2 ORDER BY n LIMIT 1; +SELECT arraySort(x -> x.2, [tuple('a', 10)]) AS X FROM ttt01746 PREWHERE d >= toDate('2021-03-03') - 2 ORDER BY n LIMIT 1; +DROP TABLE ttt01746; diff --git a/tests/queries/0_stateless/01747_alter_partition_key_enum_zookeeper.reference b/tests/queries/0_stateless/01747_alter_partition_key_enum_zookeeper.reference new file mode 100644 index 00000000000..02359f0f98b --- /dev/null +++ b/tests/queries/0_stateless/01747_alter_partition_key_enum_zookeeper.reference @@ -0,0 +1,6 @@ +IU lada 2101 1970-04-19 15:00:00 +PS jeep Grand Cherokee 2005-10-03 15:00:00 +PS jeep Grand Cherokee 2005-10-03 15:00:00 +IU lada 2101 1970-04-19 15:00:00 +PS jeep Grand Cherokee 2005-10-03 15:00:00 +PS jeep Grand Cherokee 2005-10-03 15:00:00 diff --git a/tests/queries/0_stateless/01747_alter_partition_key_enum_zookeeper.sql b/tests/queries/0_stateless/01747_alter_partition_key_enum_zookeeper.sql new file mode 100644 index 00000000000..759c8ba3a0b --- /dev/null +++ b/tests/queries/0_stateless/01747_alter_partition_key_enum_zookeeper.sql @@ -0,0 +1,63 @@ +DROP TABLE IF EXISTS report; + +CREATE TABLE report +( + `product` Enum8('IU' = 1, 'WS' = 2), + `machine` String, + `branch` String, + `generated_time` DateTime +) +ENGINE = MergeTree +PARTITION BY (product, toYYYYMM(generated_time)) +ORDER BY (product, machine, branch, generated_time); + +INSERT INTO report VALUES ('IU', 'lada', '2101', toDateTime('1970-04-19 15:00:00')); + +SELECT * FROM report WHERE product = 'IU'; + +ALTER TABLE report MODIFY COLUMN product Enum8('IU' = 1, 'WS' = 2, 'PS' = 3); + +SELECT * FROM report WHERE product = 'PS'; + +INSERT INTO report VALUES ('PS', 'jeep', 'Grand Cherokee', toDateTime('2005-10-03 15:00:00')); + +SELECT * FROM report WHERE product = 'PS'; + +DETACH TABLE report; +ATTACH TABLE report; + +SELECT * FROM report WHERE product = 'PS'; + +DROP TABLE IF EXISTS report; + +DROP TABLE IF EXISTS replicated_report; + +CREATE TABLE replicated_report +( + `product` Enum8('IU' = 1, 'WS' = 2), + `machine` String, + `branch` String, + `generated_time` DateTime +) +ENGINE = ReplicatedMergeTree('/clickhouse/01747_alter_partition_key/t', '1') +PARTITION BY (product, toYYYYMM(generated_time)) +ORDER BY (product, machine, branch, generated_time); + +INSERT INTO replicated_report VALUES ('IU', 'lada', '2101', toDateTime('1970-04-19 15:00:00')); + +SELECT * FROM replicated_report WHERE product = 'IU'; + +ALTER TABLE replicated_report MODIFY COLUMN product Enum8('IU' = 1, 'WS' = 2, 'PS' = 3) SETTINGS replication_alter_partitions_sync=2; + +SELECT * FROM replicated_report WHERE product = 'PS'; + +INSERT INTO replicated_report VALUES ('PS', 'jeep', 'Grand Cherokee', toDateTime('2005-10-03 15:00:00')); + +SELECT * FROM replicated_report WHERE product = 'PS'; + +DETACH TABLE replicated_report; +ATTACH TABLE replicated_report; + +SELECT * FROM replicated_report WHERE product = 'PS'; + +DROP TABLE IF EXISTS replicated_report; diff --git a/tests/queries/0_stateless/01747_executable_pool_dictionary_implicit_key.reference b/tests/queries/0_stateless/01747_executable_pool_dictionary_implicit_key.reference new file mode 100644 index 00000000000..ab44ba51330 --- /dev/null +++ b/tests/queries/0_stateless/01747_executable_pool_dictionary_implicit_key.reference @@ -0,0 +1,10 @@ +executable_pool_simple_implicit_key +1 a +1 b +2 a +2 b +executable_pool_complex_implicit_key +data a +data b +data a +data b diff --git a/tests/queries/0_stateless/01747_executable_pool_dictionary_implicit_key.sql b/tests/queries/0_stateless/01747_executable_pool_dictionary_implicit_key.sql new file mode 100644 index 00000000000..6c6d33c7d43 --- /dev/null +++ b/tests/queries/0_stateless/01747_executable_pool_dictionary_implicit_key.sql @@ -0,0 +1,15 @@ +SELECT 'executable_pool_simple_implicit_key'; + +SELECT dictGet('executable_pool_simple_implicit_key', 'a', toUInt64(1)); +SELECT dictGet('executable_pool_simple_implicit_key', 'b', toUInt64(1)); + +SELECT dictGet('executable_pool_simple_implicit_key', 'a', toUInt64(2)); +SELECT dictGet('executable_pool_simple_implicit_key', 'b', toUInt64(2)); + +SELECT 'executable_pool_complex_implicit_key'; + +SELECT dictGet('executable_pool_complex_implicit_key', 'a', ('First_1', 'Second_1')); +SELECT dictGet('executable_pool_complex_implicit_key', 'b', ('First_1', 'Second_1')); + +SELECT dictGet('executable_pool_complex_implicit_key', 'a', ('First_2', 'Second_2')); +SELECT dictGet('executable_pool_complex_implicit_key', 'b', ('First_2', 'Second_2')); diff --git a/tests/queries/0_stateless/01747_join_view_filter_dictionary.reference b/tests/queries/0_stateless/01747_join_view_filter_dictionary.reference new file mode 100644 index 00000000000..24ed2375adf --- /dev/null +++ b/tests/queries/0_stateless/01747_join_view_filter_dictionary.reference @@ -0,0 +1,2 @@ +name test 33 1.2 +33 diff --git a/tests/queries/0_stateless/01747_join_view_filter_dictionary.sql b/tests/queries/0_stateless/01747_join_view_filter_dictionary.sql new file mode 100644 index 00000000000..b43fa336485 --- /dev/null +++ b/tests/queries/0_stateless/01747_join_view_filter_dictionary.sql @@ -0,0 +1,49 @@ +drop table if exists summing_table01747; +drop view if exists rates01747; +drop view if exists agg_view01747; +drop table if exists dictst01747; +drop DICTIONARY if exists default.dict01747; + +CREATE TABLE summing_table01747 + ( + some_name String, + user_id UInt64, + amount Int64, + currency String + ) +ENGINE = SummingMergeTree() +ORDER BY (some_name); + +CREATE VIEW rates01747 AS + SELECT 'USD' as from_currency, 'EUR' as to_currency, 1.2 as rates01747; + +insert into summing_table01747 values ('name', 2, 20, 'USD'),('name', 1, 10, 'USD'); + +create table dictst01747(some_name String, field1 String, field2 UInt8) Engine = Memory +as select 'name', 'test', 33; + +CREATE DICTIONARY default.dict01747 (some_name String, field1 String, field2 UInt8) +PRIMARY KEY some_name SOURCE(CLICKHOUSE(HOST 'localhost' PORT 9000 +TABLE dictst01747 DB currentDatabase() USER 'default')) +LIFETIME(MIN 0 MAX 0) LAYOUT(COMPLEX_KEY_HASHED()); + + +CREATE VIEW agg_view01747 AS + SELECT + summing_table01747.some_name as some_name, + dictGet('default.dict01747', 'field1', tuple(some_name)) as field1, + dictGet('default.dict01747', 'field2', tuple(some_name)) as field2, + rates01747.rates01747 as rates01747 + FROM summing_table01747 + ANY LEFT JOIN rates01747 + ON rates01747.from_currency = summing_table01747.currency; + +select * from agg_view01747; + +SELECT field2 FROM agg_view01747 WHERE field1 = 'test'; + +drop table summing_table01747; +drop view rates01747; +drop view agg_view01747; +drop table dictst01747; +drop DICTIONARY default.dict01747; diff --git a/tests/queries/0_stateless/01747_transform_empty_arrays.reference b/tests/queries/0_stateless/01747_transform_empty_arrays.reference new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/tests/queries/0_stateless/01747_transform_empty_arrays.reference @@ -0,0 +1 @@ +1 diff --git a/tests/queries/0_stateless/01747_transform_empty_arrays.sql b/tests/queries/0_stateless/01747_transform_empty_arrays.sql new file mode 100644 index 00000000000..cc9a00a4555 --- /dev/null +++ b/tests/queries/0_stateless/01747_transform_empty_arrays.sql @@ -0,0 +1,27 @@ +SELECT * +FROM +( + WITH + + ( + SELECT groupArray(a) + FROM + ( + SELECT 1 AS a + ) + ) AS keys, + + ( + SELECT groupArray(a) + FROM + ( + SELECT 2 AS a + ) + ) AS values + SELECT * + FROM + ( + SELECT 1 AS a + ) + WHERE transform(a, keys, values, 0) +) AS wrap; diff --git a/tests/queries/0_stateless/01748_dictionary_table_dot.reference b/tests/queries/0_stateless/01748_dictionary_table_dot.reference new file mode 100644 index 00000000000..e965047ad7c --- /dev/null +++ b/tests/queries/0_stateless/01748_dictionary_table_dot.reference @@ -0,0 +1 @@ +Hello diff --git a/tests/queries/0_stateless/01748_dictionary_table_dot.sql b/tests/queries/0_stateless/01748_dictionary_table_dot.sql new file mode 100644 index 00000000000..a974786f446 --- /dev/null +++ b/tests/queries/0_stateless/01748_dictionary_table_dot.sql @@ -0,0 +1,34 @@ +DROP DATABASE IF EXISTS test_01748; +CREATE DATABASE test_01748; +USE test_01748; + +DROP TABLE IF EXISTS `test.txt`; +DROP DICTIONARY IF EXISTS test_dict; + +CREATE TABLE `test.txt` +( + `key1` UInt32, + `key2` UInt32, + `value` String +) +ENGINE = Memory(); + +CREATE DICTIONARY test_dict +( + `key1` UInt32, + `key2` UInt32, + `value` String +) +PRIMARY KEY key1, key2 +SOURCE(CLICKHOUSE(HOST 'localhost' PORT 9000 USER 'default' TABLE `test.txt` PASSWORD '' DB currentDatabase())) +LIFETIME(MIN 1 MAX 3600) +LAYOUT(COMPLEX_KEY_HASHED()); + +INSERT INTO `test.txt` VALUES (1, 2, 'Hello'); + +-- TODO: it does not work without fully qualified name. +SYSTEM RELOAD DICTIONARY test_01748.test_dict; + +SELECT dictGet(test_dict, 'value', (toUInt32(1), toUInt32(2))); + +DROP DATABASE test_01748; diff --git a/tests/queries/0_stateless/01750_parsing_exception.reference b/tests/queries/0_stateless/01750_parsing_exception.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01750_parsing_exception.sh b/tests/queries/0_stateless/01750_parsing_exception.sh new file mode 100755 index 00000000000..cd50d769f6d --- /dev/null +++ b/tests/queries/0_stateless/01750_parsing_exception.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +# if it will not match, the exit code of grep will be non-zero and the test will fail +$CLICKHOUSE_CLIENT -q "SELECT toDateTime(format('{}-{}-01 00:00:00', '2021', '1'))" |& grep -F -q 'Cannot parse datetime 2021-1-01 00:00:00: Cannot parse DateTime from String:' diff --git a/tests/queries/0_stateless/01752_distributed_query_sigsegv.reference b/tests/queries/0_stateless/01752_distributed_query_sigsegv.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01752_distributed_query_sigsegv.sql b/tests/queries/0_stateless/01752_distributed_query_sigsegv.sql new file mode 100644 index 00000000000..a6936aec913 --- /dev/null +++ b/tests/queries/0_stateless/01752_distributed_query_sigsegv.sql @@ -0,0 +1,8 @@ +-- this is enough to trigger the regression +SELECT throwIf(dummy = 0) FROM remote('127.1', system.one); -- { serverError 395 } + +-- these are just in case +SELECT throwIf(dummy = 0) FROM remote('127.{1,2}', system.one); -- { serverError 395 } +SELECT throwIf(dummy = 0) FROM remote('127.{1,2}', system.one) SETTINGS prefer_localhost_replica=0; -- { serverError 395 } +SELECT throwIf(dummy = 0) FROM remote('127.{1,2}', system.one) SETTINGS prefer_localhost_replica=0, distributed_group_by_no_merge=1; -- { serverError 395 } +SELECT throwIf(dummy = 0) FROM remote('127.{1,2}', system.one) SETTINGS prefer_localhost_replica=0, distributed_group_by_no_merge=2; -- { serverError 395 } diff --git a/tests/queries/0_stateless/01753_direct_dictionary_simple_key.reference b/tests/queries/0_stateless/01753_direct_dictionary_simple_key.reference new file mode 100644 index 00000000000..1d3a43b59fb --- /dev/null +++ b/tests/queries/0_stateless/01753_direct_dictionary_simple_key.reference @@ -0,0 +1,66 @@ +Dictionary direct_dictionary_simple_key_simple_attributes +dictGet existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 value_0 value_second_0 +1 value_1 value_second_1 +2 value_2 value_second_2 +Dictionary direct_dictionary_simple_key_complex_attributes +dictGet existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 value_0 value_second_0 +1 value_1 \N +2 value_2 value_second_2 +Dictionary direct_dictionary_simple_key_hierarchy +dictGet +0 +0 +1 +1 +2 +dictGetHierarchy +[1] +[4,2,1] diff --git a/tests/queries/0_stateless/01753_direct_dictionary_simple_key.sql b/tests/queries/0_stateless/01753_direct_dictionary_simple_key.sql new file mode 100644 index 00000000000..afd91ffdaa5 --- /dev/null +++ b/tests/queries/0_stateless/01753_direct_dictionary_simple_key.sql @@ -0,0 +1,120 @@ +DROP DATABASE IF EXISTS 01753_dictionary_db; +CREATE DATABASE 01753_dictionary_db; + +CREATE TABLE 01753_dictionary_db.simple_key_simple_attributes_source_table +( + id UInt64, + value_first String, + value_second String +) +ENGINE = TinyLog; + +INSERT INTO 01753_dictionary_db.simple_key_simple_attributes_source_table VALUES(0, 'value_0', 'value_second_0'); +INSERT INTO 01753_dictionary_db.simple_key_simple_attributes_source_table VALUES(1, 'value_1', 'value_second_1'); +INSERT INTO 01753_dictionary_db.simple_key_simple_attributes_source_table VALUES(2, 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01753_dictionary_db.direct_dictionary_simple_key_simple_attributes +( + id UInt64, + value_first String DEFAULT 'value_first_default', + value_second String DEFAULT 'value_second_default' +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_simple_attributes_source_table')) +LAYOUT(DIRECT()); + +SELECT 'Dictionary direct_dictionary_simple_key_simple_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01753_dictionary_db.direct_dictionary_simple_key_simple_attributes', 'value_first', number) as value_first, + dictGet('01753_dictionary_db.direct_dictionary_simple_key_simple_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01753_dictionary_db.direct_dictionary_simple_key_simple_attributes', 'value_first', number) as value_first, + dictGet('01753_dictionary_db.direct_dictionary_simple_key_simple_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01753_dictionary_db.direct_dictionary_simple_key_simple_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01753_dictionary_db.direct_dictionary_simple_key_simple_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01753_dictionary_db.direct_dictionary_simple_key_simple_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01753_dictionary_db.direct_dictionary_simple_key_simple_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01753_dictionary_db.direct_dictionary_simple_key_simple_attributes', number) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01753_dictionary_db.direct_dictionary_simple_key_simple_attributes; + +DROP DICTIONARY 01753_dictionary_db.direct_dictionary_simple_key_simple_attributes; +DROP TABLE 01753_dictionary_db.simple_key_simple_attributes_source_table; + +CREATE TABLE 01753_dictionary_db.simple_key_complex_attributes_source_table +( + id UInt64, + value_first String, + value_second Nullable(String) +) +ENGINE = TinyLog; + +INSERT INTO 01753_dictionary_db.simple_key_complex_attributes_source_table VALUES(0, 'value_0', 'value_second_0'); +INSERT INTO 01753_dictionary_db.simple_key_complex_attributes_source_table VALUES(1, 'value_1', NULL); +INSERT INTO 01753_dictionary_db.simple_key_complex_attributes_source_table VALUES(2, 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01753_dictionary_db.direct_dictionary_simple_key_complex_attributes +( + id UInt64, + value_first String DEFAULT 'value_first_default', + value_second Nullable(String) DEFAULT 'value_second_default' +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_complex_attributes_source_table')) +LAYOUT(DIRECT()); + +SELECT 'Dictionary direct_dictionary_simple_key_complex_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01753_dictionary_db.direct_dictionary_simple_key_complex_attributes', 'value_first', number) as value_first, + dictGet('01753_dictionary_db.direct_dictionary_simple_key_complex_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01753_dictionary_db.direct_dictionary_simple_key_complex_attributes', 'value_first', number) as value_first, + dictGet('01753_dictionary_db.direct_dictionary_simple_key_complex_attributes', 'value_second', number) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01753_dictionary_db.direct_dictionary_simple_key_complex_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01753_dictionary_db.direct_dictionary_simple_key_complex_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01753_dictionary_db.direct_dictionary_simple_key_complex_attributes', 'value_first', number, toString('default')) as value_first, + dictGetOrDefault('01753_dictionary_db.direct_dictionary_simple_key_complex_attributes', 'value_second', number, toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01753_dictionary_db.direct_dictionary_simple_key_complex_attributes', number) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01753_dictionary_db.direct_dictionary_simple_key_complex_attributes; + +DROP DICTIONARY 01753_dictionary_db.direct_dictionary_simple_key_complex_attributes; +DROP TABLE 01753_dictionary_db.simple_key_complex_attributes_source_table; + +CREATE TABLE 01753_dictionary_db.simple_key_hierarchy_table +( + id UInt64, + parent_id UInt64 +) ENGINE = TinyLog(); + +INSERT INTO 01753_dictionary_db.simple_key_hierarchy_table VALUES (1, 0); +INSERT INTO 01753_dictionary_db.simple_key_hierarchy_table VALUES (2, 1); +INSERT INTO 01753_dictionary_db.simple_key_hierarchy_table VALUES (3, 1); +INSERT INTO 01753_dictionary_db.simple_key_hierarchy_table VALUES (4, 2); + +CREATE DICTIONARY 01753_dictionary_db.direct_dictionary_simple_key_hierarchy +( + id UInt64, + parent_id UInt64 HIERARCHICAL +) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'simple_key_hierarchy_table')) +LAYOUT(DIRECT()); + +SELECT 'Dictionary direct_dictionary_simple_key_hierarchy'; +SELECT 'dictGet'; +SELECT dictGet('01753_dictionary_db.direct_dictionary_simple_key_hierarchy', 'parent_id', number) FROM system.numbers LIMIT 5; +SELECT 'dictGetHierarchy'; +SELECT dictGetHierarchy('01753_dictionary_db.direct_dictionary_simple_key_hierarchy', toUInt64(1)); +SELECT dictGetHierarchy('01753_dictionary_db.direct_dictionary_simple_key_hierarchy', toUInt64(4)); + +DROP DICTIONARY 01753_dictionary_db.direct_dictionary_simple_key_hierarchy; +DROP TABLE 01753_dictionary_db.simple_key_hierarchy_table; + +DROP DATABASE 01753_dictionary_db; diff --git a/tests/queries/0_stateless/01753_fix_clickhouse_format.reference b/tests/queries/0_stateless/01753_fix_clickhouse_format.reference new file mode 100644 index 00000000000..0aad4d64c55 --- /dev/null +++ b/tests/queries/0_stateless/01753_fix_clickhouse_format.reference @@ -0,0 +1,25 @@ +SELECT 1 +; + +SELECT 1 +UNION ALL +( + SELECT 1 + UNION DISTINCT + SELECT 1 +) +; + +SELECT 1 +; + +SELECT 1 +UNION ALL +( + SELECT 1 + UNION DISTINCT + SELECT 1 +) +; + +OK diff --git a/tests/queries/0_stateless/01753_fix_clickhouse_format.sh b/tests/queries/0_stateless/01753_fix_clickhouse_format.sh new file mode 100755 index 00000000000..5cdd53b2166 --- /dev/null +++ b/tests/queries/0_stateless/01753_fix_clickhouse_format.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +echo "select 1; select 1 union all (select 1 union distinct select 1); " | $CLICKHOUSE_FORMAT -n; + +echo "select 1; select 1 union all (select 1 union distinct select 1); -- comment " | $CLICKHOUSE_FORMAT -n; + +echo "insert into t values (1); " | $CLICKHOUSE_FORMAT -n 2>&1 \ | grep -F -q "Code: 578" && echo 'OK' || echo 'FAIL' diff --git a/tests/queries/0_stateless/01753_mutate_table_predicated_with_table.reference b/tests/queries/0_stateless/01753_mutate_table_predicated_with_table.reference new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/tests/queries/0_stateless/01753_mutate_table_predicated_with_table.reference @@ -0,0 +1 @@ +1 diff --git a/tests/queries/0_stateless/01753_mutate_table_predicated_with_table.sql b/tests/queries/0_stateless/01753_mutate_table_predicated_with_table.sql new file mode 100644 index 00000000000..efb444eb4b1 --- /dev/null +++ b/tests/queries/0_stateless/01753_mutate_table_predicated_with_table.sql @@ -0,0 +1,12 @@ +DROP TABLE IF EXISTS mmm; + +CREATE TABLE mmm ENGINE=MergeTree ORDER BY number +AS SELECT number, rand() % 10 AS a FROM numbers(1000); + +ALTER TABLE mmm DELETE WHERE a IN (SELECT a FROM mmm) SETTINGS mutations_sync=1; + +SELECT is_done FROM system.mutations WHERE table = 'mmm' and database=currentDatabase(); + +SELECT * FROM mmm; + +DROP TABLE IF EXISTS mmm; diff --git a/tests/queries/0_stateless/01753_optimize_aggregation_in_order.reference b/tests/queries/0_stateless/01753_optimize_aggregation_in_order.reference new file mode 100644 index 00000000000..0cfbf08886f --- /dev/null +++ b/tests/queries/0_stateless/01753_optimize_aggregation_in_order.reference @@ -0,0 +1 @@ +2 diff --git a/tests/queries/0_stateless/01753_optimize_aggregation_in_order.sh b/tests/queries/0_stateless/01753_optimize_aggregation_in_order.sh new file mode 100755 index 00000000000..2a7345f4865 --- /dev/null +++ b/tests/queries/0_stateless/01753_optimize_aggregation_in_order.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +CLICKHOUSE_CLIENT_SERVER_LOGS_LEVEL=trace + +CUR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CUR_DIR"/../shell_config.sh + +$CLICKHOUSE_CLIENT --optimize_aggregation_in_order=1 -nm -q " +drop table if exists data_01753; +create table data_01753 (key Int) engine=MergeTree() order by key as select * from numbers(8); +select * from data_01753 group by key settings max_block_size=1; +select * from data_01753 group by key settings max_block_size=1; +drop table data_01753; +" |& grep -F -c 'AggregatingInOrderTransform: Aggregated. 8 to 8 rows' diff --git a/tests/queries/0_stateless/01754_clickhouse_format_backslash.reference b/tests/queries/0_stateless/01754_clickhouse_format_backslash.reference new file mode 100644 index 00000000000..328483d9867 --- /dev/null +++ b/tests/queries/0_stateless/01754_clickhouse_format_backslash.reference @@ -0,0 +1,16 @@ +SELECT * \ +FROM \ +( \ + SELECT 1 AS x \ + UNION ALL \ + SELECT 1 \ + UNION DISTINCT \ + SELECT 3 \ +) +SELECT 1 \ +UNION ALL \ +( \ + SELECT 1 \ + UNION DISTINCT \ + SELECT 1 \ +) diff --git a/tests/queries/0_stateless/01754_clickhouse_format_backslash.sh b/tests/queries/0_stateless/01754_clickhouse_format_backslash.sh new file mode 100755 index 00000000000..6a76dc9c5c8 --- /dev/null +++ b/tests/queries/0_stateless/01754_clickhouse_format_backslash.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CURDIR"/../shell_config.sh + +echo "select * from (select 1 as x union all select 1 union distinct select 3)" | $CLICKHOUSE_FORMAT --backslash; + +echo "select 1 union all (select 1 union distinct select 1)" | $CLICKHOUSE_FORMAT --backslash; diff --git a/tests/queries/0_stateless/01754_direct_dictionary_complex_key.reference b/tests/queries/0_stateless/01754_direct_dictionary_complex_key.reference new file mode 100644 index 00000000000..603785e984c --- /dev/null +++ b/tests/queries/0_stateless/01754_direct_dictionary_complex_key.reference @@ -0,0 +1,56 @@ +Dictionary direct_dictionary_complex_key_simple_attributes +dictGet existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 value_second_1 +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 id_key_0 value_0 value_second_0 +1 id_key_1 value_1 value_second_1 +2 id_key_2 value_2 value_second_2 +Dictionary direct_dictionary_complex_key_complex_attributes +dictGet existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGet with non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +value_first_default value_second_default +dictGetOrDefault existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +dictGetOrDefault non existing value +value_0 value_second_0 +value_1 \N +value_2 value_second_2 +default default +dictHas +1 +1 +1 +0 +select all values as input stream +0 id_key_0 value_0 value_second_0 +1 id_key_1 value_1 \N +2 id_key_2 value_2 value_second_2 diff --git a/tests/queries/0_stateless/01754_direct_dictionary_complex_key.sql b/tests/queries/0_stateless/01754_direct_dictionary_complex_key.sql new file mode 100644 index 00000000000..51b29457011 --- /dev/null +++ b/tests/queries/0_stateless/01754_direct_dictionary_complex_key.sql @@ -0,0 +1,95 @@ +DROP DATABASE IF EXISTS 01754_dictionary_db; +CREATE DATABASE 01754_dictionary_db; + +CREATE TABLE 01754_dictionary_db.complex_key_simple_attributes_source_table +( + id UInt64, + id_key String, + value_first String, + value_second String +) +ENGINE = TinyLog; + +INSERT INTO 01754_dictionary_db.complex_key_simple_attributes_source_table VALUES(0, 'id_key_0', 'value_0', 'value_second_0'); +INSERT INTO 01754_dictionary_db.complex_key_simple_attributes_source_table VALUES(1, 'id_key_1', 'value_1', 'value_second_1'); +INSERT INTO 01754_dictionary_db.complex_key_simple_attributes_source_table VALUES(2, 'id_key_2', 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01754_dictionary_db.direct_dictionary_complex_key_simple_attributes +( + id UInt64, + id_key String DEFAULT 'test_default_id_key', + value_first String DEFAULT 'value_first_default', + value_second String DEFAULT 'value_second_default' +) +PRIMARY KEY id, id_key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'complex_key_simple_attributes_source_table')) +LAYOUT(COMPLEX_KEY_DIRECT()); + +SELECT 'Dictionary direct_dictionary_complex_key_simple_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01754_dictionary_db.direct_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01754_dictionary_db.direct_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01754_dictionary_db.direct_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01754_dictionary_db.direct_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01754_dictionary_db.direct_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01754_dictionary_db.direct_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01754_dictionary_db.direct_dictionary_complex_key_simple_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01754_dictionary_db.direct_dictionary_complex_key_simple_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01754_dictionary_db.direct_dictionary_complex_key_simple_attributes', (number, concat('id_key_', toString(number)))) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01754_dictionary_db.direct_dictionary_complex_key_simple_attributes; + +DROP DICTIONARY 01754_dictionary_db.direct_dictionary_complex_key_simple_attributes; +DROP TABLE 01754_dictionary_db.complex_key_simple_attributes_source_table; + +CREATE TABLE 01754_dictionary_db.complex_key_complex_attributes_source_table +( + id UInt64, + id_key String, + value_first String, + value_second Nullable(String) +) +ENGINE = TinyLog; + +INSERT INTO 01754_dictionary_db.complex_key_complex_attributes_source_table VALUES(0, 'id_key_0', 'value_0', 'value_second_0'); +INSERT INTO 01754_dictionary_db.complex_key_complex_attributes_source_table VALUES(1, 'id_key_1', 'value_1', NULL); +INSERT INTO 01754_dictionary_db.complex_key_complex_attributes_source_table VALUES(2, 'id_key_2', 'value_2', 'value_second_2'); + +CREATE DICTIONARY 01754_dictionary_db.direct_dictionary_complex_key_complex_attributes +( + id UInt64, + id_key String, + + value_first String DEFAULT 'value_first_default', + value_second Nullable(String) DEFAULT 'value_second_default' +) +PRIMARY KEY id, id_key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'complex_key_complex_attributes_source_table')) +LAYOUT(COMPLEX_KEY_DIRECT()); + +SELECT 'Dictionary direct_dictionary_complex_key_complex_attributes'; +SELECT 'dictGet existing value'; +SELECT dictGet('01754_dictionary_db.direct_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01754_dictionary_db.direct_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGet with non existing value'; +SELECT dictGet('01754_dictionary_db.direct_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number)))) as value_first, + dictGet('01754_dictionary_db.direct_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number)))) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictGetOrDefault existing value'; +SELECT dictGetOrDefault('01754_dictionary_db.direct_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01754_dictionary_db.direct_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 3; +SELECT 'dictGetOrDefault non existing value'; +SELECT dictGetOrDefault('01754_dictionary_db.direct_dictionary_complex_key_complex_attributes', 'value_first', (number, concat('id_key_', toString(number))), toString('default')) as value_first, + dictGetOrDefault('01754_dictionary_db.direct_dictionary_complex_key_complex_attributes', 'value_second', (number, concat('id_key_', toString(number))), toString('default')) as value_second FROM system.numbers LIMIT 4; +SELECT 'dictHas'; +SELECT dictHas('01754_dictionary_db.direct_dictionary_complex_key_complex_attributes', (number, concat('id_key_', toString(number)))) FROM system.numbers LIMIT 4; +SELECT 'select all values as input stream'; +SELECT * FROM 01754_dictionary_db.direct_dictionary_complex_key_complex_attributes; + +DROP DICTIONARY 01754_dictionary_db.direct_dictionary_complex_key_complex_attributes; +DROP TABLE 01754_dictionary_db.complex_key_complex_attributes_source_table; + +DROP DATABASE 01754_dictionary_db; diff --git a/tests/queries/0_stateless/01758_optimize_skip_unused_shards_once.reference b/tests/queries/0_stateless/01758_optimize_skip_unused_shards_once.reference new file mode 100644 index 00000000000..d23ada2e8d4 --- /dev/null +++ b/tests/queries/0_stateless/01758_optimize_skip_unused_shards_once.reference @@ -0,0 +1,2 @@ +StorageDistributed (dist_01758): Auto-increment is 0 +StorageDistributed (dist_01758): Skipping irrelevant shards - the query will be sent to the following shards of the cluster (shard numbers): [1] diff --git a/tests/queries/0_stateless/01758_optimize_skip_unused_shards_once.sh b/tests/queries/0_stateless/01758_optimize_skip_unused_shards_once.sh new file mode 100755 index 00000000000..b26961eda8e --- /dev/null +++ b/tests/queries/0_stateless/01758_optimize_skip_unused_shards_once.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +CLICKHOUSE_CLIENT_SERVER_LOGS_LEVEL=trace + +CUR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=../shell_config.sh +. "$CUR_DIR"/../shell_config.sh + +$CLICKHOUSE_CLIENT --optimize_skip_unused_shards=1 -nm -q " +create table dist_01758 as system.one engine=Distributed(test_cluster_two_shards, system, one, dummy); +select * from dist_01758 where dummy = 0 format Null; +" |& grep -o "StorageDistributed (dist_01758).*" diff --git a/tests/queries/0_stateless/01759_dictionary_unique_attribute_names.reference b/tests/queries/0_stateless/01759_dictionary_unique_attribute_names.reference new file mode 100644 index 00000000000..bb08bbbe0b5 --- /dev/null +++ b/tests/queries/0_stateless/01759_dictionary_unique_attribute_names.reference @@ -0,0 +1,3 @@ +0 2 3 +1 5 6 +2 8 9 diff --git a/tests/queries/0_stateless/01759_dictionary_unique_attribute_names.sql b/tests/queries/0_stateless/01759_dictionary_unique_attribute_names.sql new file mode 100644 index 00000000000..11a52976716 --- /dev/null +++ b/tests/queries/0_stateless/01759_dictionary_unique_attribute_names.sql @@ -0,0 +1,32 @@ +DROP DATABASE IF EXISTS 01759_db; +CREATE DATABASE 01759_db; + +DROP TABLE IF EXISTS 01759_db.dictionary_source_table; +CREATE TABLE 01759_db.dictionary_source_table +( + key UInt64, + value1 UInt64, + value2 UInt64 +) +ENGINE = TinyLog; + +INSERT INTO 01759_db.dictionary_source_table VALUES (0, 2, 3), (1, 5, 6), (2, 8, 9); + +DROP DICTIONARY IF EXISTS 01759_db.test_dictionary; + +CREATE DICTIONARY 01759_db.test_dictionary(key UInt64, value1 UInt64, value1 UInt64) +PRIMARY KEY key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'dictionary_source_table' DB '01759_db')) +LAYOUT(COMPLEX_KEY_DIRECT()); -- {serverError 36} + +CREATE DICTIONARY 01759_db.test_dictionary(key UInt64, value1 UInt64, value2 UInt64) +PRIMARY KEY key +SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'dictionary_source_table' DB '01759_db')) +LAYOUT(COMPLEX_KEY_DIRECT()); + +SELECT number, dictGet('01759_db.test_dictionary', 'value1', tuple(number)) as value1, + dictGet('01759_db.test_dictionary', 'value2', tuple(number)) as value2 FROM system.numbers LIMIT 3; + +DROP TABLE 01759_db.dictionary_source_table; + +DROP DATABASE 01759_db; diff --git a/tests/queries/0_stateless/01760_modulo_negative.reference b/tests/queries/0_stateless/01760_modulo_negative.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01760_modulo_negative.sql b/tests/queries/0_stateless/01760_modulo_negative.sql new file mode 100644 index 00000000000..dbea06cc100 --- /dev/null +++ b/tests/queries/0_stateless/01760_modulo_negative.sql @@ -0,0 +1 @@ +SELECT -number % -9223372036854775808 FROM system.numbers; -- { serverError 153 } diff --git a/tests/queries/0_stateless/arcadia_skip_list.txt b/tests/queries/0_stateless/arcadia_skip_list.txt index 38d5d3871f5..25569f95dae 100644 --- a/tests/queries/0_stateless/arcadia_skip_list.txt +++ b/tests/queries/0_stateless/arcadia_skip_list.txt @@ -15,6 +15,7 @@ 00732_base64_functions 00746_hashing_tuples 00751_hashing_ints +00753_distributed_system_columns_and_system_tables 00800_function_java_hash 00800_low_cardinality_distributed_insert 00821_distributed_storage_with_join_on @@ -175,7 +176,7 @@ 01560_timeseriesgroupsum_segfault 00976_ttl_with_old_parts 01584_distributed_buffer_cannot_find_column -01018_ip_dictionary +01018_ip_dictionary_long 01582_distinct_subquery_groupby 01558_ttest 01558_ttest_scipy @@ -189,6 +190,7 @@ 01650_fetch_patition_with_macro_in_zk_path 01651_bugs_from_15889 01655_agg_if_nullable +01658_read_file_to_stringcolumn 01182_materialized_view_different_structure 01660_sum_ubsan 01669_columns_declaration_serde @@ -196,6 +198,9 @@ 01181_db_atomic_drop_on_cluster 01658_test_base64Encode_mysql_compatibility 01659_test_base64Decode_mysql_compatibility +01670_distributed_bytes_to_throw_insert +01674_htm_xml_coarse_parse +01675_distributed_bytes_to_delay_insert 01675_data_type_coroutine 01676_clickhouse_client_autocomplete 01671_aggregate_function_group_bitmap_data @@ -204,3 +209,16 @@ 01683_dist_INSERT_block_structure_mismatch 01702_bitmap_native_integers 01686_event_time_microseconds_part_log +01017_uniqCombined_memory_usage +01747_join_view_filter_dictionary +01748_dictionary_table_dot +00950_dict_get +01683_flat_dictionary +01681_cache_dictionary_simple_key +01682_cache_dictionary_complex_key +01684_ssd_cache_dictionary_simple_key +01685_ssd_cache_dictionary_complex_key +01304_polygons_sym_difference +01305_polygons_union +01306_polygons_intersection +01702_system_query_log diff --git a/tests/queries/0_stateless/country_polygons.tsv b/tests/queries/0_stateless/country_polygons.tsv new file mode 100644 index 00000000000..4fa8313e3cb --- /dev/null +++ b/tests/queries/0_stateless/country_polygons.tsv @@ -0,0 +1,2 @@ +Dhekelia Sovereign Base Area [[(33.905868,35.090882),(33.913619,35.090882),(33.921474,35.080702),(33.914446,35.073054),(33.908245,35.070729),(33.906524,35.069122),(33.906506,35.069105),(33.898116,35.061272),(33.880133,35.073054),(33.874655,35.067525),(33.867627,35.060497),(33.855122,35.053417),(33.841169,35.051092),(33.834865,35.056621),(33.827113,35.061272),(33.813781,35.055794),(33.804375,35.049541),(33.799001,35.038534),(33.822359,35.030059),(33.830214,35.023031),(33.829387,35.001176),(33.829387,35.001172),(33.840342,34.993369),(33.859049,34.991819),(33.859049,34.974662),(33.850471,34.973009),(33.838068,34.963707),(33.84582,34.959728),(33.864423,34.962983),(33.891841,34.958139),(33.8838,34.949123),(33.874522,34.94123),(33.862315,34.937893),(33.847423,34.94245),(33.819672,34.964748),(33.80421,34.972602),(33.781896,34.976212),(33.784945,34.976212),(33.788046,34.976988),(33.7928,34.977763),(33.79435,34.977763),(33.791146,34.982414),(33.786495,34.984687),(33.782568,34.984687),(33.777917,34.984687),(33.77399,34.988666),(33.766135,34.990268),(33.761484,34.990268),(33.75921,34.988666),(33.765411,34.985566),(33.769339,34.983964),(33.770889,34.980088),(33.77554,34.980088),(33.780191,34.979313),(33.780986,34.976338),(33.780935,34.976345),(33.760427,34.979682),(33.717296,34.977769),(33.70152,34.97289),(33.702935,34.987943),(33.711461,34.985566),(33.71544,34.997296),(33.699731,35.002722),(33.69663,35.008975),(33.705312,35.015228),(33.702211,35.022256),(33.685003,35.029284),(33.679444,35.033891),(33.679435,35.033899),(33.675649,35.037036),(33.674099,35.046441),(33.678853,35.055794),(33.69446,35.058171),(33.705312,35.06675),(33.714717,35.06675),(33.719368,35.06277),(33.711461,35.040963),(33.707585,35.029284),(33.718489,35.032385),(33.739677,35.047216),(33.766135,35.03161),(33.77554,35.040188),(33.786495,35.038534),(33.79435,35.040188),(33.798278,35.052642),(33.824012,35.06675),(33.834865,35.063597),(33.842719,35.056621),(33.853571,35.058171),(33.866904,35.06675),(33.871555,35.073054),(33.876929,35.076826),(33.871555,35.085456),(33.871555,35.100236),(33.876206,35.118994),(33.889435,35.118994),(33.891812,35.110468),(33.89884,35.108814),(33.903594,35.099512),(33.905868,35.09636),(33.905868,35.090882)],[(33.742792,35.001233),(33.746689,35.002711),(33.752063,35.004323),(33.752063,35.0144),(33.746151,35.015207),(33.741314,35.013729),(33.740239,35.010101),(33.738761,35.005264),(33.739702,35.002576),(33.742792,35.001233)]] +Kyrgyzstan [[(75.204639,42.84519),(75.271198,42.845758),(75.496611,42.823925),(75.535988,42.827025),(75.555936,42.825217),(75.620428,42.805295),(75.646163,42.806096),(75.675308,42.815372),(75.703833,42.830488),(75.727605,42.848678),(75.73825,42.861571),(75.770599,42.92565),(75.782072,42.933324),(75.797161,42.936192),(75.807059,42.936771),(75.858966,42.939809),(75.898033,42.935701),(75.976582,42.918725),(75.999113,42.91764),(76.064535,42.93397),(76.09058,42.93428),(76.163754,42.921154),(76.254498,42.921154),(76.340487,42.901672),(76.351132,42.902886),(76.370976,42.909604),(76.382965,42.910069),(76.3933,42.905263),(76.404463,42.889244),(76.414074,42.885497),(76.432058,42.88958),(76.461927,42.910999),(76.48053,42.916968),(76.506885,42.914488),(76.558768,42.89821),(76.58502,42.894799),(76.605897,42.898494),(76.644345,42.911129),(76.688786,42.910328),(76.707907,42.913661),(76.74625,42.928879),(76.750385,42.932574),(76.751625,42.937096),(76.753899,42.940765),(76.76134,42.942057),(76.77953,42.939292),(76.785214,42.939654),(76.792966,42.943065),(76.814153,42.961487),(76.83348,42.971745),(76.853427,42.974122),(76.897662,42.974536),(76.93735,42.986034),(76.956884,42.988514),(76.976417,42.98221),(77.089899,42.968154),(77.124005,42.958904),(77.135064,42.951746),(77.163693,42.921981),(77.178679,42.913196),(77.195112,42.910069),(77.21189,42.909944),(77.229632,42.909811),(77.328127,42.897564),(77.36089,42.90454),(77.403265,42.919759),(77.418561,42.922239),(77.43396,42.921412),(77.461762,42.914384),(77.501553,42.914539),(77.520984,42.906917),(77.53845,42.896272),(77.557777,42.888133),(77.574417,42.887848),(77.62692,42.906555),(77.647797,42.909501),(77.71384,42.907589),(77.781226,42.895626),(77.787531,42.889709),(77.791665,42.883043),(77.798176,42.877513),(77.809958,42.871286),(77.83559,42.879839),(77.852229,42.887952),(77.861221,42.89082),(77.883855,42.893223),(77.907006,42.891285),(77.929331,42.885006),(77.986175,42.860202),(78.030616,42.854672),(78.137897,42.861984),(78.183579,42.86015),(78.229777,42.865007),(78.249104,42.862398),(78.290136,42.851442),(78.31122,42.850512),(78.328376,42.855292),(78.364653,42.872526),(78.38553,42.878237),(78.429559,42.880665),(78.496118,42.875601),(78.594303,42.850228),(78.635437,42.832477),(78.669957,42.811161),(78.687114,42.804598),(78.807933,42.79558),(78.888135,42.771215),(78.954281,42.768424),(78.992935,42.757133),(79.030866,42.756151),(79.108794,42.785348),(79.148274,42.790981),(79.173389,42.785632),(79.180831,42.77553),(79.175146,42.737031),(79.176076,42.713931),(79.181864,42.693597),(79.192199,42.674838),(79.206359,42.656467),(79.242119,42.629776),(79.321287,42.602181),(79.353016,42.577299),(79.398388,42.496942),(79.425673,42.469605),(79.47642,42.453973),(79.571918,42.449529),(79.652533,42.461053),(79.696458,42.459838),(79.917943,42.42444),(79.960111,42.403511),(79.97396,42.39147),(80.012098,42.349509),(80.077003,42.305765),(80.110076,42.273338),(80.136534,42.23887),(80.16661,42.208717),(80.210328,42.189519),(80.21653,42.174404),(80.219837,42.141873),(80.224591,42.125569),(80.235133,42.110945),(80.247432,42.098413),(80.256527,42.084357),(80.257561,42.065263),(80.231206,42.033689),(80.181906,42.020976),(79.930862,42.023276),(79.879496,42.013199),(79.842909,42.00183),(79.826786,41.992244),(79.812833,41.97762),(79.803842,41.959998),(79.792576,41.922817),(79.783274,41.905092),(79.747514,41.879745),(79.702969,41.874939),(79.655737,41.875843),(79.610985,41.867626),(79.554658,41.837602),(79.489856,41.819257),(79.410997,41.778588),(79.390844,41.772697),(79.367382,41.772387),(79.30413,41.787554),(79.282323,41.783497),(79.264856,41.774506),(79.217521,41.741226),(79.19592,41.729521),(79.174526,41.722622),(79.127914,41.714302),(79.088743,41.702546),(78.976192,41.6418),(78.915834,41.63317),(78.897437,41.626272),(78.807313,41.578445),(78.672128,41.538448),(78.658278,41.532453),(78.645049,41.52372),(78.637401,41.512868),(78.629133,41.48796),(78.619211,41.478089),(78.583968,41.465997),(78.51038,41.454422),(78.41757,41.400471),(78.377675,41.386622),(78.359899,41.377527),(78.343466,41.362024),(78.339332,41.344041),(78.356901,41.305542),(78.359692,41.287455),(78.34946,41.270402),(78.331477,41.258723),(78.291582,41.240791),(78.275356,41.228854),(78.250345,41.200535),(78.231335,41.172856),(78.204456,41.133718),(78.190503,41.11775),(78.176034,41.105502),(78.074955,41.039512),(78.057178,41.034344),(78.036508,41.036101),(77.997647,41.049795),(77.866699,41.064058),(77.831042,41.062973),(77.797556,41.054704),(77.665574,41.001271),(77.650278,40.997137),(77.631778,40.995793),(77.580721,40.997705),(77.503517,40.981066),(77.474888,40.982047),(77.445226,40.993675),(77.388795,41.011658),(77.332985,41.02065),(77.301152,41.019306),(77.243171,41.005664),(77.118838,41.011658),(77.088555,41.019565),(77.035018,41.040338),(77.007733,41.044214),(76.900143,41.025766),(76.860972,41.013208),(76.834927,40.99352),(76.820871,40.97781),(76.783974,40.957139),(76.766818,40.944685),(76.757413,40.925772),(76.760927,40.9066),(76.768368,40.887014),(76.770848,40.867119),(76.762477,40.847017),(76.746871,40.83446),(76.707286,40.817613),(76.674214,40.795444),(76.647859,40.764851),(76.630805,40.728885),(76.624191,40.627547),(76.62078,40.611321),(76.609411,40.59711),(76.556391,40.56569),(76.531173,40.534995),(76.498927,40.464611),(76.476499,40.436138),(76.449111,40.415519),(76.361984,40.371904),(76.330152,40.348081),(76.313512,40.343327),(76.299353,40.355677),(76.283333,40.417276),(76.273411,40.434122),(76.244162,40.441202),(76.21543,40.416552),(76.185044,40.384203),(76.151351,40.368131),(76.132541,40.371542),(76.095231,40.387355),(76.07611,40.391954),(76.051616,40.390197),(75.962422,40.357331),(75.949297,40.343068),(75.938031,40.326222),(75.921495,40.309117),(75.901858,40.298885),(75.880464,40.295268),(75.858553,40.296353),(75.79375,40.30891),(75.772046,40.31015),(75.750549,40.308342),(75.704454,40.293149),(75.681819,40.291702),(75.664869,40.305706),(75.656291,40.32307),(75.640168,40.367305),(75.638308,40.386115),(75.646369,40.405338),(75.659598,40.419084),(75.669314,40.432365),(75.666936,40.450245),(75.657221,40.461097),(75.629006,40.481303),(75.617947,40.493964),(75.610816,40.512877),(75.605648,40.569411),(75.587665,40.611941),(75.559863,40.63287),(75.523793,40.63318),(75.481832,40.614111),(75.26324,40.480166),(75.253318,40.47598),(75.241536,40.474068),(75.229237,40.470347),(75.223966,40.462441),(75.220142,40.452984),(75.212494,40.444716),(75.19389,40.441254),(75.175287,40.448127),(75.15658,40.458152),(75.13808,40.463888),(75.113172,40.460787),(75.064389,40.443837),(75.039068,40.441099),(75.002378,40.4473),(74.966101,40.459289),(74.879181,40.505074),(74.856443,40.513187),(74.835359,40.511637),(74.832312,40.508116),(74.820063,40.493964),(74.816032,40.48368),(74.815102,40.480114),(74.807041,40.461769),(74.794638,40.440737),(74.787404,40.420738),(74.794638,40.405545),(74.841664,40.372059),(74.853859,40.35883),(74.862128,40.32617),(74.830915,40.319917),(74.746683,40.336505),(74.724668,40.337539),(74.705755,40.331286),(74.654388,40.291547),(74.637645,40.281987),(74.598681,40.266174),(74.565402,40.24695),(74.476622,40.172433),(74.369858,40.105822),(74.333788,40.09373),(74.302885,40.090061),(74.272293,40.093833),(74.237876,40.10391),(74.20315,40.109853),(74.167596,40.10639),(74.13287,40.095332),(74.101244,40.078847),(74.069515,40.067788),(74.003989,40.060812),(73.976704,40.043603),(73.966368,40.033268),(73.957894,40.021434),(73.952106,40.008257),(73.949729,39.993684),(73.944044,39.970068),(73.927301,39.953325),(73.907561,39.937873),(73.893195,39.918133),(73.885443,39.876534),(73.880689,39.86501),(73.872937,39.856845),(73.844102,39.838086),(73.83201,39.82372),(73.823018,39.805685),(73.818574,39.786048),(73.819814,39.766721),(73.829529,39.746981),(73.843068,39.740366),(73.859915,39.737162),(73.879345,39.727912),(73.893505,39.710394),(73.899602,39.689465),(73.904253,39.64647),(73.926784,39.592882),(73.921617,39.582133),(73.899292,39.571539),(73.883066,39.561204),(73.870457,39.546786),(73.859192,39.524255),(73.848029,39.489735),(73.838314,39.475679),(73.820744,39.468186),(73.632642,39.448343),(73.604323,39.459608),(73.512236,39.467411),(73.476889,39.464776),(73.367645,39.443795),(73.343151,39.430669),(73.335503,39.415166),(73.333332,39.40111),(73.326408,39.390878),(73.269357,39.382558),(73.167864,39.355377),(73.136032,39.353465),(73.100995,39.361164),(73.083425,39.367831),(73.071126,39.370725),(73.058414,39.368813),(73.009321,39.348607),(72.994335,39.347832),(72.976765,39.352224),(72.91434,39.362715),(72.893669,39.363903),(72.850468,39.35672),(72.835275,39.356204),(72.65048,39.393772),(72.633737,39.394496),(72.616373,39.390413),(72.606141,39.383489),(72.587021,39.364885),(72.575756,39.359304),(72.559426,39.359562),(72.534104,39.372327),(72.519015,39.375686),(72.50806,39.371965),(72.476744,39.346127),(72.460414,39.344111),(72.443567,39.344783),(72.410701,39.351346),(72.393234,39.350829),(72.355924,39.336101),(72.334117,39.333828),(72.31634,39.328815),(72.304248,39.31357),(72.281407,39.259724),(72.240272,39.189909),(72.228903,39.189237),(72.228668,39.189502),(72.218568,39.20089),(72.209163,39.217297),(72.206476,39.226883),(72.206373,39.234609),(72.203272,39.24081),(72.182395,39.249337),(72.167098,39.258742),(72.158623,39.262617),(72.115525,39.268147),(72.094751,39.275072),(72.08576,39.290109),(72.084106,39.311245),(72.078112,39.336618),(72.06695,39.358477),(72.049793,39.368864),(72.031499,39.366694),(71.996463,39.351863),(71.959152,39.345868),(71.942306,39.339047),(71.843501,39.285045),(71.807017,39.272849),(71.77043,39.269542),(71.751207,39.274245),(71.732913,39.285097),(71.71834,39.301065),(71.710899,39.32096),(71.712966,39.341527),(71.723198,39.353981),(71.736634,39.364575),(71.748106,39.379561),(71.751827,39.399663),(71.749243,39.425502),(71.740251,39.448343),(71.724438,39.459401),(71.704594,39.458988),(71.602792,39.442348),(71.554319,39.444157),(71.512875,39.458833),(71.492101,39.493663),(71.500576,39.509217),(71.526001,39.538156),(71.531375,39.553091),(71.52538,39.569162),(71.510911,39.584148),(71.509654,39.584998),(71.493031,39.596241),(71.459545,39.612105),(71.441251,39.610658),(71.406731,39.598153),(71.378309,39.594173),(71.368543,39.591486),(71.361618,39.587559),(71.347872,39.576242),(71.340586,39.571694),(71.305911,39.557173),(71.291958,39.548957),(71.260074,39.520638),(71.249273,39.514385),(71.236923,39.514488),(71.179975,39.523015),(71.137446,39.521155),(71.095898,39.51237),(71.062928,39.495627),(71.042309,39.467876),(71.027581,39.435217),(71.009288,39.407622),(70.977145,39.394909),(70.949808,39.400749),(70.925159,39.412944),(70.903351,39.420851),(70.884489,39.413874),(70.872242,39.402971),(70.864181,39.400594),(70.855292,39.40173),(70.840099,39.40142),(70.828059,39.398578),(70.797621,39.385349),(70.770129,39.382093),(70.739744,39.386228),(70.713285,39.398423),(70.698092,39.41899),(70.698609,39.431393),(70.703053,39.444725),(70.705431,39.458523),(70.699746,39.472165),(70.690134,39.479193),(70.666725,39.486893),(70.655976,39.493663),(70.655976,39.493714),(70.655925,39.49387),(70.655598,39.494664),(70.635977,39.542497),(70.622128,39.563529),(70.59784,39.577792),(70.58027,39.579549),(70.54358,39.574278),(70.526113,39.575622),(70.513504,39.581513),(70.490973,39.596861),(70.477227,39.601201),(70.459967,39.599548),(70.427618,39.590091),(70.411082,39.587456),(70.40147,39.584768),(70.395372,39.579497),(70.390411,39.57402),(70.384313,39.570867),(70.374288,39.571022),(70.353462,39.575932),(70.343179,39.576862),(70.33026,39.573089),(70.241066,39.522395),(70.223289,39.519088),(70.20603,39.5241),(70.204376,39.538156),(70.215021,39.574071),(70.214814,39.591125),(70.210267,39.609728),(70.200655,39.619495),(70.185204,39.610348),(70.15735,39.563891),(70.148979,39.554279),(70.132442,39.550042),(70.116268,39.554641),(70.08273,39.569782),(70.062266,39.573451),(70.040355,39.573606),(70.019684,39.568594),(70.002734,39.556863),(69.987128,39.539603),(69.978757,39.534436),(69.948629,39.545081),(69.907753,39.548492),(69.830445,39.536244),(69.791585,39.545391),(69.74983,39.563839),(69.710349,39.574071),(69.669421,39.577792),(69.582295,39.573555),(69.564932,39.568129),(69.531445,39.545649),(69.514392,39.537588),(69.496099,39.532575),(69.477288,39.530405),(69.455274,39.530456),(69.412176,39.52503),(69.391454,39.530508),(69.367218,39.549938),(69.361637,39.552884),(69.352025,39.549628),(69.348407,39.543169),(69.345927,39.535366),(69.339726,39.528079),(69.300348,39.515625),(69.286189,39.539707),(69.29115,39.658872),(69.287533,39.677786),(69.280091,39.694271),(69.265932,39.707758),(69.248362,39.719385),(69.233324,39.732666),(69.226296,39.751011),(69.229552,39.790544),(69.240714,39.82894),(69.286447,39.935755),(69.305671,39.968621),(69.310064,39.978646),(69.310322,39.984796),(69.313991,39.986914),(69.32784,39.984744),(69.357296,39.959474),(69.405355,39.896119),(69.501576,39.922474),(69.500439,39.935703),(69.477288,39.968156),(69.478115,39.975029),(69.477288,39.981592),(69.475118,39.987741),(69.471191,39.993684),(69.463129,40.025413),(69.46964,40.050993),(69.485712,40.073731),(69.506331,40.096933),(69.509224,40.103445),(69.513462,40.120705),(69.518009,40.125097),(69.526071,40.123185),(69.536613,40.107889),(69.543021,40.103083),(69.558834,40.101739),(69.575474,40.1036),(69.969558,40.211603),(70.004595,40.208761),(70.14717,40.136983),(70.168822,40.13166),(70.218535,40.134141),(70.241531,40.132745),(70.263494,40.12427),(70.277808,40.112075),(70.290262,40.098174),(70.306282,40.08479),(70.324265,40.077503),(70.359509,40.074041),(70.397646,40.061225),(70.477227,40.052027),(70.502135,40.045981),(70.525493,40.033682),(70.535622,40.015957),(70.520946,39.993736),(70.505029,39.985106),(70.488493,39.978543),(70.473197,39.97012),(70.460226,39.956115),(70.450872,39.937408),(70.44803,39.919993),(70.455627,39.906816),(70.477227,39.900925),(70.485961,39.909606),(70.494177,39.931672),(70.500895,39.940561),(70.512574,39.94516),(70.555052,39.946245),(70.576601,39.952239),(70.5966,39.961955),(70.613963,39.975752),(70.627399,39.993891),(70.635977,40.028514),(70.634737,40.059313),(70.63944,40.084945),(70.66595,40.104168),(70.729822,40.120705),(70.743464,40.127113),(70.782532,40.152589),(70.788733,40.158997),(70.792144,40.161374),(70.797725,40.161942),(70.802686,40.160134),(70.806045,40.157653),(70.806716,40.156155),(70.824906,40.163544),(70.831831,40.168195),(70.845164,40.171813),(70.898545,40.162614),(70.929293,40.170624),(70.962883,40.189693),(70.979522,40.214084),(70.958955,40.238372),(70.995129,40.266587),(71.053213,40.274235),(71.169382,40.26142),(71.201008,40.263848),(71.215115,40.280747),(71.223952,40.302864),(71.239558,40.321106),(71.253821,40.324413),(71.263949,40.318212),(71.272838,40.307722),(71.283225,40.29842),(71.297074,40.293821),(71.313559,40.292684),(71.344926,40.295216),(71.365132,40.294131),(71.396551,40.271548),(71.441355,40.260903),(71.450966,40.248914),(71.458925,40.234134),(71.477115,40.220802),(71.498405,40.210518),(71.521246,40.203749),(71.568272,40.196566),(71.592973,40.198426),(71.601655,40.20995),(71.604032,40.227261),(71.61013,40.246382),(71.62832,40.258887),(71.645993,40.247105),(71.660153,40.224471),(71.667181,40.204162),(71.666871,40.163131),(71.673072,40.147886),(71.693329,40.141117),(71.707178,40.144269),(71.759785,40.168092),(71.775908,40.179926),(71.78676,40.193517),(71.805467,40.225298),(71.836473,40.249172),(71.872956,40.250774),(71.912334,40.243436),(71.951814,40.240904),(71.96339,40.243746),(71.969178,40.244418),(71.977033,40.243074),(71.989021,40.239302),(72.004834,40.237287),(72.01889,40.240026),(72.025402,40.250878),(72.019821,40.258732),(72.013239,40.262072),(72.005971,40.26576),(71.977033,40.276096),(71.958222,40.286534),(71.951091,40.30152),(71.951094,40.301529),(71.956672,40.31568),(72.043178,40.349321),(72.069637,40.369423),(72.084106,40.39738),(72.090101,40.416035),(72.099299,40.426371),(72.165858,40.454431),(72.182705,40.45779),(72.228328,40.459606),(72.235931,40.459909),(72.254225,40.458307),(72.263415,40.452651),(72.26363,40.452519),(72.259599,40.44239),(72.24513,40.438721),(72.228077,40.437533),(72.216501,40.434949),(72.211768,40.425836),(72.211644,40.425596),(72.224356,40.422443),(72.269624,40.424045),(72.284301,40.41986),(72.343418,40.393401),(72.370497,40.38565),(72.394061,40.389422),(72.414422,40.410713),(72.425171,40.435983),(72.426204,40.45934),(72.426096,40.459545),(72.420028,40.471027),(72.415662,40.479287),(72.415585,40.47933),(72.372254,40.503265),(72.363469,40.512309),(72.363467,40.51241),(72.363262,40.523574),(72.36998,40.539852),(72.370083,40.557732),(72.369928,40.557931),(72.348483,40.585379),(72.348509,40.585508),(72.351893,40.601967),(72.381556,40.612148),(72.414835,40.589875),(72.447908,40.560471),(72.476744,40.549567),(72.515294,40.54564),(72.585781,40.508743),(72.625468,40.5105),(72.640868,40.519853),(72.65048,40.532152),(72.655131,40.546363),(72.656474,40.561143),(72.664226,40.577783),(72.682416,40.577679),(72.719209,40.564864),(72.748355,40.575096),(72.760034,40.641758),(72.783908,40.669663),(72.818945,40.681084),(72.890982,40.695088),(72.976765,40.736068),(73.070609,40.762474),(73.118048,40.782938),(73.148641,40.813686),(73.14337,40.833839),(73.143292,40.833853),(73.135042,40.835274),(73.112467,40.839162),(73.053556,40.83632),(73.033299,40.847224),(73.01945,40.8619),(73.00343,40.870168),(72.929429,40.844175),(72.883127,40.819628),(72.870311,40.818181),(72.872998,40.834821),(72.868658,40.864122),(72.830107,40.87208),(72.701226,40.863243),(72.658231,40.867171),(72.619474,40.88009),(72.588468,40.905825),(72.545577,40.956519),(72.52625,40.962204),(72.501445,40.963496),(72.483358,40.970575),(72.483565,40.99352),(72.485219,40.999566),(72.484702,41.004682),(72.481911,41.008816),(72.476744,41.011813),(72.423517,41.01574),(72.395198,41.022045),(72.374321,41.031967),(72.345692,41.06597),(72.33236,41.072843),(72.314066,41.061681),(72.308795,41.054446),(72.297323,41.028143),(72.289778,41.023544),(72.252985,41.019616),(72.195486,41.006358),(72.165135,40.999359),(72.178777,41.023182),(72.185599,41.041062),(72.185599,41.060647),(72.1764,41.112892),(72.174643,41.141418),(72.169889,41.168651),(72.158417,41.187875),(72.132889,41.199295),(72.108497,41.196401),(72.085243,41.184877),(72.063642,41.170201),(72.033773,41.15661),(72.016513,41.163535),(72.001217,41.18002),(71.977033,41.195213),(71.897658,41.184929),(71.871613,41.194489),(71.866342,41.236606),(71.868822,41.279239),(71.863034,41.312208),(71.847015,41.341819),(71.75317,41.44729),(71.745212,41.45282),(71.73684,41.455404),(71.730433,41.451166),(71.729709,41.430082),(71.721648,41.424759),(71.712242,41.428015),(71.706868,41.444086),(71.696119,41.447445),(71.691469,41.441916),(71.687334,41.431012),(71.681443,41.422847),(71.671935,41.425483),(71.671108,41.437627),(71.689505,41.493799),(71.689401,41.514625),(71.68413,41.534055),(71.671418,41.547388),(71.649507,41.54992),(71.62739,41.543202),(71.615297,41.532143),(71.595454,41.493799),(71.595454,41.493747),(71.595557,41.493696),(71.595557,41.493489),(71.605582,41.476849),(71.633694,41.449616),(71.637415,41.431271),(71.633074,41.411324),(71.618811,41.377786),(71.585532,41.323525),(71.557937,41.301718),(71.52383,41.296654),(71.480629,41.310761),(71.432466,41.344816),(71.418772,41.3474),(71.412571,41.334687),(71.421459,41.162088),(71.416085,41.127362),(71.393657,41.112737),(71.325238,41.157334),(71.300226,41.133046),(71.289478,41.113874),(71.276145,41.113151),(71.263381,41.123486),(71.253821,41.13749),(71.241522,41.175162),(71.230153,41.187255),(71.206382,41.188753),(71.185711,41.180227),(71.183024,41.166377),(71.187882,41.148446),(71.189949,41.127465),(71.18013,41.108138),(71.164421,41.116199),(71.139099,41.148394),(71.123079,41.158212),(71.085769,41.162036),(71.067579,41.169736),(71.047012,41.182035),(71.024688,41.189787),(70.977145,41.19635),(70.93415,41.19144),(70.914203,41.193042),(70.895962,41.206116),(70.882164,41.220482),(70.865731,41.233195),(70.847747,41.243065),(70.828524,41.249111),(70.805993,41.247458),(70.786563,41.24043),(70.770439,41.238518),(70.758037,41.25216),(70.75628,41.269627),(70.77106,41.331018),(70.769199,41.352102),(70.759691,41.372515),(70.70357,41.445482),(70.686724,41.462483),(70.66781,41.471372),(70.633807,41.467496),(70.511334,41.414476),(70.477227,41.404657),(70.470782,41.404879),(70.453198,41.405484),(70.438057,41.416078),(70.413614,41.450701),(70.398989,41.464964),(70.382246,41.476436),(70.344936,41.493489),(70.344729,41.493644),(70.344522,41.493696),(70.344419,41.493799),(70.203446,41.505633),(70.166549,41.520206),(70.148255,41.552452),(70.169288,41.578342),(70.33119,41.649629),(70.390824,41.685054),(70.423484,41.696913),(70.453663,41.71208),(70.477227,41.738435),(70.506476,41.78559),(70.550091,41.824063),(70.648948,41.887393),(70.679696,41.901113),(70.779328,41.909665),(70.814003,41.919535),(70.825113,41.93633),(70.828059,41.993743),(70.845474,42.030356),(70.886711,42.038495),(70.935907,42.036867),(70.977145,42.044231),(71.118429,42.122908),(71.201008,42.140788),(71.238215,42.160244),(71.253201,42.197555),(71.249868,42.198385),(71.217854,42.206365),(71.077604,42.281167),(71.045772,42.29096),(71.014042,42.287704),(70.9696,42.263468),(70.947793,42.248146),(70.918648,42.253365),(70.897822,42.261608),(70.858134,42.291063),(70.852657,42.306075),(70.864801,42.321552),(70.888825,42.338575),(70.900354,42.346744),(70.932703,42.3762),(70.939835,42.387827),(70.937354,42.394778),(70.931773,42.401496),(70.929913,42.412296),(70.936114,42.431623),(70.947586,42.451286),(70.961952,42.468107),(70.977145,42.478752),(71.024739,42.455963),(71.041017,42.4548),(71.054712,42.460381),(71.064168,42.470329),(71.066287,42.482137),(71.057864,42.493402),(71.057657,42.493402),(71.057554,42.493506),(71.057554,42.493609),(71.022724,42.51645),(71.012699,42.526036),(71.00319,42.563527),(71.040656,42.580529),(71.127007,42.590606),(71.142768,42.602543),(71.148091,42.6174),(71.146437,42.656855),(71.149021,42.677939),(71.157548,42.687938),(71.19522,42.69724),(71.211446,42.705224),(71.223849,42.717936),(71.245449,42.747133),(71.262502,42.753567),(71.284723,42.7484),(71.308495,42.740105),(71.329785,42.737031),(71.347562,42.742844),(71.363065,42.75411),(71.376294,42.768321),(71.386939,42.783074),(71.404613,42.794883),(71.428849,42.79558),(71.477115,42.78354),(71.493651,42.788914),(71.504193,42.789612),(71.514322,42.78571),(71.553803,42.760905),(71.566308,42.757236),(71.583568,42.759639),(71.693536,42.811807),(71.726402,42.819661),(71.796682,42.822297),(71.831408,42.831573),(71.847738,42.834053),(71.863241,42.829041),(71.878847,42.821341),(71.895384,42.816044),(71.956982,42.804598),(72.072737,42.757185),(72.10488,42.750337),(72.11997,42.75181),(72.148805,42.76199),(72.164101,42.765091),(72.292362,42.76106),(72.358405,42.741397),(72.476744,42.682564),(72.51178,42.677551),(72.583817,42.678275),(72.725824,42.652876),(72.756933,42.640215),(72.780601,42.620449),(72.815224,42.573036),(72.840752,42.555698),(72.874549,42.543993),(72.908345,42.536965),(72.942348,42.536035),(73.070609,42.551926),(73.115051,42.550841),(73.152671,42.539213),(73.172722,42.527845),(73.189052,42.520765),(73.206828,42.517173),(73.278348,42.513401),(73.301396,42.507071),(73.316589,42.493712),(73.313385,42.463171),(73.314419,42.441571),(73.326201,42.428677),(73.417461,42.41705),(73.476889,42.399067),(73.505105,42.402943),(73.505518,42.420926),(73.505077,42.421557),(73.432964,42.524847),(73.417565,42.556163),(73.41002,42.58965),(73.412707,42.627322),(73.423869,42.662772),(73.476889,42.75088),(73.503554,42.794082),(73.507068,42.809404),(73.504278,42.827594),(73.491979,42.861003),(73.489498,42.877823),(73.493012,42.894954),(73.501177,42.909346),(73.521744,42.936166),(73.559675,43.017298),(73.57094,43.031922),(73.58665,43.042283),(73.634089,43.062463),(73.805551,43.114734),(73.822811,43.117318),(73.864256,43.116103),(73.90167,43.13096),(73.935053,43.199716),(73.965335,43.216924),(73.985385,43.211679),(74.021456,43.186306),(74.039852,43.181861),(74.197362,43.195788),(74.213899,43.202635),(74.216586,43.216924),(74.206044,43.234106),(74.178759,43.261702),(74.207697,43.24979),(74.25865,43.215761),(74.286969,43.207209),(74.320042,43.201654),(74.348774,43.191034),(74.400554,43.159537),(74.420604,43.151837),(74.462772,43.148634),(74.498222,43.131115),(74.539253,43.122899),(74.558167,43.115044),(74.572016,43.102202),(74.597028,43.070344),(74.61129,43.058174),(74.71392,42.999883),(74.74875,42.990013),(74.862851,42.975828),(74.948531,42.944848),(74.976849,42.926477),(75.005375,42.9164),(75.066146,42.902602),(75.094258,42.890303),(75.118133,42.876531),(75.178594,42.84966),(75.204639,42.84519)],[(71.008564,40.157757),(70.977145,40.144579),(70.959885,40.113418),(70.954046,40.095797),(70.952961,40.079208),(70.958438,40.063085),(70.98314,40.021383),(70.994509,40.008877),(71.007634,40.003503),(71.034299,39.99911),(71.045823,39.99203),(71.050371,39.962885),(71.007634,39.911157),(71.009288,39.885732),(71.021897,39.880823),(71.036056,39.887541),(71.049802,39.897979),(71.060964,39.904129),(71.079981,39.903405),(71.084787,39.894827),(71.087216,39.88382),(71.098895,39.8755),(71.113674,39.874466),(71.16101,39.884233),(71.1946,39.884802),(71.208449,39.888781),(71.219094,39.900925),(71.221058,39.931724),(71.17703,39.968156),(71.174704,39.993994),(71.190982,40.006241),(71.237284,40.031098),(71.244002,40.046756),(71.236354,40.056057),(71.223745,40.057866),(71.198217,40.052595),(71.192946,40.05027),(71.181887,40.043397),(71.176926,40.042001),(71.169382,40.042828),(71.165454,40.044637),(71.162043,40.046911),(71.105975,40.064946),(71.078844,40.07864),(71.06174,40.095176),(71.047942,40.122513),(71.031199,40.146905),(71.008564,40.157757)],[(71.741801,39.90077),(71.757304,39.903095),(71.767123,39.915446),(71.789757,39.979318),(71.78552,39.989705),(71.760612,39.98371),(71.724128,39.962678),(71.706868,39.956115),(71.681753,39.955082),(71.665527,39.940199),(71.675346,39.925781),(71.696843,39.913844),(71.71617,39.906764),(71.741801,39.90077)],[(70.498725,39.881908),(70.483739,39.882218),(70.482602,39.866767),(70.490147,39.850179),(70.503479,39.835502),(70.537379,39.817312),(70.547301,39.807649),(70.575878,39.77008),(70.581614,39.766566),(70.63298,39.79845),(70.661609,39.809819),(70.694527,39.814832),(70.70481,39.822067),(70.706412,39.839998),(70.698919,39.858447),(70.68662,39.860876),(70.654994,39.849765),(70.619906,39.850695),(70.498725,39.881908)]] diff --git a/tests/queries/0_stateless/country_rings.tsv b/tests/queries/0_stateless/country_rings.tsv new file mode 100644 index 00000000000..15ab66ec0c0 --- /dev/null +++ b/tests/queries/0_stateless/country_rings.tsv @@ -0,0 +1,103 @@ +Aruba [(-69.996938,12.577582),(-69.936391,12.531724),(-69.924672,12.519232),(-69.915761,12.497016),(-69.880198,12.453559),(-69.87682,12.427395),(-69.888092,12.41767),(-69.908803,12.417792),(-69.930531,12.425971),(-69.945139,12.440375),(-69.924672,12.440375),(-69.924672,12.447211),(-69.958567,12.463202),(-70.027659,12.522935),(-70.048085,12.531155),(-70.058095,12.537177),(-70.062408,12.54682),(-70.060374,12.556952),(-70.051096,12.574042),(-70.048736,12.583726),(-70.052642,12.600002),(-70.059641,12.614244),(-70.061106,12.625393),(-70.048736,12.632148),(-70.007151,12.585517),(-69.996938,12.577582)] +Afghanistan [(71.049802,38.408664),(71.05714,38.409026),(71.064943,38.411817),(71.076984,38.412178),(71.089386,38.409853),(71.117395,38.398639),(71.155946,38.376212),(71.217699,38.325827),(71.300123,38.298697),(71.334384,38.280662),(71.358156,38.251258),(71.364512,38.206816),(71.359086,38.184105),(71.340947,38.140929),(71.334539,38.11168),(71.316039,38.083284),(71.302397,38.04233),(71.272631,37.997992),(71.265913,37.972541),(71.255785,37.949881),(71.254544,37.939287),(71.258265,37.926472),(71.263536,37.924353),(71.271184,37.926187),(71.281829,37.924999),(71.31976,37.900582),(71.341154,37.893295),(71.360998,37.902029),(71.379188,37.912932),(71.501196,37.946212),(71.537059,37.944455),(71.567342,37.928074),(71.597727,37.89836),(71.590286,37.891435),(71.593387,37.879343),(71.59504,37.857535),(71.594214,37.833764),(71.590286,37.815729),(71.57468,37.798004),(71.537783,37.779039),(71.529515,37.761133),(71.531168,37.751754),(71.540263,37.730515),(71.542537,37.719559),(71.540883,37.709715),(71.529515,37.67858),(71.52476,37.647729),(71.522073,37.637626),(71.517216,37.629229),(71.505123,37.616),(71.501506,37.610341),(71.497165,37.566545),(71.511221,37.485878),(71.501506,37.445777),(71.490241,37.423376),(71.48714,37.409087),(71.494685,37.370692),(71.496545,37.328524),(71.493858,37.307543),(71.487863,37.294986),(71.487037,37.267055),(71.45014,37.21667),(71.453757,37.192615),(71.446832,37.183597),(71.441045,37.16843),(71.43319,37.127347),(71.431123,37.066989),(71.43319,37.054742),(71.439184,37.044097),(71.456444,37.022548),(71.459958,37.010739),(71.459958,36.969786),(71.463059,36.948082),(71.47174,36.930047),(71.528481,36.856149),(71.538506,36.836099),(71.545328,36.790004),(71.552872,36.769591),(71.563931,36.750678),(71.577367,36.733263),(71.61106,36.704841),(71.653021,36.687012),(71.699943,36.678641),(71.748519,36.678641),(71.797612,36.686082),(71.836576,36.699156),(72.126687,36.872738),(72.152836,36.895708),(72.186839,36.911392),(72.195934,36.918988),(72.210403,36.93661),(72.220325,36.94555),(72.259806,36.967305),(72.360988,37.000275),(72.405947,37.007665),(72.474987,36.997484),(72.50868,37.011075),(72.657714,37.028826),(72.666603,37.038335),(72.672701,37.05761),(72.714352,37.109984),(72.760964,37.187499),(72.79073,37.220262),(72.83052,37.239769),(72.877443,37.246875),(72.902247,37.2538),(72.924262,37.274832),(72.995575,37.3093),(73.067509,37.315062),(73.087766,37.326069),(73.099238,37.339867),(73.116394,37.369064),(73.132104,37.384386),(73.170241,37.40826),(73.179026,37.410741),(73.200627,37.404178),(73.211479,37.40826),(73.260262,37.450041),(73.276075,37.459472),(73.296332,37.464949),(73.32124,37.467017),(73.345011,37.464484),(73.361858,37.456397),(73.378394,37.452547),(73.440612,37.479936),(73.485261,37.480969),(73.605047,37.445777),(73.6745,37.43105),(73.717805,37.431825),(73.753462,37.428388),(73.747054,37.403119),(73.745917,37.394902),(73.74571,37.352863),(73.739096,37.338342),(73.722249,37.322452),(73.704989,37.310954),(73.690416,37.305218),(73.651969,37.302065),(73.630988,37.295993),(73.609904,37.281395),(73.597295,37.261809),(73.601636,37.24088),(73.617656,37.233181),(73.659927,37.243748),(73.680494,37.242457),(73.688039,37.236901),(73.702405,37.221166),(73.709227,37.217006),(73.719975,37.217549),(73.736202,37.227651),(73.746123,37.230545),(73.768654,37.228892),(73.783951,37.225894),(73.798213,37.22853),(73.836247,37.256745),(73.856401,37.261577),(73.899292,37.265478),(73.95562,37.286769),(73.976704,37.290283),(74.052151,37.312246),(74.163256,37.330074),(74.187647,37.338394),(74.206044,37.355654),(74.207697,37.389915),(74.223924,37.403351),(74.250382,37.403687),(74.279424,37.397512),(74.303816,37.400173),(74.315598,37.426916),(74.320869,37.413893),(74.332444,37.420353),(74.343813,37.420999),(74.353632,37.415909),(74.368204,37.396375),(74.378126,37.393765),(74.389392,37.393403),(74.418331,37.389192),(74.435901,37.392344),(74.454814,37.393636),(74.476622,37.386091),(74.512692,37.377229),(74.521167,37.375601),(74.529848,37.375756),(74.631444,37.381079),(74.660383,37.393972),(74.78854,37.331159),(74.816859,37.306923),(74.862644,37.244601),(74.892307,37.231114),(74.813138,37.21543),(74.794018,37.213931),(74.783269,37.219667),(74.743995,37.288397),(74.737381,37.296123),(74.721464,37.297776),(74.709372,37.290826),(74.698934,37.28031),(74.676299,37.263721),(74.670925,37.261344),(74.650978,37.259639),(74.646327,37.254833),(74.64302,37.248374),(74.629997,37.238297),(74.627207,37.234318),(74.623279,37.230804),(74.615011,37.228375),(74.609017,37.230183),(74.596511,37.240751),(74.59,37.243361),(74.575944,37.242147),(74.532225,37.232199),(74.500083,37.23163),(74.487267,37.225946),(74.476622,37.210055),(74.46763,37.189927),(74.456674,37.177318),(74.441585,37.170549),(74.420294,37.168068),(74.38226,37.172047),(74.368308,37.167061),(74.366137,37.14776),(74.38257,37.126572),(74.414403,37.107839),(74.476622,37.083138),(74.494088,37.066472),(74.505767,37.047042),(74.519203,37.030247),(74.542354,37.021669),(74.547418,37.015675),(74.549279,37.008931),(74.548142,37.001644),(74.544214,36.994022),(74.537393,36.962241),(74.521373,36.958495),(74.501736,36.972421),(74.48365,36.99397),(74.480342,36.996916),(74.476622,36.999319),(74.456984,37.004383),(74.43559,37.003221),(74.394043,36.994022),(74.368101,36.976762),(74.284592,36.934232),(74.235706,36.902167),(74.211728,36.895139),(74.145996,36.901702),(74.129666,36.898421),(74.1153,36.889532),(74.108789,36.875631),(74.103931,36.841318),(74.094319,36.831241),(74.035305,36.815583),(74.006366,36.815738),(73.976704,36.824833),(73.946938,36.83088),(73.865083,36.872582),(73.834077,36.882866),(73.772892,36.892013),(73.711842,36.894139),(73.711335,36.894157),(73.711128,36.894164),(73.709483,36.894221),(73.640083,36.896638),(73.509342,36.87868),(73.476889,36.882866),(73.445883,36.886483),(73.379738,36.879249),(73.331782,36.882091),(73.281862,36.867983),(73.267496,36.866536),(73.252717,36.868035),(73.223468,36.874339),(73.191842,36.877027),(73.042497,36.864263),(73.026271,36.859457),(73.002293,36.846124),(72.990511,36.841577),(72.976765,36.842093),(72.945862,36.852222),(72.921058,36.847364),(72.896873,36.836977),(72.867727,36.830415),(72.779361,36.826797),(72.695852,36.836719),(72.629602,36.832947),(72.565214,36.820596),(72.516741,36.800597),(72.454109,36.757964),(72.433129,36.753417),(72.387343,36.755794),(72.346209,36.74489),(72.301974,36.74272),(72.213607,36.726442),(72.169682,36.711352),(72.153456,36.702102),(72.149632,36.689338),(72.164618,36.670063),(72.171646,36.653629),(72.154179,36.645465),(72.096095,36.638902),(72.070877,36.632287),(72.059095,36.627119),(72.050413,36.618645),(72.05217,36.610376),(72.056304,36.601901),(72.054961,36.592858),(72.038838,36.580456),(71.997806,36.572446),(71.977033,36.563041),(71.960909,36.549605),(71.913471,36.527591),(71.899725,36.518341),(71.887632,36.508005),(71.874713,36.499065),(71.85859,36.494156),(71.793788,36.490745),(71.773221,36.480048),(71.774564,36.448422),(71.791514,36.421292),(71.794408,36.407598),(71.782626,36.396539),(71.766916,36.391837),(71.751,36.391113),(71.736324,36.395919),(71.706868,36.421447),(71.649301,36.452763),(71.629147,36.459533),(71.61044,36.457931),(71.600725,36.449301),(71.588736,36.41845),(71.580364,36.402327),(71.572303,36.391682),(71.547188,36.371631),(71.542227,36.356387),(71.552666,36.340987),(71.55835,36.327861),(71.53892,36.319283),(71.514632,36.315201),(71.495822,36.309619),(71.479078,36.300524),(71.402752,36.231381),(71.382443,36.218566),(71.31914,36.200582),(71.313972,36.194019),(71.309011,36.172729),(71.302087,36.163323),(71.292682,36.157897),(71.262296,36.146115),(71.223073,36.125393),(71.217699,36.118055),(71.212635,36.096816),(71.207622,36.087617),(71.175376,36.061159),(71.165919,36.045708),(71.169913,36.030802),(71.170932,36.027001),(71.181887,36.018836),(71.217854,36.002713),(71.23191,35.99398),(71.257438,35.971552),(71.28431,35.962457),(71.312525,35.957393),(71.341567,35.947264),(71.356399,35.933053),(71.360688,35.90029),(71.371333,35.885149),(71.416705,35.858846),(71.431019,35.843705),(71.464402,35.794715),(71.470914,35.779936),(71.47205,35.769962),(71.471017,35.761333),(71.47112,35.752289),(71.475564,35.741024),(71.481352,35.734099),(71.496132,35.724591),(71.502746,35.719061),(71.515355,35.701491),(71.519799,35.683766),(71.514012,35.665576),(71.495925,35.646611),(71.483316,35.62656),(71.492721,35.609559),(71.512771,35.596278),(71.567859,35.574212),(71.584188,35.564187),(71.59349,35.549356),(71.59287,35.530184),(71.586049,35.512097),(71.581708,35.493132),(71.587806,35.470911),(71.593422,35.464194),(71.600725,35.45546),(71.613954,35.443212),(71.622429,35.429621),(71.620879,35.410139),(71.61106,35.395463),(71.562277,35.360582),(71.531582,35.327922),(71.529825,35.300895),(71.547808,35.275626),(71.603205,35.223381),(71.633694,35.203124),(71.637932,35.189688),(71.62925,35.170102),(71.604135,35.138166),(71.534992,35.098582),(71.508947,35.072021),(71.5075,35.028199),(71.512978,35.018122),(71.511325,35.008717),(71.504297,35.000604),(71.493444,34.994196),(71.493444,34.994144),(71.493341,34.994144),(71.493341,34.994041),(71.485383,34.983499),(71.476701,34.960296),(71.46957,34.949702),(71.459958,34.942674),(71.445239,34.937757),(71.324928,34.897561),(71.289478,34.87503),(71.270822,34.844283),(71.25563,34.810228),(71.203075,34.748164),(71.189535,34.737054),(71.150933,34.720311),(71.080601,34.672923),(71.070163,34.661245),(71.068768,34.645948),(71.076261,34.623624),(71.079878,34.602902),(71.076571,34.578511),(71.065822,34.55846),(71.047529,34.551122),(71.006963,34.556341),(70.985827,34.556186),(70.983356,34.555256),(70.96867,34.549727),(70.956991,34.532002),(70.955648,34.510014),(70.961229,34.487612),(70.970841,34.468879),(70.991511,34.443067),(71.01983,34.414438),(71.050939,34.389788),(71.122046,34.356819),(71.126387,34.332221),(71.097086,34.262458),(71.09688,34.244345),(71.106543,34.209386),(71.109489,34.189206),(71.108093,34.165228),(71.101789,34.151818),(71.073884,34.125257),(71.062773,34.10531),(71.063858,34.088928),(71.067269,34.073012),(71.062618,34.054253),(71.046702,34.041877),(70.997712,34.033324),(70.977145,34.027407),(70.965725,34.013816),(70.953994,34.004825),(70.939731,34.000923),(70.921231,34.002241),(70.894308,34.009372),(70.884334,34.007047),(70.879994,33.994257),(70.862217,33.964775),(70.791317,33.953562),(70.656183,33.95475),(70.521979,33.938705),(70.49149,33.939609),(70.408963,33.954414),(70.328193,33.957282),(70.309899,33.961675),(70.275586,33.97617),(70.218845,33.980692),(70.002838,34.043789),(69.969093,34.045727),(69.916021,34.038879),(69.889253,34.031206),(69.872613,34.017227),(69.870443,34.001337),(69.873853,33.986325),(69.871993,33.971519),(69.854216,33.956352),(69.841091,33.941805),(69.847188,33.926948),(69.876489,33.902557),(69.885429,33.889457),(69.898761,33.851501),(69.907546,33.83561),(69.931318,33.806439),(69.940103,33.791479),(69.947234,33.771971),(69.957518,33.752695),(69.972659,33.744841),(69.996478,33.742091),(70.011829,33.740319),(70.065573,33.721018),(70.108154,33.727296),(70.118128,33.716522),(70.126551,33.676964),(70.132546,33.661435),(70.136886,33.656293),(70.145981,33.649885),(70.162518,33.643245),(70.170218,33.638671),(70.174093,33.632108),(70.173473,33.607872),(70.153009,33.544749),(70.151356,33.525862),(70.154973,33.506612),(70.163758,33.488655),(70.177607,33.47341),(70.185462,33.468966),(70.213368,33.461344),(70.220447,33.456021),(70.227837,33.43995),(70.233005,33.432612),(70.285715,33.382873),(70.301579,33.35179),(70.294448,33.318949),(70.124794,33.199034),(70.105364,33.18981),(70.08366,33.191283),(70.059785,33.198052),(70.048003,33.194073),(70.014517,33.140769),(70.006869,33.131803),(69.994725,33.127333),(69.965734,33.1294),(69.955812,33.127695),(69.880933,33.089248),(69.838713,33.086664),(69.771844,33.114776),(69.732983,33.109298),(69.68601,33.080773),(69.667768,33.077),(69.658776,33.078421),(69.650198,33.081858),(69.640689,33.084235),(69.60834,33.079067),(69.587773,33.079532),(69.547517,33.075011),(69.514185,33.056691),(69.487727,33.028373),(69.478125,33.01135),(69.468503,32.994292),(69.48721,32.885875),(69.477288,32.856833),(69.471449,32.852234),(69.445559,32.835671),(69.421064,32.80681),(69.387165,32.785338),(69.376313,32.771877),(69.37807,32.752317),(69.383237,32.744462),(69.39042,32.737899),(69.399154,32.732964),(69.407732,32.729941),(69.414657,32.725575),(69.41724,32.718004),(69.419101,32.70046),(69.429126,32.667361),(69.426025,32.655088),(69.413933,32.635477),(69.361223,32.568478),(69.34355,32.55605),(69.302105,32.543777),(69.281952,32.532796),(69.251566,32.50055),(69.232859,32.462671),(69.228001,32.421304),(69.238543,32.378283),(69.264433,32.322369),(69.268102,32.301337),(69.266965,32.279581),(69.259989,32.236819),(69.259524,32.194522),(69.251876,32.15225),(69.251049,32.13065),(69.270634,32.035978),(69.302157,31.959911),(69.304793,31.94694),(69.301157,31.941282),(69.29885,31.93769),(69.250946,31.907046),(69.223764,31.881931),(69.114313,31.737754),(69.10005,31.724008),(69.084754,31.715791),(69.071628,31.69786),(69.040106,31.673107),(69.004036,31.651092),(68.977267,31.641481),(68.94099,31.643651),(68.906987,31.634298),(68.843529,31.606496),(68.803841,31.602568),(68.77728,31.618588),(68.731184,31.675535),(68.705449,31.70127),(68.697905,31.715946),(68.694907,31.756357),(68.688293,31.768605),(68.675787,31.774702),(68.61946,31.783487),(68.561065,31.811806),(68.527476,31.822968),(68.5051,31.822658),(68.481484,31.815682),(68.438179,31.796045),(68.418748,31.783022),(68.422211,31.773152),(68.439574,31.766589),(68.461433,31.763592),(68.521274,31.764781),(68.540601,31.762507),(68.5498,31.753515),(68.536829,31.741009),(68.515177,31.729951),(68.49802,31.725248),(68.460968,31.730467),(68.356065,31.762507),(68.316532,31.765194),(68.276948,31.763592),(68.255037,31.766383),(68.242635,31.776925),(68.2323,31.790154),(68.206823,31.807879),(68.184758,31.818214),(68.159126,31.825914),(68.138559,31.824674),(68.125743,31.811496),(68.104504,31.76876),(68.09834,31.759124),(68.093497,31.751551),(68.060476,31.725558),(68.055566,31.716566),(68.052259,31.695431),(68.046575,31.688403),(67.994071,31.663443),(67.977328,31.651868),(67.966063,31.638225),(67.955211,31.633212),(67.914696,31.631352),(67.884311,31.635641),(67.870668,31.635176),(67.842711,31.623497),(67.781165,31.564173),(67.74828,31.544392),(67.726698,31.53141),(67.696312,31.520816),(67.665461,31.518129),(67.600504,31.53048),(67.568981,31.52986),(67.556114,31.512186),(67.5634,31.497252),(67.578076,31.48211),(67.591099,31.464799),(67.59699,31.42568),(67.611459,31.410797),(67.631406,31.4001),(67.651147,31.395294),(67.734294,31.404751),(67.770364,31.394674),(67.775067,31.352764),(67.764731,31.334058),(67.749435,31.328011),(67.709024,31.329303),(67.692798,31.325221),(67.678949,31.316591),(67.665926,31.306256),(67.602157,31.271116),(67.583657,31.265225),(67.530224,31.256646),(67.493327,31.242952),(67.433899,31.236079),(67.364601,31.210706),(67.346204,31.20776),(67.282177,31.212773),(67.230294,31.210603),(67.213757,31.212256),(67.19319,31.218509),(67.156707,31.235924),(67.136759,31.241092),(67.116864,31.240316),(67.078468,31.232048),(67.058211,31.232358),(67.035267,31.235924),(67.022865,31.239386),(67.015268,31.244657),(67.013873,31.252667),(67.017904,31.258713),(67.023433,31.264863),(67.025965,31.273028),(67.023898,31.2953),(67.016818,31.309149),(67.002091,31.315867),(66.943283,31.314731),(66.905921,31.305532),(66.838483,31.277007),(66.808614,31.254734),(66.785308,31.23179),(66.759522,31.214788),(66.721281,31.210292),(66.696993,31.195823),(66.663093,31.083117),(66.643973,31.060172),(66.550025,30.976973),(66.527494,30.968343),(66.392309,30.944624),(66.375359,30.936717),(66.366264,30.922868),(66.267975,30.601389),(66.264926,30.557826),(66.281928,30.518138),(66.306113,30.491112),(66.313761,30.478296),(66.319393,30.457832),(66.321822,30.437368),(66.303012,30.305283),(66.305286,30.24477),(66.300893,30.225598),(66.236349,30.1116),(66.221725,30.073721),(66.219296,30.057856),(66.225239,30.04442),(66.260431,30.02313),(66.301565,29.98675),(66.332364,29.966079),(66.340529,29.956571),(66.336808,29.952023),(66.328437,29.949543),(66.322442,29.946545),(66.301772,29.915694),(66.27521,29.885154),(66.195628,29.835338),(66.110466,29.813634),(66.052381,29.798854),(65.994297,29.784023),(65.936109,29.769295),(65.878232,29.75449),(65.820147,29.739736),(65.762063,29.724905),(65.70403,29.710151),(65.645843,29.695346),(65.58781,29.680567),(65.529726,29.665736),(65.471745,29.650956),(65.413661,29.636177),(65.355783,29.621423),(65.297595,29.606644),(65.239511,29.591838),(65.181427,29.57711),(65.036371,29.540162),(64.986606,29.541557),(64.820312,29.567886),(64.683886,29.568816),(64.499477,29.570203),(64.477697,29.570367),(64.207739,29.499983),(64.172599,29.4843),(64.149758,29.458461),(64.113378,29.396295),(64.086093,29.386605),(63.971991,29.429574),(63.78792,29.46058),(63.568605,29.497477),(63.415953,29.484971),(63.366809,29.480941),(63.317768,29.47691),(63.268675,29.472879),(63.219686,29.468797),(63.170697,29.464766),(63.121604,29.460787),(63.072615,29.456756),(63.023626,29.452674),(62.974533,29.448643),(62.925544,29.444638),(62.876451,29.440581),(62.827462,29.436602),(62.778421,29.43252),(62.72938,29.428489),(62.680391,29.424458),(62.63135,29.420428),(62.602581,29.41807),(62.477509,29.407819),(62.374466,29.424872),(62.279433,29.451485),(62.196286,29.47492),(62.112983,29.498226),(62.029629,29.521636),(61.946534,29.545045),(61.863231,29.568351),(61.779929,29.591787),(61.696626,29.615196),(61.613427,29.638502),(61.530228,29.66186),(61.446926,29.685321),(61.363727,29.708627),(61.280424,29.732011),(61.197225,29.755343),(61.114026,29.778726),(61.030621,29.802161),(60.947422,29.825519),(60.876005,29.845518),(60.844379,29.858179),(60.902153,29.916883),(60.978117,29.994139),(60.978427,29.994398),(61.133043,30.154285),(61.215622,30.239706),(61.272156,30.298307),(61.380367,30.41029),(61.461705,30.494522),(61.461705,30.494574),(61.57622,30.613895),(61.702621,30.745515),(61.7852,30.831401),(61.802253,30.847059),(61.799773,30.852381),(61.798429,30.853467),(61.799876,30.871502),(61.802356,30.87853),(61.808351,30.881424),(61.804527,30.94974),(61.800186,30.961419),(61.819306,30.993923),(61.826438,31.014956),(61.826334,31.034593),(61.821477,31.054488),(61.809281,31.087148),(61.791814,31.118929),(61.789334,31.129315),(61.78768,31.158616),(61.779205,31.181095),(61.752437,31.219129),(61.742722,31.239541),(61.742308,31.259437),(61.749233,31.30238),(61.742308,31.32088),(61.706548,31.359844),(61.686911,31.373177),(61.661176,31.38191),(61.606259,31.388741),(61.490851,31.403097),(61.29479,31.427644),(61.125149,31.448887),(61.123535,31.449089),(60.956,31.47007),(60.855024,31.482731),(60.821744,31.494668),(60.809962,31.588357),(60.794976,31.636675),(60.792599,31.660084),(60.805311,31.733981),(60.791462,31.826534),(60.789292,31.874955),(60.796733,31.93676),(60.794976,31.958464),(60.791049,31.969161),(60.786088,31.978979),(60.784021,31.989263),(60.792599,32.011277),(60.786708,32.01691),(60.778336,32.021044),(60.774926,32.027194),(60.782677,32.042541),(60.808825,32.07117),(60.81482,32.087862),(60.828256,32.167443),(60.830323,32.248885),(60.79632,32.355907),(60.752291,32.494581),(60.711674,32.61031),(60.67488,32.715601),(60.64005,32.815517),(60.60615,32.912359),(60.577522,32.994344),(60.562949,33.058268),(60.561502,33.137307),(60.5676,33.151285),(60.615969,33.206191),(60.670332,33.267712),(60.719012,33.323032),(60.757046,33.366337),(60.785881,33.387782),(60.818644,33.404887),(60.829082,33.416282),(60.834664,33.436255),(60.832803,33.453463),(60.829289,33.470129),(60.832183,33.484495),(60.849856,33.494365),(60.897295,33.497026),(60.912075,33.501522),(60.919788,33.512571),(60.92086,33.514105),(60.911971,33.528446),(60.895125,33.541132),(60.879622,33.548703),(60.846032,33.555782),(60.807378,33.558159),(60.733894,33.554852),(60.655553,33.559891),(60.574834,33.587796),(60.511789,33.638387),(60.486881,33.71138),(60.494943,33.744117),(60.525845,33.80215),(60.528016,33.84145),(60.499387,33.994257),(60.488461,34.080927),(60.486778,34.094277),(60.492772,34.139028),(60.520884,34.186131),(60.552407,34.220057),(60.587443,34.250262),(60.634986,34.271217),(60.650592,34.28535),(60.643667,34.306641),(60.714361,34.310129),(60.815957,34.315271),(60.890474,34.318914),(60.879105,34.337647),(60.804898,34.417487),(60.789085,34.44348),(60.77937,34.455081),(60.767277,34.464151),(60.742783,34.473452),(60.733894,34.480429),(60.725316,34.504277),(60.718908,34.51115),(60.71033,34.515129),(60.699685,34.516396),(60.714361,34.537428),(60.739269,34.548022),(60.794046,34.554119),(60.818954,34.559907),(60.838488,34.570914),(60.883859,34.613702),(60.888924,34.62166),(60.895435,34.628327),(60.908871,34.634683),(60.922824,34.636543),(60.935846,34.635665),(60.947525,34.63799),(60.957964,34.649411),(60.961994,34.67375),(60.958687,34.699589),(60.959927,34.723205),(60.978014,34.74062),(61.00964,34.76098),(61.02907,34.789712),(61.034755,34.806249),(61.06545,34.814724),(61.073409,34.847693),(61.077749,34.88304),(61.077026,34.891721),(61.072582,34.910325),(61.071548,34.920557),(61.074752,34.933114),(61.088912,34.951925),(61.092012,34.961485),(61.095319,34.981018),(61.109892,35.018535),(61.115887,35.059877),(61.123121,35.074191),(61.147306,35.102096),(61.136764,35.111191),(61.135214,35.119408),(61.137901,35.128296),(61.139865,35.139665),(61.137074,35.143902),(61.101521,35.183228),(61.096353,35.193202),(61.102347,35.197698),(61.112373,35.202038),(61.112786,35.21165),(61.107929,35.221262),(61.102347,35.225603),(61.101624,35.235318),(61.102451,35.25666),(61.108342,35.277951),(61.122708,35.287666),(61.143999,35.28808),(61.167873,35.291387),(61.187097,35.300379),(61.195055,35.318104),(61.190404,35.369573),(61.195055,35.390089),(61.200843,35.401148),(61.221823,35.424247),(61.227301,35.434479),(61.235983,35.465847),(61.247041,35.48507),(61.270503,35.508428),(61.283835,35.52729),(61.290036,35.548064),(61.287556,35.568269),(61.277014,35.609197),(61.269676,35.618499),(61.283318,35.622633),(61.335718,35.630901),(61.344193,35.630901),(61.351531,35.627801),(61.360936,35.621031),(61.360109,35.618395),(61.351531,35.60713),(61.363934,35.598242),(61.365484,35.5985),(61.367654,35.597983),(61.383467,35.586459),(61.383881,35.582119),(61.379953,35.571318),(61.380263,35.567339),(61.386878,35.559536),(61.393182,35.553593),(61.401244,35.549821),(61.412613,35.548322),(61.419309,35.545891),(61.427702,35.542845),(61.492711,35.494165),(61.538703,35.452307),(61.604746,35.430603),(61.739621,35.413757),(61.799049,35.417478),(61.919352,35.451842),(61.977746,35.450912),(62.00746,35.438923),(62.033815,35.423989),(62.136341,35.341358),(62.163885,35.326165),(62.219023,35.30627),(62.2337,35.293764),(62.244345,35.278055),(62.251218,35.260381),(62.252613,35.242811),(62.25096,35.202349),(62.256851,35.187156),(62.275713,35.151034),(62.286203,35.140647),(62.302016,35.14752),(62.399323,35.255937),(62.431879,35.280638),(62.458905,35.281879),(62.524586,35.232166),(62.53549,35.22736),(62.545515,35.228032),(62.555437,35.230409),(62.566186,35.230771),(62.595641,35.22059),(62.60453,35.219402),(62.621066,35.222709),(62.69362,35.248392),(62.708606,35.25604),(62.721628,35.266427),(62.734238,35.280742),(62.760489,35.302446),(62.823063,35.327514),(62.827565,35.329318),(62.918206,35.388177),(62.985282,35.414584),(63.005539,35.418408),(63.047087,35.421353),(63.066827,35.425591),(63.080211,35.437063),(63.086257,35.455666),(63.090495,35.493545),(63.100727,35.524964),(63.097213,35.535455),(63.080573,35.546514),(63.077369,35.558761),(63.07494,35.609817),(63.076646,35.6247),(63.103156,35.646042),(63.179895,35.666455),(63.207697,35.683198),(63.213588,35.692293),(63.214415,35.699269),(63.209351,35.704488),(63.183926,35.712343),(63.17726,35.716891),(63.163255,35.73229),(63.112044,35.769911),(63.105688,35.782882),(63.101295,35.800555),(63.091322,35.813319),(63.084397,35.826083),(63.088634,35.843395),(63.104086,35.856469),(63.125273,35.860241),(63.342934,35.856262),(63.430216,35.871042),(63.511089,35.901841),(63.52592,35.912693),(63.549588,35.939048),(63.563438,35.950623),(63.582093,35.959047),(63.602298,35.962664),(63.725702,35.968865),(63.765906,35.977288),(63.859854,36.022092),(63.889826,36.029637),(63.906327,36.031732),(63.921969,36.033719),(63.949977,36.028861),(64.045114,35.998734),(64.045579,36.011291),(64.03638,36.058575),(64.036225,36.076404),(64.044648,36.09232),(64.057258,36.105239),(64.123352,36.146064),(64.158698,36.160275),(64.195905,36.165907),(64.237143,36.16043),(64.253731,36.154849),(64.266134,36.152471),(64.276056,36.159241),(64.291869,36.199445),(64.303651,36.211538),(64.318947,36.219754),(64.33724,36.225955),(64.410879,36.239856),(64.444572,36.249985),(64.477697,36.271637),(64.498161,36.291429),(64.576657,36.389615),(64.594382,36.424186),(64.605855,36.461083),(64.610505,36.500926),(64.607767,36.521648),(64.593711,36.559837),(64.589008,36.580249),(64.588801,36.600454),(64.592005,36.621073),(64.604821,36.660554),(64.621357,36.692593),(64.728549,36.85057),(64.765225,36.904622),(64.778764,36.93847),(64.77463,36.977589),(64.755613,37.053631),(64.76016,37.092621),(64.778764,37.118046),(64.807909,37.135512),(64.989087,37.213673),(65.063088,37.233232),(65.487922,37.241997),(65.501407,37.242276),(65.536857,37.257107),(65.583159,37.30806),(65.611271,37.331056),(65.624087,37.345138),(65.629461,37.365421),(65.628893,37.387538),(65.620986,37.430404),(65.625741,37.452805),(65.635766,37.474096),(65.648168,37.493837),(65.648272,37.49394),(65.648323,37.493992),(65.648323,37.494147),(65.65871,37.51027),(65.668839,37.520553),(65.681034,37.526393),(65.698294,37.529416),(65.739429,37.529054),(65.752658,37.537865),(65.758859,37.564117),(65.761443,37.578379),(65.776532,37.572902),(65.79648,37.569336),(65.804334,37.565305),(65.821078,37.535178),(65.829087,37.525618),(65.836064,37.519158),(65.855184,37.507944),(66.079666,37.440868),(66.097856,37.428414),(66.125607,37.3987),(66.142918,37.385058),(66.163072,37.376893),(66.174648,37.375498),(66.207721,37.376893),(66.218469,37.3748),(66.232525,37.365421),(66.241879,37.363302),(66.250848,37.35965),(66.257743,37.356842),(66.274383,37.343277),(66.294434,37.331211),(66.320685,37.329144),(66.389622,37.347179),(66.413496,37.349633),(66.423625,37.34568),(66.438663,37.327904),(66.451065,37.322943),(66.461452,37.324441),(66.469927,37.329764),(66.485223,37.343406),(66.502896,37.355654),(66.519588,37.36418),(66.539018,37.36909),(66.564598,37.370692),(66.588576,37.36847),(66.65467,37.346145),(66.667021,37.344311),(66.694099,37.343406),(66.704745,37.346533),(66.724433,37.36015),(66.734975,37.363302),(66.865768,37.367927),(66.957649,37.385213),(67.005915,37.384386),(67.024105,37.377487),(67.064102,37.354569),(67.085083,37.349633),(67.097382,37.34059),(67.113918,37.297182),(67.123324,37.281963),(67.143477,37.27186),(67.187816,37.258244),(67.20797,37.243464),(67.217995,37.226256),(67.225281,37.207704),(67.236753,37.192408),(67.259129,37.185147),(67.281453,37.188661),(67.319591,37.208428),(67.345222,37.213027),(67.36951,37.21468),(67.391163,37.21959),(67.411265,37.22791),(67.431108,37.239769),(67.463975,37.266279),(67.482371,37.277364),(67.503145,37.281963),(67.526141,37.272894),(67.545003,37.231527),(67.561385,37.2199),(67.572185,37.223155),(67.579937,37.232664),(67.586034,37.242612),(67.592287,37.247185),(67.602726,37.24827),(67.621794,37.252921),(67.633163,37.254058),(67.644635,37.251216),(67.666443,37.238012),(67.677502,37.233542),(67.690162,37.23225),(67.725871,37.233542),(67.746593,37.229408),(67.764266,37.220882),(67.775997,37.207549),(67.780544,37.188868),(67.771966,37.12497),(67.773051,37.109984),(67.78535,37.096548),(67.808036,37.083241),(67.832893,37.073087),(67.87811,37.064431),(67.891959,37.052029),(67.902501,37.034381),(67.918417,37.013814),(67.929269,37.006244),(67.952937,36.996244),(67.961825,36.98994),(67.99619,36.955782),(68.00203,36.947487),(68.00606,36.938677),(68.011125,36.930874),(68.02022,36.92568),(68.02482,36.925518),(68.032725,36.925241),(68.044714,36.92922),(68.054946,36.934646),(68.121092,36.980276),(68.133391,36.986529),(68.151995,36.992782),(68.167963,37.006089),(68.186411,37.01831),(68.212559,37.021256),(68.253746,37.010223),(68.277775,37.010068),(68.288317,37.024408),(68.281599,37.066472),(68.280772,37.086652),(68.288317,37.103214),(68.307282,37.114221),(68.326661,37.113033),(68.346091,37.106909),(68.365832,37.103214),(68.391877,37.105437),(68.411462,37.113369),(68.418025,37.128277),(68.403711,37.151635),(68.465774,37.155356),(68.513316,37.163986),(68.523858,37.164658),(68.532747,37.168999),(68.546544,37.188222),(68.551453,37.192615),(68.571401,37.194708),(68.608814,37.204087),(68.626901,37.206257),(68.630777,37.213828),(68.63641,37.229925),(68.648605,37.244369),(68.671239,37.247185),(68.665452,37.259381),(68.662661,37.263721),(68.657545,37.267675),(68.668862,37.278294),(68.686949,37.279018),(68.725913,37.274522),(68.746532,37.276227),(68.759606,37.275245),(68.771285,37.270724),(68.808492,37.251629),(68.820378,37.250906),(68.824615,37.260621),(68.822031,37.281963),(68.810197,37.312091),(68.813815,37.323408),(68.835829,37.329144),(68.856758,37.324906),(68.868023,37.312142),(68.877015,37.296097),(68.890296,37.281963),(68.904714,37.276692),(68.915824,37.279069),(68.921147,37.287958),(68.917633,37.302427),(68.912982,37.306768),(68.896755,37.316483),(68.890296,37.322943),(68.885077,37.334828),(68.887867,37.338135),(68.893655,37.337154),(68.897169,37.335965),(68.965433,37.329144),(68.985225,37.320359),(69.005483,37.305528),(69.021037,37.287958),(69.035765,37.251577),(69.055609,37.237108),(69.078398,37.225171),(69.096433,37.213027),(69.114313,37.177473),(69.123615,37.169205),(69.145732,37.156958),(69.151003,37.155046),(69.245675,37.103886),(69.265777,37.105411),(69.285621,37.11293),(69.308617,37.116882),(69.312079,37.117477),(69.323913,37.120991),(69.334765,37.129053),(69.350836,37.144142),(69.391196,37.164658),(69.407732,37.177473),(69.442148,37.223621),(69.445197,37.23641),(69.426852,37.239459),(69.409851,37.245661),(69.417912,37.267675),(69.409696,37.276744),(69.403081,37.31116),(69.394606,37.326069),(69.389439,37.332916),(69.386441,37.34152),(69.384891,37.3509),(69.384478,37.36015),(69.385821,37.363147),(69.388508,37.363767),(69.390885,37.365317),(69.391196,37.370692),(69.388302,37.37511),(69.378948,37.377125),(69.377036,37.380665),(69.376313,37.418854),(69.37838,37.437406),(69.384478,37.453271),(69.389645,37.4588),(69.404011,37.466861),(69.411711,37.47252),(69.415587,37.477507),(69.421788,37.489496),(69.425405,37.49425),(69.469744,37.52014),(69.491448,37.536986),(69.508656,37.578973),(69.528655,37.586027),(69.664977,37.576157),(69.687301,37.579594),(69.729573,37.594089),(69.754274,37.596673),(69.762232,37.595794),(69.784453,37.59042),(69.791843,37.586105),(69.80223,37.581506),(69.812668,37.585846),(69.823004,37.592952),(69.832926,37.596673),(69.853286,37.60122),(69.895247,37.61817),(69.918812,37.617137),(69.935245,37.605664),(69.944547,37.589696),(69.955399,37.575485),(69.976586,37.569336),(69.989505,37.56732),(69.994673,37.562256),(69.998497,37.55559),(70.004187,37.551371),(70.007592,37.548846),(70.016894,37.545978),(70.048003,37.541431),(70.041698,37.548846),(70.06919,37.545203),(70.099059,37.536573),(70.129135,37.532284),(70.157867,37.541431),(70.192697,37.576028),(70.199415,37.579284),(70.201947,37.587991),(70.216468,37.617137),(70.218432,37.617447),(70.237655,37.618118),(70.240963,37.617137),(70.246079,37.621271),(70.248301,37.623338),(70.253934,37.630805),(70.255225,37.637471),(70.253882,37.646592),(70.253572,37.654576),(70.257706,37.65809),(70.262564,37.660881),(70.275121,37.675479),(70.277033,37.687985),(70.280547,37.696046),(70.283079,37.704831),(70.281891,37.719559),(70.271762,37.748705),(70.269592,37.762632),(70.275121,37.774181),(70.265561,37.781209),(70.256517,37.791803),(70.249851,37.804877),(70.247164,37.819166),(70.240343,37.827563),(70.207476,37.835624),(70.196004,37.839914),(70.179158,37.860791),(70.165205,37.889911),(70.160503,37.920658),(70.17213,37.946083),(70.192232,37.93288),(70.214711,37.929262),(70.238121,37.932363),(70.26153,37.939287),(70.253675,37.947401),(70.250161,37.955617),(70.25042,37.964144),(70.253934,37.973394),(70.26091,37.976469),(70.272692,37.978174),(70.283751,37.981869),(70.288712,37.990809),(70.293776,37.996106),(70.298583,37.998134),(70.317961,38.006312),(70.326281,38.011273),(70.371187,38.058298),(70.415371,38.094523),(70.425964,38.100647),(70.460071,38.112248),(70.470303,38.120517),(70.482602,38.137363),(70.508543,38.192502),(70.537947,38.238055),(70.547197,38.262653),(70.559393,38.268182),(70.573036,38.27105),(70.583061,38.275081),(70.5966,38.309187),(70.596703,38.317585),(70.595566,38.327791),(70.595773,38.338178),(70.600011,38.347066),(70.609312,38.3512),(70.632102,38.350115),(70.641352,38.354197),(70.676698,38.37492),(70.68476,38.38665),(70.664865,38.398639),(70.664865,38.405409),(70.683313,38.414581),(70.741811,38.419439),(70.754213,38.436466),(70.761086,38.44352),(70.777261,38.446466),(70.808887,38.446362),(70.817982,38.444993),(70.834105,38.4406),(70.843045,38.440161),(70.849814,38.442823),(70.853587,38.447422),(70.859323,38.451659),(70.871002,38.45321),(70.91224,38.437655),(70.936217,38.433004),(70.946759,38.443236),(70.943452,38.465948),(70.950739,38.473053),(70.974045,38.473673),(70.986809,38.470909),(70.998229,38.465664),(71.008564,38.458584),(71.018641,38.449825),(71.024584,38.441918),(71.032956,38.423651),(71.039467,38.415331),(71.049802,38.408664)] +Albania [(19.747766,42.578901),(19.746009,42.579934),(19.741358,42.574405),(19.733916,42.562597),(19.732159,42.555543),(19.730299,42.540428),(19.730919,42.533658),(19.73433,42.524382),(19.75159,42.493402),(19.784456,42.474566),(19.801406,42.468132),(19.819596,42.466479),(19.829063,42.468723),(19.835512,42.470251),(19.873339,42.486839),(19.882538,42.493402),(19.882745,42.493557),(19.882745,42.493609),(19.907549,42.506399),(19.956332,42.505314),(19.981757,42.510765),(20.017723,42.546241),(20.039221,42.557765),(20.064956,42.546758),(20.085626,42.530015),(20.135546,42.509629),(20.152392,42.493712),(20.152599,42.493712),(20.152599,42.493609),(20.152702,42.493428),(20.152702,42.493402),(20.180814,42.443095),(20.186292,42.437437),(20.199728,42.427799),(20.204689,42.420099),(20.204379,42.411831),(20.194043,42.4001),(20.192803,42.393693),(20.197454,42.38744),(20.21306,42.377518),(20.218848,42.371446),(20.221225,42.36372),(20.219468,42.350207),(20.220915,42.343101),(20.229597,42.32672),(20.237762,42.319924),(20.249647,42.318607),(20.317964,42.319821),(20.333363,42.317883),(20.456973,42.250497),(20.473665,42.237123),(20.481674,42.230705),(20.500795,42.211223),(20.538622,42.150116),(20.549371,42.123476),(20.551954,42.105803),(20.552161,42.07379),(20.558259,42.055109),(20.589678,41.993639),(20.594329,41.973718),(20.59929,41.960567),(20.59929,41.94788),(20.588748,41.929586),(20.580583,41.921732),(20.573348,41.917675),(20.567251,41.912172),(20.562496,41.900105),(20.562703,41.892845),(20.567767,41.88052),(20.567147,41.873182),(20.541722,41.86158),(20.540786,41.844865),(20.540482,41.839437),(20.54844,41.814193),(20.550136,41.80006),(20.550921,41.793522),(20.54441,41.784763),(20.521155,41.767658),(20.511337,41.757943),(20.503275,41.744637),(20.500381,41.734095),(20.508339,41.661748),(20.513404,41.640405),(20.534591,41.594026),(20.53467,41.587324),(20.534694,41.585266),(20.52932,41.574879),(20.520845,41.568368),(20.507409,41.56227),(20.49294,41.557671),(20.444157,41.549661),(20.447878,41.53545),(20.444984,41.508475),(20.452012,41.493592),(20.463174,41.489768),(20.470822,41.483774),(20.481597,41.468269),(20.483535,41.46548),(20.486842,41.457781),(20.488909,41.441451),(20.490873,41.436025),(20.498004,41.431477),(20.514644,41.429462),(20.522189,41.42569),(20.534074,41.412977),(20.539049,41.402944),(20.540172,41.400678),(20.539965,41.387139),(20.532937,41.370447),(20.523429,41.356805),(20.510407,41.344403),(20.49604,41.337788),(20.481674,41.341199),(20.478108,41.321585),(20.477747,41.319598),(20.483121,41.289471),(20.500071,41.23552),(20.51268,41.210147),(20.549681,41.170615),(20.565494,41.147412),(20.570558,41.124829),(20.569938,41.107104),(20.576966,41.093513),(20.597419,41.086273),(20.605284,41.083488),(20.618927,41.082403),(20.631536,41.082868),(20.634129,41.082576),(20.643008,41.081576),(20.65386,41.075272),(20.664092,41.059149),(20.683419,40.99383),(20.702746,40.936314),(20.717216,40.913214),(20.730573,40.904611),(20.740883,40.89797),(20.766102,40.893732),(20.783672,40.899055),(20.816951,40.920242),(20.836544,40.923904),(20.837415,40.924066),(20.890228,40.918279),(20.939941,40.907065),(20.956684,40.894766),(20.964849,40.875956),(20.965262,40.849394),(20.967019,40.802007),(20.960922,40.780768),(20.943662,40.765265),(20.95348,40.759167),(20.957201,40.751622),(20.959165,40.743561),(20.963505,40.736068),(20.992031,40.7155),(21.018593,40.690902),(21.028825,40.676846),(21.035336,40.65938),(21.036679,40.639743),(21.033165,40.621398),(21.02252,40.586619),(21.020763,40.575096),(21.02035,40.566776),(21.018799,40.558972),(21.013528,40.548896),(21.006707,40.543211),(20.997509,40.53918),(20.98831,40.533496),(20.981489,40.523264),(20.96857,40.520577),(20.957924,40.514944),(20.95193,40.506056),(20.952653,40.493653),(20.94976,40.487866),(20.946452,40.482905),(20.93684,40.472518),(20.911932,40.459547),(20.889608,40.463733),(20.866767,40.472053),(20.839999,40.471639),(20.826666,40.464818),(20.821292,40.456395),(20.817365,40.446835),(20.8092,40.436603),(20.800311,40.432779),(20.779537,40.429006),(20.770649,40.421978),(20.768995,40.412573),(20.773336,40.38534),(20.773853,40.374901),(20.770442,40.36255),(20.765998,40.354282),(20.755043,40.338624),(20.739552,40.309166),(20.736646,40.303639),(20.728791,40.298265),(20.717836,40.293924),(20.706984,40.288085),(20.699129,40.278369),(20.694581,40.25558),(20.696648,40.235581),(20.696442,40.215066),(20.68528,40.191191),(20.679802,40.187832),(20.665022,40.18437),(20.660372,40.178892),(20.659855,40.172743),(20.663162,40.161684),(20.663472,40.15662),(20.668226,40.138068),(20.666779,40.13352),(20.651793,40.101016),(20.647556,40.09404),(20.640218,40.090112),(20.615361,40.081017),(20.577793,40.067271),(20.552885,40.065411),(20.499865,40.071457),(20.481674,40.067788),(20.465965,40.060812),(20.432789,40.063809),(20.413772,40.057194),(20.400439,40.045257),(20.38907,40.029444),(20.380699,40.011667),(20.376461,39.993736),(20.359925,39.991048),(20.310005,39.98986),(20.297913,39.986914),(20.302977,39.979111),(20.317964,39.918391),(20.323131,39.912397),(20.346902,39.894259),(20.392998,39.835451),(20.397028,39.818087),(20.388967,39.79814),(20.371604,39.784291),(20.35455,39.78579),(20.336877,39.794006),(20.299577,39.805056),(20.298326,39.805427),(20.288405,39.806615),(20.280033,39.80398),(20.273005,39.796487),(20.275485,39.792404),(20.281377,39.788167),(20.284684,39.780312),(20.283134,39.775144),(20.276829,39.763155),(20.275692,39.760055),(20.278173,39.756748),(20.285511,39.749668),(20.287268,39.746671),(20.291092,39.737937),(20.296466,39.733493),(20.299463,39.728222),(20.296466,39.71737),(20.28272,39.704399),(20.264117,39.696079),(20.249027,39.684814),(20.24603,39.662903),(20.237245,39.667037),(20.228563,39.669156),(20.220088,39.669156),(20.212027,39.667037),(20.204172,39.660319),(20.203035,39.65262),(20.203449,39.645333),(20.199935,39.640062),(20.184122,39.637013),(20.163761,39.6443),(20.135236,39.664195),(20.089347,39.682799),(20.049556,39.69272),(20.01607,39.701402),(19.99991,39.693498),(19.999848,39.693508),(19.996837,39.692572),(19.99586,39.686713),(19.989024,39.686713),(19.983572,39.701361),(19.98699,39.717963),(20.002696,39.748236),(19.985606,39.75373),(19.980642,39.75731),(19.99586,39.782945),(20.014171,39.832953),(20.016287,39.845038),(20.009776,39.865668),(19.999278,39.871405),(19.983735,39.872382),(19.961681,39.878567),(19.960216,39.881049),(19.959972,39.885077),(19.958832,39.88935),(19.954845,39.892808),(19.941173,39.898993),(19.931163,39.901923),(19.914073,39.902411),(19.906423,39.90644),(19.906423,39.912665),(19.921235,39.926947),(19.931,39.934516),(19.941173,39.940009),(19.923839,39.952826),(19.876801,40.022366),(19.870453,40.034735),(19.863455,40.045356),(19.855235,40.049872),(19.823253,40.050605),(19.807384,40.052883),(19.79656,40.057318),(19.804535,40.063463),(19.777354,40.077786),(19.773123,40.071234),(19.771658,40.068305),(19.770518,40.063463),(19.767263,40.072455),(19.762462,40.07685),(19.756358,40.079901),(19.74936,40.084621),(19.748057,40.088609),(19.740896,40.100409),(19.732677,40.110256),(19.729015,40.108222),(19.719086,40.116034),(19.653168,40.132392),(19.59783,40.157701),(19.565766,40.179836),(19.509288,40.194485),(19.476248,40.21369),(19.381114,40.295233),(19.369965,40.309027),(19.365082,40.317369),(19.351573,40.362047),(19.344249,40.374335),(19.309255,40.400824),(19.296886,40.41356),(19.295177,40.417548),(19.295177,40.418687),(19.289561,40.420396),(19.289561,40.427232),(19.316173,40.437812),(19.33253,40.43891),(19.348155,40.43065),(19.3838,40.397406),(19.39324,40.386298),(19.406505,40.362616),(19.411957,40.34809),(19.414236,40.334418),(19.423595,40.330024),(19.444591,40.333808),(19.465587,40.341498),(19.474946,40.348375),(19.481619,40.439114),(19.47877,40.453925),(19.453136,40.465318),(19.418793,40.491889),(19.391368,40.521796),(19.386404,40.54328),(19.39324,40.537055),(19.396007,40.529608),(19.398611,40.520941),(19.406749,40.522773),(19.414236,40.522773),(19.433604,40.505927),(19.446056,40.511135),(19.452647,40.529853),(19.4546,40.55386),(19.442149,40.573065),(19.415701,40.583482),(19.391612,40.578315),(19.386404,40.550727),(19.379242,40.566148),(19.309825,40.644355),(19.304373,40.653144),(19.309337,40.665025),(19.322927,40.674872),(19.339041,40.684068),(19.351573,40.694159),(19.360525,40.709784),(19.364513,40.726508),(19.365571,40.785956),(19.368826,40.802151),(19.377778,40.812974),(19.396251,40.817043),(19.406749,40.820746),(19.404063,40.829291),(19.396739,40.83869),(19.39324,40.844916),(19.397634,40.852973),(19.404796,40.86107),(19.411388,40.867092),(19.414236,40.868842),(19.406261,40.880316),(19.391124,40.89525),(19.381196,40.908271),(19.389822,40.913804),(19.404959,40.918158),(19.424571,40.939643),(19.440929,40.948635),(19.427013,40.936835),(19.435395,40.913398),(19.427257,40.893378),(19.427257,40.87226),(19.434744,40.87226),(19.437836,40.886542),(19.437673,40.88345),(19.439138,40.880072),(19.440929,40.87226),(19.454112,40.88581),(19.506602,40.905097),(19.523448,40.92064),(19.525157,40.945258),(19.514659,40.964911),(19.501475,40.982978),(19.495453,41.002631),(19.492035,40.976955),(19.479666,40.953925),(19.453868,40.923977),(19.453461,40.928371),(19.447765,40.934312),(19.458507,40.942613),(19.469981,40.956732),(19.477224,40.975002),(19.474946,40.995795),(19.469981,41.000718),(19.453787,41.005845),(19.447765,41.009467),(19.440603,41.020657),(19.441254,41.026028),(19.445486,41.030707),(19.456391,41.106676),(19.451182,41.122707),(19.445486,41.129462),(19.441173,41.137356),(19.441905,41.143866),(19.463715,41.151313),(19.467133,41.162665),(19.467133,41.176174),(19.468761,41.187567),(19.509532,41.237291),(19.516612,41.256415),(19.513357,41.276679),(19.50294,41.294135),(19.488048,41.306464),(19.471934,41.311103),(19.450043,41.311103),(19.431651,41.313707),(19.418956,41.322577),(19.414236,41.341498),(19.414236,41.382799),(19.410818,41.391669),(19.396007,41.402045),(19.39324,41.41352),(19.406423,41.400377),(19.428722,41.401313),(19.44516,41.415188),(19.440929,41.440863),(19.46461,41.450873),(19.489268,41.466132),(19.508637,41.486884),(19.516612,41.513414),(19.514171,41.529975),(19.507172,41.536282),(19.496349,41.538764),(19.482432,41.54385),(19.468028,41.554267),(19.451996,41.574774),(19.440929,41.585395),(19.528087,41.576565),(19.556407,41.583075),(19.565196,41.58511),(19.584809,41.619574),(19.591645,41.619574),(19.592296,41.608588),(19.596039,41.602729),(19.603038,41.601752),(19.612966,41.605292),(19.604991,41.632148),(19.600108,41.639106),(19.591645,41.632636),(19.587087,41.640692),(19.557628,41.660549),(19.578136,41.687649),(19.576345,41.71894),(19.571137,41.752387),(19.5713,41.770413),(19.589529,41.765692),(19.598969,41.778713),(19.599783,41.79975),(19.591645,41.818793),(19.585216,41.818549),(19.465505,41.855455),(19.451182,41.862535),(19.432953,41.868598),(19.365122,41.852372),(19.364223,41.862846),(19.364947,41.888995),(19.356989,41.89964),(19.347687,41.906358),(19.34531,41.910337),(19.34593,41.914471),(19.345413,41.921189),(19.346653,41.926176),(19.350477,41.931369),(19.352854,41.938501),(19.346447,41.961548),(19.351614,41.965166),(19.359779,41.965993),(19.365774,41.969713),(19.371045,41.98656),(19.363707,41.993484),(19.363396,41.993639),(19.354198,42.008703),(19.350581,42.027823),(19.351718,42.047615),(19.356575,42.064798),(19.374869,42.094667),(19.372491,42.104253),(19.369998,42.106507),(19.355025,42.12004),(19.297767,42.151666),(19.282058,42.164559),(19.281956,42.164723),(19.272033,42.180682),(19.274926,42.191276),(19.304589,42.215099),(19.400397,42.325893),(19.401327,42.331061),(19.400707,42.344755),(19.402671,42.352015),(19.412076,42.368397),(19.417243,42.374107),(19.468403,42.41811),(19.481735,42.434491),(19.501476,42.444129),(19.517806,42.45803),(19.531655,42.474773),(19.543747,42.493402),(19.543747,42.493557),(19.549328,42.508595),(19.561317,42.516243),(19.575683,42.522341),(19.588086,42.532857),(19.593667,42.54482),(19.599248,42.571046),(19.605035,42.584844),(19.621779,42.604997),(19.647927,42.627838),(19.658037,42.634613),(19.676039,42.646675),(19.699293,42.654814),(19.722134,42.64608),(19.737534,42.624402),(19.746009,42.5989),(19.746885,42.58893),(19.747766,42.578901)] +Andorra [(1.707006,42.502781),(1.697498,42.494462),(1.686336,42.490612),(1.674244,42.490508),(1.662358,42.493712),(1.659774,42.496813),(1.656984,42.49764),(1.653986,42.496529),(1.650369,42.493402),(1.639517,42.466427),(1.607478,42.456428),(1.544432,42.450356),(1.538851,42.445653),(1.534511,42.439917),(1.528206,42.434233),(1.51663,42.429504),(1.508466,42.428677),(1.447901,42.434646),(1.436429,42.440951),(1.436429,42.453482),(1.407593,42.486762),(1.424543,42.492472),(1.430227,42.493557),(1.449968,42.504073),(1.446557,42.519886),(1.428987,42.531462),(1.406456,42.52924),(1.409764,42.540609),(1.4263,42.561796),(1.426403,42.565646),(1.418032,42.569832),(1.419272,42.579263),(1.424853,42.589365),(1.429297,42.595386),(1.451415,42.602052),(1.466814,42.641455),(1.49844,42.640241),(1.527793,42.648535),(1.543089,42.649362),(1.597349,42.621921),(1.608304,42.618123),(1.721993,42.609855),(1.713311,42.589546),(1.729434,42.582001),(1.752688,42.576679),(1.761107,42.567646),(1.765091,42.563372),(1.739976,42.561641),(1.721683,42.548515),(1.710624,42.527741),(1.707006,42.502781)] +Ashmore and Cartier Islands [(123.597016,-12.428318),(123.597748,-12.438572),(123.575613,-12.436782),(123.575043,-12.426609),(123.597016,-12.428318)] +Austria [(15.161792,48.937221),(15.238067,48.95076),(15.243234,48.95293),(15.257084,48.963886),(15.260391,48.969157),(15.262872,48.982593),(15.266902,48.986675),(15.27455,48.986727),(15.279615,48.982593),(15.283749,48.977632),(15.28871,48.975358),(15.335529,48.974996),(15.357853,48.97081),(15.405912,48.954687),(15.450354,48.944817),(15.471851,48.936704),(15.521254,48.908489),(15.544187,48.902612),(15.603729,48.887353),(15.681347,48.858466),(15.703775,48.854952),(15.726823,48.854952),(15.743669,48.858466),(15.779222,48.870868),(15.787904,48.872263),(15.818497,48.872315),(15.824284,48.869421),(15.828315,48.857122),(15.833276,48.852006),(15.840097,48.850094),(15.859218,48.849164),(15.870173,48.843893),(15.877614,48.841671),(15.885986,48.842033),(15.875754,48.833093),(15.888363,48.835056),(15.899629,48.834746),(15.90707,48.830251),(15.908103,48.819709),(15.925053,48.822602),(15.930324,48.818313),(15.930324,48.811389),(15.931771,48.806428),(16.032334,48.758059),(16.085354,48.742866),(16.177751,48.746535),(16.317588,48.73284),(16.318724,48.733512),(16.339498,48.735579),(16.352727,48.728448),(16.358309,48.727259),(16.374018,48.730308),(16.384974,48.737078),(16.43572,48.794542),(16.453083,48.80219),(16.481919,48.7994),(16.492254,48.79971),(16.510341,48.804774),(16.519539,48.805601),(16.528737,48.803534),(16.545791,48.796299),(16.605529,48.784827),(16.624029,48.78338),(16.643149,48.778264),(16.651004,48.766223),(16.654725,48.751857),(16.661959,48.740023),(16.675085,48.733926),(16.691001,48.732065),(16.729035,48.733099),(16.744332,48.729637),(16.780505,48.713772),(16.798902,48.709224),(16.818125,48.710775),(16.856573,48.719818),(16.873006,48.718991),(16.896674,48.696977),(16.910523,48.63078),(16.945043,48.604166),(16.954345,48.557399),(16.949055,48.544836),(16.946903,48.539726),(16.93047,48.528202),(16.913934,48.519339),(16.906492,48.509908),(16.901221,48.496602),(16.875073,48.471539),(16.864944,48.458077),(16.86081,48.443788),(16.851922,48.390407),(16.849338,48.384102),(16.846858,48.381131),(16.845101,48.376583),(16.84448,48.365602),(16.847581,48.359582),(16.855332,48.356455),(16.875486,48.355034),(16.881171,48.352812),(16.891713,48.347024),(16.901945,48.339402),(16.906492,48.33147),(16.904218,48.327025),(16.900291,48.321238),(16.898431,48.316173),(16.902771,48.314106),(16.905459,48.311988),(16.908869,48.306975),(16.912073,48.301239),(16.913313,48.296691),(16.916621,48.2908),(16.924269,48.287519),(16.933364,48.284728),(16.944423,48.27801),(16.950624,48.276589),(16.954345,48.273127),(16.955275,48.268786),(16.953931,48.25734),(16.954345,48.25256),(16.969951,48.216645),(16.974705,48.198558),(16.974808,48.17688),(16.98194,48.161299),(17.007158,48.142799),(17.020904,48.137166),(17.036923,48.135513),(17.047465,48.130991),(17.062455,48.112724),(17.067206,48.106936),(17.080228,48.097608),(17.069996,48.089159),(17.064829,48.07903),(17.059144,48.060427),(17.063072,48.058773),(17.075061,48.052081),(17.069686,48.035674),(17.092631,48.02725),(17.12498,48.019525),(17.148338,48.005443),(17.085603,47.970148),(17.096145,47.961931),(17.095731,47.95573),(17.090874,47.949477),(17.088083,47.940899),(17.086119,47.93922),(17.076818,47.934956),(17.07413,47.932114),(17.075164,47.927773),(17.080125,47.925758),(17.085396,47.924621),(17.087463,47.922632),(17.083329,47.904829),(17.077541,47.891729),(17.067619,47.881626),(17.051186,47.872893),(17.016563,47.867699),(17.004057,47.863281),(17.004367,47.852377),(17.010672,47.847882),(17.031652,47.841345),(17.039507,47.837365),(17.049119,47.818684),(17.05563,47.812354),(17.040644,47.801114),(17.041988,47.783906),(17.048706,47.763649),(17.050566,47.730989),(17.055527,47.720913),(17.064002,47.71329),(17.075371,47.708484),(17.054804,47.702025),(16.98194,47.695436),(16.902668,47.682026),(16.864738,47.686729),(16.850165,47.712929),(16.836936,47.705358),(16.817299,47.684248),(16.80624,47.676884),(16.797455,47.675463),(16.741128,47.681458),(16.730379,47.685902),(16.719217,47.693731),(16.711569,47.704066),(16.707848,47.714608),(16.702474,47.7236),(16.689865,47.729568),(16.609766,47.750627),(16.567805,47.754192),(16.531115,47.742978),(16.52512,47.733315),(16.526877,47.720137),(16.521399,47.711533),(16.512924,47.706004),(16.47303,47.691767),(16.461145,47.684532),(16.45453,47.681768),(16.449879,47.682414),(16.444918,47.68554),(16.43913,47.690475),(16.431792,47.685463),(16.4166,47.668823),(16.407815,47.66133),(16.425901,47.654276),(16.481919,47.638954),(16.509617,47.64314),(16.575453,47.624949),(16.608422,47.628773),(16.63023,47.622004),(16.647697,47.606139),(16.656172,47.585934),(16.65059,47.566555),(16.66754,47.560096),(16.68139,47.550561),(16.689141,47.53803),(16.688004,47.52263),(16.677359,47.509866),(16.648213,47.501546),(16.636845,47.4932),(16.640875,47.452919),(16.626973,47.445549),(16.589406,47.425633),(16.481919,47.392302),(16.46993,47.405531),(16.456597,47.411836),(16.444091,47.40951),(16.433963,47.39685),(16.436443,47.358506),(16.434273,47.35556),(16.429312,47.353803),(16.424971,47.351116),(16.424351,47.345199),(16.427142,47.341375),(16.431689,47.339721),(16.436133,47.338559),(16.43882,47.336569),(16.469206,47.293238),(16.473237,47.276805),(16.466622,47.263421),(16.452463,47.254584),(16.421354,47.243138),(16.421354,47.243061),(16.421354,47.243035),(16.424661,47.225594),(16.409262,47.203683),(16.412776,47.187173),(16.41877,47.183659),(16.426728,47.184124),(16.4351,47.183581),(16.441818,47.177121),(16.442128,47.168336),(16.433963,47.151283),(16.433653,47.145754),(16.447089,47.139708),(16.480885,47.150767),(16.497318,47.149681),(16.509514,47.137537),(16.50476,47.125833),(16.481919,47.10524),(16.460835,47.0963),(16.454323,47.081701),(16.461765,47.068498),(16.481919,47.063898),(16.493701,47.059816),(16.497215,47.054622),(16.493184,47.049145),(16.481919,47.04421),(16.437167,47.031782),(16.424661,47.024082),(16.45329,47.021679),(16.467553,47.018423),(16.481919,47.00938),(16.486363,46.998554),(16.467449,46.995427),(16.441404,46.99522),(16.424764,46.993102),(16.424764,46.992998),(16.420424,46.99026),(16.415566,46.989433),(16.410398,46.990415),(16.405024,46.993153),(16.387764,47.002042),(16.366577,47.003825),(16.325856,47.00044),(16.288545,47.005582),(16.274903,47.004315),(16.265394,46.993257),(16.261054,46.97809),(16.252992,46.973516),(16.24307,46.972018),(16.232942,46.966075),(16.230358,46.959977),(16.231185,46.954422),(16.230668,46.94835),(16.22395,46.941064),(16.217025,46.937395),(16.196148,46.931297),(16.170723,46.918533),(16.159148,46.910316),(16.122871,46.876365),(16.110055,46.867916),(16.094035,46.862774),(16.052936,46.84606),(16.032024,46.837556),(16.028441,46.836947),(15.987582,46.830011),(15.981691,46.827685),(15.971976,46.820632),(15.972906,46.818435),(15.97735,46.816213),(15.978177,46.809134),(15.971252,46.778076),(15.970985,46.77505),(15.969702,46.760532),(15.970529,46.743014),(15.982001,46.718545),(16.003291,46.709191),(16.014557,46.693714),(16.016723,46.670691),(16.016727,46.670641),(16.016593,46.670757),(15.997917,46.686919),(15.986962,46.69219),(15.946344,46.697151),(15.878545,46.720715),(15.850743,46.724488),(15.822941,46.722834),(15.78461,46.7122),(15.755141,46.704024),(15.728683,46.70299),(15.652098,46.710819),(15.635975,46.717563),(15.632875,46.702473),(15.632978,46.689632),(15.626984,46.680873),(15.621745,46.678175),(15.616648,46.67555),(15.603729,46.673018),(15.58864,46.675963),(15.567349,46.675757),(15.545955,46.671881),(15.530659,46.663845),(15.52084,46.649608),(15.520308,46.64772),(15.517636,46.63824),(15.513939,46.632545),(15.511228,46.628369),(15.492625,46.618293),(15.462653,46.614649),(15.440018,46.62439),(15.435381,46.627195),(15.417591,46.637955),(15.388135,46.645578),(15.332784,46.64358),(15.204891,46.638963),(15.172557,46.64136),(15.105591,46.646323),(15.085723,46.647795),(15.061954,46.649557),(15.004386,46.636844),(14.967179,46.600257),(14.947955,46.619274),(14.933589,46.621135),(14.919507,46.615017),(14.897726,46.605554),(14.894063,46.605215),(14.877055,46.603642),(14.862999,46.604831),(14.85039,46.601136),(14.833647,46.584393),(14.822278,46.567546),(14.814519,46.551337),(14.807189,46.536024),(14.796663,46.519401),(14.788585,46.506646),(14.783004,46.503261),(14.760887,46.496284),(14.735255,46.493339),(14.726367,46.497706),(14.709727,46.492512),(14.703733,46.487758),(14.698772,46.480962),(14.687093,46.471221),(14.679961,46.458871),(14.672546,46.459791),(14.666629,46.460524),(14.662081,46.459698),(14.642031,46.445228),(14.631696,46.440577),(14.621567,46.43851),(14.599863,46.437167),(14.590148,46.434428),(14.575368,46.419726),(14.566997,46.400373),(14.562108,46.391737),(14.557695,46.38394),(14.540332,46.378643),(14.527102,46.388229),(14.515837,46.40536),(14.502194,46.418356),(14.467675,46.412672),(14.450931,46.414481),(14.437145,46.418884),(14.420029,46.424351),(14.414448,46.429002),(14.411244,46.434635),(14.40649,46.439337),(14.395844,46.440991),(14.362151,46.435875),(14.242323,46.438237),(14.149865,46.440061),(14.147933,46.440425),(14.137255,46.442438),(14.081032,46.47595),(14.066355,46.48104),(14.050026,46.484399),(14.032456,46.484709),(14.014922,46.482531),(13.998763,46.480523),(13.98233,46.481918),(13.890862,46.511787),(13.860683,46.51525),(13.795778,46.507886),(13.782135,46.507782),(13.716093,46.518867),(13.700951,46.519746),(13.685345,46.517627),(13.670256,46.518712),(13.549229,46.545842),(13.506751,46.546927),(13.499103,46.550622),(13.484944,46.561733),(13.478019,46.563567),(13.417041,46.560492),(13.373323,46.565789),(13.271417,46.550777),(13.231109,46.552173),(13.210025,46.558012),(13.146463,46.584961),(13.064504,46.598035),(12.83041,46.609637),(12.773566,46.635191),(12.7485,46.640996),(12.739873,46.642994),(12.732018,46.64227),(12.715999,46.637955),(12.706593,46.637749),(12.697395,46.640539),(12.679205,46.650022),(12.671368,46.652466),(12.669593,46.653019),(12.62019,46.656481),(12.562003,46.65121),(12.547327,46.652192),(12.53079,46.65767),(12.499888,46.672139),(12.469632,46.675799),(12.445627,46.678702),(12.40501,46.690123),(12.370387,46.711155),(12.351473,46.743246),(12.342688,46.765131),(12.326048,46.772495),(12.305274,46.774459),(12.284397,46.779988),(12.274785,46.784639),(12.269101,46.788566),(12.266724,46.795336),(12.26693,46.808255),(12.269618,46.819831),(12.273338,46.826755),(12.276129,46.83399),(12.275819,46.846289),(12.26662,46.868148),(12.250807,46.875615),(12.208743,46.876623),(12.1951,46.880085),(12.189002,46.884943),(12.183525,46.891222),(12.172156,46.89918),(12.160994,46.90303),(12.137429,46.905924),(12.126887,46.908869),(12.141563,46.918843),(12.141667,46.927989),(12.134742,46.937446),(12.128231,46.948582),(12.122133,46.971656),(12.117792,46.983076),(12.111178,46.992998),(12.12172,47.010517),(12.182284,47.033616),(12.203575,47.053331),(12.203897,47.067012),(12.204195,47.079686),(12.180631,47.085215),(12.133146,47.078832),(12.116242,47.076559),(12.014956,47.040489),(11.943643,47.038164),(11.899511,47.027725),(11.857033,47.012015),(11.822513,46.993257),(11.777141,46.988296),(11.766082,46.983438),(11.746445,46.972457),(11.73487,46.970622),(11.716163,46.97548),(11.683814,46.991913),(11.664797,46.993257),(11.657252,46.992533),(11.649707,46.992998),(11.648467,46.993257),(11.64795,46.993257),(11.59648,47.00044),(11.572709,46.998915),(11.543667,46.993102),(11.543564,46.993102),(11.543357,46.992998),(11.543254,46.992998),(11.533849,46.989536),(11.524443,46.988347),(11.515348,46.989484),(11.506977,46.992998),(11.501706,46.997856),(11.495918,47.001602),(11.489407,47.004212),(11.471837,47.00708),(11.461812,47.005504),(11.452923,47.000879),(11.445275,46.993102),(11.445172,46.992998),(11.411169,46.970493),(11.380576,46.971553),(11.349467,46.98194),(11.31381,46.987262),(11.243737,46.979252),(11.174491,46.963853),(11.156611,46.956515),(11.091912,46.912435),(11.083643,46.900136),(11.073101,46.86497),(11.054291,46.834145),(11.053464,46.830321),(11.054601,46.819934),(11.052844,46.814921),(11.048503,46.811692),(11.037445,46.808255),(11.033311,46.805568),(11.010883,46.779213),(10.99693,46.76911),(10.982668,46.767741),(10.965718,46.771642),(10.930888,46.773994),(10.913731,46.77234),(10.880348,46.764589),(10.870426,46.764072),(10.860195,46.766991),(10.843141,46.777043),(10.83415,46.780246),(10.823918,46.78035),(10.804901,46.776629),(10.795082,46.776888),(10.76635,46.788101),(10.754775,46.790763),(10.733691,46.786189),(10.722942,46.786448),(10.716947,46.795207),(10.721598,46.800142),(10.743819,46.812518),(10.748677,46.819443),(10.738962,46.829546),(10.662481,46.860965),(10.647081,46.863756),(10.629408,46.862412),(10.527708,46.843214),(10.486264,46.846366),(10.453811,46.864427),(10.451434,46.88577),(10.463836,46.919747),(10.458462,46.936619),(10.449574,46.943906),(10.415571,46.962406),(10.394693,46.985402),(10.384358,46.992998),(10.384358,46.993153),(10.384255,46.993153),(10.378984,46.995505),(10.373403,46.996254),(10.367925,46.995505),(10.338883,46.98411),(10.313665,46.964318),(10.296198,46.941374),(10.295681,46.922693),(10.270773,46.921892),(10.251343,46.92538),(10.235116,46.923313),(10.219924,46.905769),(10.215169,46.893108),(10.214342,46.884685),(10.211655,46.877036),(10.201423,46.86683),(10.157808,46.851612),(10.13197,46.846573),(10.125188,46.846751),(10.1113,46.847116),(10.068098,46.856624),(10.045567,46.865564),(10.006913,46.890757),(9.899943,46.914398),(9.875138,46.927421),(9.862426,46.939772),(9.860772,46.949151),(9.863976,46.959925),(9.866457,46.983387),(9.870591,46.992947),(9.870591,46.998838),(9.866767,47.001938),(9.860566,47.001602),(9.856328,47.004083),(9.857982,47.015478),(9.669053,47.056199),(9.65231,47.05793),(9.59991,47.053486),(9.581203,47.05687),(9.608798,47.080771),(9.615723,47.106764),(9.605594,47.132266),(9.581823,47.154901),(9.552057,47.16689),(9.551954,47.175571),(9.561876,47.190609),(9.562909,47.19774),(9.554331,47.211615),(9.544823,47.220323),(9.540378,47.229108),(9.547096,47.243035),(9.53025,47.253654),(9.521155,47.262801),(9.553298,47.299853),(9.587404,47.32781),(9.591228,47.334683),(9.596396,47.352305),(9.601047,47.36127),(9.639804,47.394524),(9.649519,47.409717),(9.650346,47.452092),(9.621717,47.469197),(9.58451,47.480721),(9.554951,47.5109),(9.553059,47.516891),(9.547482,47.534547),(9.549887,47.533534),(9.554144,47.532743),(9.612622,47.521881),(9.676701,47.52263),(9.703986,47.531415),(9.718455,47.546711),(9.730858,47.564901),(9.752665,47.582058),(9.767135,47.587277),(9.782121,47.588414),(9.79628,47.584952),(9.807959,47.576322),(9.811266,47.564488),(9.809303,47.552318),(9.813127,47.54175),(9.833487,47.534619),(9.841549,47.535032),(9.853848,47.540407),(9.858912,47.541337),(9.888988,47.533792),(9.918753,47.53219),(9.933843,47.534206),(9.945935,47.540769),(9.948726,47.524232),(9.959164,47.514879),(9.97167,47.506404),(9.980765,47.492942),(9.980765,47.489919),(9.981075,47.48687),(9.982625,47.481031),(9.993581,47.476586),(10.002366,47.47917),(10.011254,47.484441),(10.022623,47.487955),(10.071819,47.439121),(10.080604,47.42739),(10.075953,47.416874),(10.053215,47.40486),(10.064171,47.396178),(10.066858,47.385791),(10.067788,47.375042),(10.073162,47.365482),(10.082878,47.359074),(10.089596,47.359281),(10.097244,47.363131),(10.11037,47.367394),(10.11533,47.366955),(10.125666,47.362692),(10.130833,47.362666),(10.135071,47.364888),(10.146956,47.373802),(10.190881,47.379228),(10.209278,47.372484),(10.208555,47.354475),(10.190468,47.317475),(10.192742,47.310912),(10.193259,47.304917),(10.190778,47.298251),(10.18592,47.294995),(10.172691,47.292308),(10.168661,47.290422),(10.159462,47.279131),(10.155431,47.272878),(10.159876,47.271121),(10.174951,47.272376),(10.239354,47.277735),(10.261161,47.283497),(10.305913,47.302178),(10.325447,47.314322),(10.34343,47.330756),(10.365651,47.361115),(10.371646,47.367394),(10.381981,47.372122),(10.403065,47.377109),(10.411643,47.381037),(10.428283,47.396049),(10.442856,47.41628),(10.451951,47.438759),(10.451744,47.460205),(10.44761,47.472581),(10.442236,47.481392),(10.433657,47.487852),(10.419601,47.493045),(10.42973,47.532914),(10.43097,47.542164),(10.424356,47.553352),(10.415674,47.564385),(10.414227,47.573015),(10.429213,47.57702),(10.445956,47.579061),(10.453604,47.581102),(10.457118,47.579242),(10.461563,47.569914),(10.460322,47.565987),(10.455465,47.561181),(10.451744,47.554825),(10.453501,47.546246),(10.458772,47.541647),(10.466937,47.53772),(10.482543,47.532862),(10.525125,47.52847),(10.536907,47.529865),(10.549619,47.536789),(10.569876,47.555936),(10.583726,47.562473),(10.60791,47.562266),(10.739892,47.52847),(10.743923,47.525317),(10.74723,47.52015),(10.752191,47.515395),(10.760769,47.513638),(10.790328,47.516067),(10.830636,47.528573),(10.844795,47.531312),(10.858644,47.530666),(10.86929,47.526583),(10.892234,47.514879),(10.883862,47.508006),(10.851616,47.493097),(10.858438,47.485165),(10.909907,47.46899),(10.959827,47.432506),(10.962824,47.427959),(10.963134,47.421241),(10.96086,47.414316),(10.957656,47.409717),(10.955279,47.409614),(10.965511,47.396075),(10.979464,47.390545),(11.083747,47.389512),(11.10328,47.393568),(11.168599,47.424264),(11.193818,47.428941),(11.215212,47.422998),(11.213041,47.395816),(11.237019,47.393956),(11.258827,47.400725),(11.273089,47.411112),(11.286318,47.423205),(11.305645,47.4354),(11.324249,47.439431),(11.367657,47.440129),(11.383884,47.444857),(11.392462,47.454779),(11.388638,47.46222),(11.377786,47.467052),(11.365487,47.469326),(11.412616,47.506094),(11.435353,47.509711),(11.459951,47.507437),(11.482585,47.50258),(11.529508,47.507851),(11.551212,47.51369),(11.569402,47.527384),(11.574466,47.536634),(11.582321,47.559785),(11.589142,47.570379),(11.617048,47.586761),(11.620458,47.589654),(11.638958,47.589241),(11.682573,47.58335),(11.764015,47.583117),(11.820343,47.575288),(11.830678,47.577614),(11.840703,47.594615),(11.851969,47.599163),(11.935891,47.610738),(12.165645,47.603969),(12.173603,47.60508),(12.202128,47.629833),(12.205745,47.636215),(12.206779,47.645568),(12.205125,47.672285),(12.202335,47.677789),(12.197271,47.680088),(12.189106,47.685566),(12.181768,47.692129),(12.178564,47.697658),(12.1766,47.705823),(12.192413,47.710164),(12.216494,47.723703),(12.225176,47.727372),(12.239749,47.731687),(12.242229,47.732023),(12.239128,47.72745),(12.236545,47.716778),(12.233031,47.708872),(12.226623,47.702878),(12.223315,47.695901),(12.228793,47.684868),(12.238715,47.6789),(12.249567,47.680011),(12.271891,47.687891),(12.293699,47.69001),(12.351473,47.68169),(12.368423,47.683551),(12.407697,47.693731),(12.42413,47.69156),(12.428781,47.685798),(12.43922,47.664482),(12.444697,47.656291),(12.452759,47.649754),(12.482524,47.633579),(12.49658,47.628903),(12.517148,47.628541),(12.538232,47.631331),(12.553838,47.636008),(12.563375,47.641761),(12.598383,47.66288),(12.6174,47.669339),(12.653057,47.675127),(12.688713,47.675127),(12.744834,47.66536),(12.761991,47.666859),(12.751655,47.649392),(12.767365,47.63637),(12.793307,47.624794),(12.81315,47.611824),(12.785865,47.602677),(12.773669,47.5795),(12.77894,47.554825),(12.803642,47.541337),(12.819041,47.539528),(12.828446,47.537255),(12.836921,47.532655),(12.882603,47.498575),(12.931593,47.473512),(12.942548,47.470489),(12.951023,47.472478),(12.959291,47.475527),(12.96973,47.475734),(12.979342,47.472246),(12.984923,47.468267),(12.991124,47.465683),(13.001873,47.466019),(13.008797,47.470101),(13.037323,47.493045),(13.037013,47.501365),(13.034429,47.507437),(13.031225,47.512553),(13.028951,47.518031),(13.028124,47.524232),(13.028124,47.541647),(13.030605,47.544257),(13.040113,47.560457),(13.04125,47.561904),(13.03908,47.561336),(13.038253,47.584022),(13.04094,47.58335),(13.057063,47.597664),(13.057683,47.600429),(13.069569,47.620247),(13.072049,47.622417),(13.07422,47.63451),(13.07484,47.646654),(13.072049,47.659469),(13.064091,47.67399),(13.044557,47.696573),(13.032258,47.706624),(13.019856,47.712929),(13.004353,47.714608),(12.979032,47.707089),(12.964045,47.705358),(12.908338,47.71236),(12.892009,47.723548),(12.910612,47.742927),(12.910819,47.74303),(12.910819,47.743082),(12.917227,47.750161),(12.918984,47.756776),(12.919294,47.763184),(12.921257,47.76954),(12.926735,47.777395),(12.991227,47.847106),(12.986576,47.850259),(12.964976,47.871963),(12.931076,47.924879),(12.914229,47.93599),(12.906168,47.93891),(12.886014,47.952888),(12.862036,47.962552),(12.853975,47.970484),(12.8486,47.980948),(12.848246,47.982389),(12.845603,47.993144),(12.830617,48.015468),(12.760234,48.064871),(12.750932,48.074741),(12.742043,48.086782),(12.736979,48.099959),(12.738943,48.113447),(12.745041,48.12063),(12.751449,48.122103),(12.75796,48.121896),(12.764058,48.123756),(12.77832,48.138717),(12.782351,48.142024),(12.822142,48.160679),(12.835164,48.170704),(12.853458,48.18998),(12.862553,48.196646),(12.877642,48.202046),(12.93304,48.209255),(12.931696,48.211632),(12.947199,48.220004),(12.979445,48.232018),(13.016652,48.255893),(13.032775,48.263567),(13.136438,48.291059),(13.274207,48.307104),(13.307797,48.319636),(13.405569,48.376583),(13.419522,48.392164),(13.425206,48.413377),(13.42717,48.418544),(13.431717,48.423712),(13.436161,48.430585),(13.438228,48.440998),(13.436368,48.469239),(13.438228,48.478541),(13.442983,48.487713),(13.456418,48.506653),(13.459209,48.516394),(13.457039,48.525179),(13.447737,48.534816),(13.443706,48.552851),(13.440709,48.557347),(13.440089,48.560965),(13.445566,48.567915),(13.454558,48.573445),(13.487218,48.581584),(13.520704,48.584581),(13.624367,48.565357),(13.641834,48.559104),(13.65806,48.551094),(13.673356,48.535488),(13.714336,48.523215),(13.716506,48.521691),(13.725394,48.548381),(13.733869,48.559776),(13.73728,48.559259),(13.758054,48.561481),(13.766012,48.563755),(13.77428,48.569207),(13.779034,48.573935),(13.796191,48.598585),(13.802392,48.611711),(13.805493,48.626129),(13.806216,48.642923),(13.800945,48.675221),(13.803529,48.687159),(13.816862,48.695582),(13.804356,48.699561),(13.799395,48.70261),(13.78875,48.716511),(13.783582,48.71527),(13.785856,48.724779),(13.815725,48.76643),(13.855929,48.759299),(13.874946,48.752426),(13.893136,48.743021),(13.915047,48.73098),(13.98233,48.706485),(13.991115,48.700181),(14.007754,48.683283),(14.014162,48.675066),(14.019227,48.671914),(14.026151,48.670054),(14.032146,48.667263),(14.034729,48.661165),(14.032869,48.654912),(14.028322,48.653982),(14.023464,48.654602),(14.020467,48.653155),(14.013749,48.643802),(14.008064,48.642407),(14.006204,48.639513),(14.010855,48.62587),(14.015196,48.620393),(14.032456,48.60613),(14.040827,48.601169),(14.07483,48.591712),(14.216527,48.58117),(14.315746,48.557916),(14.325358,48.558639),(14.333213,48.560706),(14.353366,48.571429),(14.405353,48.586286),(14.421166,48.597061),(14.443593,48.636516),(14.458166,48.643182),(14.482144,48.624475),(14.522038,48.610626),(14.53382,48.608714),(14.548807,48.610936),(14.578779,48.620496),(14.594179,48.621323),(14.600586,48.617576),(14.601827,48.611194),(14.60193,48.604528),(14.605134,48.600316),(14.612885,48.599748),(14.628182,48.603288),(14.634693,48.602332),(14.645442,48.592901),(14.651333,48.583496),(14.659187,48.576959),(14.675621,48.576235),(14.69114,48.586535),(14.695671,48.589542),(14.700735,48.615535),(14.700219,48.646102),(14.703836,48.673103),(14.722749,48.693411),(14.775356,48.724004),(14.78042,48.743124),(14.790446,48.754855),(14.794476,48.766999),(14.800367,48.776507),(14.815457,48.780331),(14.86765,48.775577),(14.919327,48.761573),(14.939584,48.762813),(14.951056,48.780331),(14.948886,48.78214),(14.944441,48.788599),(14.940101,48.796506),(14.938137,48.80281),(14.93979,48.809787),(14.947025,48.822396),(14.968213,48.885028),(14.968316,48.912674),(14.964182,48.943267),(14.964595,48.971741),(14.978238,48.992825),(14.977308,48.998251),(14.977308,49.002902),(14.978858,49.00626),(14.982062,49.007914),(15.003973,49.009774),(15.059576,48.997217),(15.137401,48.993031),(15.144739,48.978924),(15.148977,48.965333),(15.148563,48.951742),(15.141949,48.937479),(15.161792,48.937221)] +Burundi [(30.415073,-2.313088),(30.418484,-2.311847),(30.423238,-2.317325),(30.428406,-2.331381),(30.434142,-2.339236),(30.488454,-2.383781),(30.521733,-2.399387),(30.5546,-2.400628),(30.521475,-2.442279),(30.508091,-2.463466),(30.47016,-2.55576),(30.461995,-2.58749),(30.457655,-2.598032),(30.448043,-2.610537),(30.424168,-2.633171),(30.416003,-2.645574),(30.412128,-2.670172),(30.423238,-2.680921),(30.442668,-2.681127),(30.463752,-2.674203),(30.499616,-2.657873),(30.52256,-2.649398),(30.516101,-2.668311),(30.458585,-2.72867),(30.450523,-2.741795),(30.447268,-2.757298),(30.446906,-2.782723),(30.425099,-2.812179),(30.413626,-2.8344),(30.415797,-2.851659),(30.440808,-2.884009),(30.456001,-2.898272),(30.474191,-2.903233),(30.469644,-2.914188),(30.475431,-2.922146),(30.484113,-2.930724),(30.488325,-2.94316),(30.488454,-2.94354),(30.49326,-2.941266),(30.513052,-2.913981),(30.524937,-2.904163),(30.53889,-2.898995),(30.547003,-2.900339),(30.61196,-2.939199),(30.62519,-2.94478),(30.62953,-2.947674),(30.632114,-2.953772),(30.634905,-2.970102),(30.637592,-2.974443),(30.650925,-2.977337),(30.661363,-2.974753),(30.671337,-2.970825),(30.683687,-2.969998),(30.695986,-2.974546),(30.718879,-2.989532),(30.732057,-2.99346),(30.755414,-2.991393),(30.80213,-2.97837),(30.825488,-2.978577),(30.818815,-2.990495),(30.815824,-2.995837),(30.78487,-3.031493),(30.778255,-3.04741),(30.783216,-3.062086),(30.807814,-3.085237),(30.817684,-3.099086),(30.817839,-3.104357),(30.813085,-3.11769),(30.812258,-3.123477),(30.815824,-3.131022),(30.828795,-3.140531),(30.832929,-3.147662),(30.833962,-3.160271),(30.832205,-3.172777),(30.823524,-3.196651),(30.809364,-3.216805),(30.809881,-3.224143),(30.814325,-3.24192),(30.814842,-3.247708),(30.799753,-3.274579),(30.775671,-3.291012),(30.747921,-3.294113),(30.721463,-3.280987),(30.718414,-3.292873),(30.712006,-3.301865),(30.702239,-3.307342),(30.68994,-3.308893),(30.662603,-3.319228),(30.640538,-3.33287),(30.621676,-3.35044),(30.603279,-3.372558),(30.61025,-3.376359),(30.640434,-3.392815),(30.639142,-3.41948),(30.612891,-3.444905),(30.565968,-3.466712),(30.552946,-3.482215),(30.544988,-3.48914),(30.538115,-3.49162),(30.511502,-3.497718),(30.509951,-3.500199),(30.508246,-3.50888),(30.507161,-3.511051),(30.48804,-3.512601),(30.487524,-3.510741),(30.48556,-3.510534),(30.46892,-3.513014),(30.466336,-3.516115),(30.462616,-3.527897),(30.460135,-3.531928),(30.432282,-3.551875),(30.426856,-3.563864),(30.429233,-3.583914),(30.428871,-3.602208),(30.421378,-3.620811),(30.38014,-3.685614),(30.373112,-3.703597),(30.373068,-3.704339),(30.371975,-3.722924),(30.376213,-3.739771),(30.381897,-3.75517),(30.384998,-3.770776),(30.381587,-3.788346),(30.33699,-3.773774),(30.31172,-3.789897),(30.273273,-3.856249),(30.22077,-3.909993),(30.208781,-3.930457),(30.191418,-4.002494),(30.175852,-4.039992),(30.173228,-4.046315),(30.149766,-4.08683),(30.119587,-4.12352),(30.051478,-4.180157),(30.041143,-4.19504),(30.015614,-4.256018),(30.003005,-4.271935),(29.980785,-4.28444),(29.970656,-4.292605),(29.936343,-4.312035),(29.900479,-4.345625),(29.847356,-4.370533),(29.838571,-4.37353),(29.821828,-4.37074),(29.810976,-4.365262),(29.80033,-4.363919),(29.784104,-4.37384),(29.782295,-4.377354),(29.780177,-4.393684),(29.775009,-4.402262),(29.757956,-4.410221),(29.751651,-4.416112),(29.747931,-4.430271),(29.747414,-4.44319),(29.744365,-4.454456),(29.732841,-4.463344),(29.728293,-4.461587),(29.687469,-4.458383),(29.638273,-4.446808),(29.404179,-4.449805),(29.37276,-4.208166),(29.367224,-4.189048),(29.33948,-4.093237),(29.277727,-3.988954),(29.239796,-3.948027),(29.224552,-3.926529),(29.215043,-3.899864),(29.206568,-3.781939),(29.217123,-3.709266),(29.22326,-3.66701),(29.225172,-3.588565),(29.206672,-3.334524),(29.208739,-3.305275),(29.213079,-3.291943),(29.236117,-3.270704),(29.240881,-3.266311),(29.223828,-3.252669),(29.216904,-3.233135),(29.214113,-3.166472),(29.217524,-3.146215),(29.225017,-3.129369),(29.237781,-3.122237),(29.242328,-3.110765),(29.241539,-3.104188),(29.234629,-3.046583),(29.225378,-3.031803),(29.211529,-3.021158),(29.194476,-3.014647),(29.175976,-3.012477),(29.156752,-3.004828),(29.148174,-2.986948),(29.144246,-2.966278),(29.138407,-2.950361),(29.123369,-2.940233),(29.105076,-2.934135),(29.08978,-2.926074),(29.083268,-2.910054),(29.081718,-2.893931),(29.077584,-2.884009),(29.062701,-2.862201),(29.053503,-2.835433),(29.049058,-2.827475),(29.034072,-2.82086),(29.013143,-2.818897),(28.994902,-2.813626),(28.986892,-2.796779),(28.988804,-2.775488),(28.995522,-2.758435),(29.008234,-2.74748),(29.028595,-2.744896),(29.015365,-2.720711),(29.032574,-2.620666),(29.05526,-2.598445),(29.113447,-2.594621),(29.129725,-2.596998),(29.190445,-2.623456),(29.212769,-2.630278),(29.254989,-2.635549),(29.276125,-2.640613),(29.294418,-2.651052),(29.306614,-2.660147),(29.307337,-2.664797),(29.306045,-2.67658),(29.309481,-2.690127),(29.309714,-2.691049),(29.331418,-2.71141),(29.337516,-2.723812),(29.335346,-2.735181),(29.321497,-2.752131),(29.318086,-2.762569),(29.32036,-2.774145),(29.329661,-2.794919),(29.33085,-2.807424),(29.339687,-2.826441),(29.364285,-2.824168),(29.407435,-2.805461),(29.425366,-2.803394),(29.444675,-2.806989),(29.480867,-2.813729),(29.504121,-2.826855),(29.523138,-2.820447),(29.541845,-2.808561),(29.563756,-2.805667),(29.574091,-2.806081),(29.582049,-2.80298),(29.589491,-2.798433),(29.619256,-2.787684),(29.626388,-2.788097),(29.637087,-2.791629),(29.678684,-2.805357),(29.697546,-2.808251),(29.719922,-2.805461),(29.729637,-2.79957),(29.733978,-2.790268),(29.737285,-2.769287),(29.744727,-2.759985),(29.756199,-2.759882),(29.778523,-2.7666),(29.803379,-2.767324),(29.823585,-2.763499),(29.842395,-2.752441),(29.862859,-2.731667),(29.876191,-2.71358),(29.888387,-2.692909),(29.897896,-2.671102),(29.90327,-2.649088),(29.903726,-2.637947),(29.907921,-2.5354),(29.929573,-2.459849),(29.92239,-2.382954),(29.928901,-2.331795),(29.928798,-2.322493),(29.931692,-2.316912),(29.941924,-2.316602),(29.949934,-2.321149),(29.956781,-2.327038),(29.95852,-2.328533),(29.976134,-2.34368),(29.983885,-2.344817),(29.992308,-2.34399),(30.00192,-2.3443),(30.013341,-2.348331),(30.025536,-2.357736),(30.056542,-2.394426),(30.072975,-2.408792),(30.093853,-2.422642),(30.116797,-2.43153),(30.139121,-2.430807),(30.156174,-2.419024),(30.20134,-2.362387),(30.203407,-2.355359),(30.203923,-2.345954),(30.207489,-2.339236),(30.219116,-2.340373),(30.250329,-2.355566),(30.262731,-2.358356),(30.278854,-2.357633),(30.297974,-2.353705),(30.316785,-2.347608),(30.331151,-2.340269),(30.344018,-2.328384),(30.34861,-2.322352),(30.352752,-2.316912),(30.362518,-2.307817),(30.37859,-2.303062),(30.383447,-2.305543),(30.415073,-2.313088)] +Belgium [(4.815447,51.431074),(4.822682,51.413685),(4.779067,51.426423),(4.767802,51.425389),(4.762117,51.413375),(4.783304,51.407638),(4.853274,51.40614),(4.871671,51.403039),(4.910325,51.391903),(4.931926,51.395624),(4.957144,51.410997),(4.980192,51.430531),(4.995798,51.446706),(5.002723,51.459005),(5.006133,51.468307),(5.012128,51.474327),(5.027527,51.476807),(5.030318,51.47443),(5.06029,51.461976),(5.079927,51.438541),(5.076413,51.421901),(5.065251,51.405907),(5.061737,51.384255),(5.068145,51.37454),(5.102561,51.350665),(5.107832,51.341984),(5.118064,51.319918),(5.122922,51.313381),(5.140182,51.307386),(5.178836,51.309505),(5.197336,51.308342),(5.214906,51.294338),(5.215423,51.258733),(5.232993,51.255916),(5.239456,51.25693),(5.270717,51.261833),(5.389056,51.258707),(5.409933,51.263539),(5.451894,51.282116),(5.471635,51.288085),(5.493235,51.286535),(5.516696,51.277233),(5.535197,51.26204),(5.542328,51.242661),(5.545532,51.219924),(5.551407,51.216767),(5.568373,51.207651),(5.62501,51.196902),(5.638549,51.190907),(5.648161,51.183957),(5.659013,51.179074),(5.67617,51.179177),(5.718028,51.184603),(5.730844,51.18375),(5.747173,51.177601),(5.768051,51.159462),(5.781383,51.152409),(5.812079,51.157318),(5.829132,51.156465),(5.83802,51.143727),(5.840501,51.138921),(5.826445,51.130162),(5.823241,51.118741),(5.845979,51.103393),(5.83678,51.099492),(5.826652,51.096908),(5.815903,51.095875),(5.804948,51.096624),(5.807428,51.089389),(5.808978,51.08634),(5.811769,51.082309),(5.804327,51.068589),(5.79885,51.061484),(5.791305,51.054998),(5.779626,51.061303),(5.771461,51.058125),(5.766397,51.048436),(5.76402,51.035181),(5.777559,51.023553),(5.761746,50.999162),(5.722369,50.959423),(5.744693,50.963247),(5.754305,50.963092),(5.76402,50.959423),(5.752548,50.947227),(5.735288,50.923973),(5.722369,50.911674),(5.717614,50.909245),(5.706039,50.90661),(5.694463,50.903664),(5.622323,50.852659),(5.624493,50.830284),(5.64072,50.815039),(5.657432,50.807641),(5.663251,50.805065),(5.684852,50.798503),(5.700458,50.795557),(5.698701,50.783775),(5.688366,50.76083),(5.706556,50.754216),(5.717408,50.752821),(5.727846,50.754164),(5.732777,50.758851),(5.743556,50.769099),(5.752444,50.773439),(5.76247,50.771011),(5.782933,50.756696),(5.793165,50.752149),(5.879878,50.753544),(5.891288,50.751246),(5.891321,50.75124),(5.902203,50.749048),(5.974756,50.74755),(5.99491,50.749927),(5.993256,50.748066),(5.992636,50.746258),(5.99274,50.744449),(5.994187,50.742589),(6.010826,50.737059),(6.011343,50.727447),(6.007623,50.716905),(6.01155,50.708534),(6.024779,50.707552),(6.064363,50.714477),(6.081003,50.713495),(6.100227,50.701299),(6.161102,50.642181),(6.147769,50.636755),(6.159448,50.622389),(6.180015,50.615516),(6.249055,50.614431),(6.251329,50.608437),(6.244301,50.599548),(6.232932,50.590763),(6.232932,50.587146),(6.210608,50.578671),(6.179085,50.561979),(6.160688,50.543583),(6.177328,50.530198),(6.169473,50.522499),(6.170817,50.517951),(6.178878,50.515781),(6.190557,50.515212),(6.182599,50.506582),(6.19066,50.501828),(6.199239,50.490408),(6.207197,50.486325),(6.217119,50.486015),(6.250915,50.492681),(6.253086,50.494077),(6.255566,50.494593),(6.25784,50.494077),(6.260114,50.492681),(6.27541,50.48803),(6.318715,50.481674),(6.336905,50.481003),(6.325743,50.474026),(6.323262,50.466016),(6.326156,50.457025),(6.331634,50.446896),(6.340212,50.437853),(6.347343,50.436974),(6.351167,50.433564),(6.350444,50.416872),(6.343313,50.393308),(6.336388,50.379923),(6.337732,50.368089),(6.372458,50.329436),(6.3734,50.32308),(6.374525,50.315483),(6.362019,50.306956),(6.335458,50.303856),(6.322022,50.305406),(6.310653,50.308248),(6.299491,50.308868),(6.285952,50.303856),(6.27603,50.296104),(6.269415,50.286492),(6.267348,50.276416),(6.271792,50.267424),(6.253396,50.256778),(6.210401,50.249027),(6.189627,50.242722),(6.179808,50.233007),(6.157174,50.222724),(6.146839,50.214042),(6.160171,50.204534),(6.165752,50.193165),(6.165132,50.181899),(6.159138,50.172443),(6.151696,50.169342),(6.131749,50.168308),(6.123171,50.164898),(6.121311,50.16159),(6.118003,50.150377),(6.115833,50.145467),(6.125962,50.140196),(6.129476,50.134047),(6.126582,50.127329),(6.117487,50.120456),(6.102604,50.124745),(6.10033,50.132652),(6.101467,50.142108),(6.097126,50.151307),(6.084207,50.159317),(6.076456,50.158645),(6.070048,50.154201),(6.061366,50.150738),(6.038628,50.148413),(6.027363,50.149447),(6.022967,50.15082),(6.014134,50.153581),(6.008036,50.160919),(6.004729,50.170479),(5.998321,50.174975),(5.982921,50.167068),(5.96163,50.165621),(5.953156,50.156371),(5.949021,50.142677),(5.941063,50.128311),(5.92618,50.118337),(5.888973,50.106607),(5.872437,50.096892),(5.86882,50.090535),(5.866856,50.074309),(5.864375,50.067488),(5.858278,50.061803),(5.843705,50.053638),(5.83771,50.047437),(5.838847,50.035862),(5.838847,50.026457),(5.836367,50.01855),(5.829132,50.013589),(5.808875,50.007801),(5.802674,50.002479),(5.801537,49.988681),(5.808565,49.9831),(5.812596,49.977571),(5.80164,49.963825),(5.793372,49.958812),(5.778593,49.95659),(5.771565,49.953541),(5.76371,49.946823),(5.759989,49.941604),(5.757612,49.93654),(5.753581,49.930183),(5.718958,49.891374),(5.714927,49.881866),(5.726709,49.878197),(5.748827,49.867293),(5.758129,49.858198),(5.731877,49.859955),(5.73198,49.854167),(5.730533,49.85117),(5.728673,49.848845),(5.726916,49.845227),(5.736528,49.83944),(5.724642,49.834272),(5.720198,49.824712),(5.721645,49.812775),(5.727743,49.800217),(5.738285,49.788848),(5.748414,49.785644),(5.759162,49.784456),(5.771875,49.779392),(5.778489,49.773035),(5.802054,49.742856),(5.803604,49.738154),(5.805774,49.724201),(5.805361,49.721876),(5.811769,49.718517),(5.825721,49.715778),(5.831716,49.713607),(5.837297,49.712936),(5.843705,49.714331),(5.850216,49.714021),(5.856004,49.708078),(5.856403,49.705807),(5.857347,49.70043),(5.853627,49.696296),(5.848769,49.69273),(5.847219,49.687201),(5.846702,49.68069),(5.843705,49.677486),(5.842258,49.67392),(5.845772,49.666582),(5.852593,49.663223),(5.872644,49.661724),(5.879878,49.657745),(5.885459,49.643534),(5.879878,49.634853),(5.869957,49.628858),(5.861998,49.62276),(5.849183,49.599713),(5.841224,49.589687),(5.829959,49.582763),(5.846909,49.576717),(5.8374,49.56111),(5.814456,49.545142),(5.790685,49.537753),(5.779006,49.539613),(5.757095,49.548398),(5.746346,49.549431),(5.735598,49.545711),(5.722679,49.5346),(5.710276,49.531086),(5.688676,49.533515),(5.667178,49.54044),(5.644647,49.543799),(5.619739,49.53553),(5.607854,49.524937),(5.60558,49.517754),(5.602273,49.513723),(5.587493,49.512431),(5.578915,49.51393),(5.547599,49.523438),(5.528789,49.517961),(5.503674,49.505093),(5.477732,49.495223),(5.456132,49.498944),(5.44993,49.507832),(5.450964,49.516772),(5.454168,49.526177),(5.454375,49.536616),(5.450241,49.545762),(5.402078,49.602451),(5.391166,49.608817),(5.383475,49.613304),(5.352469,49.620693),(5.3411,49.625137),(5.334899,49.625809),(5.331178,49.623122),(5.326941,49.617644),(5.32167,49.61258),(5.314538,49.611133),(5.297898,49.613252),(5.293041,49.617179),(5.290664,49.626378),(5.293764,49.640537),(5.301826,49.643896),(5.306373,49.647513),(5.299449,49.662499),(5.280122,49.677899),(5.259244,49.691335),(5.237644,49.690973),(5.192478,49.682808),(5.169431,49.687201),(5.151241,49.695986),(5.136358,49.705339),(5.093776,49.745337),(5.081891,49.752727),(5.046234,49.759393),(5.026287,49.766731),(4.98908,49.790554),(4.970993,49.797065),(4.968371,49.796981),(4.950013,49.796393),(4.906604,49.786471),(4.884177,49.784146),(4.858029,49.786575),(4.849037,49.794171),(4.849244,49.831585),(4.846763,49.837528),(4.836945,49.848018),(4.834878,49.85303),(4.836738,49.859128),(4.845626,49.865846),(4.848934,49.871066),(4.854308,49.883313),(4.859372,49.891684),(4.861956,49.900314),(4.860199,49.913337),(4.844593,49.931734),(4.797257,49.944291),(4.783925,49.958295),(4.788265,49.974263),(4.826713,50.036017),(4.827643,50.046714),(4.826093,50.055034),(4.827229,50.064077),(4.84604,50.09069),(4.852137,50.091621),(4.862886,50.084076),(4.86516,50.101594),(4.870534,50.122265),(4.871878,50.139783),(4.862679,50.147586),(4.831364,50.1434),(4.820098,50.146449),(4.815551,50.161332),(4.788575,50.153374),(4.681915,50.083921),(4.676128,50.076066),(4.67344,50.066196),(4.675818,50.060201),(4.679538,50.055189),(4.680572,50.048316),(4.672924,50.01638),(4.665896,50.000515),(4.656697,49.989095),(4.645845,49.984495),(4.604194,49.980206),(4.464771,49.935609),(4.435109,49.93225),(4.427651,49.933572),(4.277599,49.960156),(4.215953,49.954408),(4.201118,49.953024),(4.187682,49.955505),(4.131665,49.974987),(4.132365,49.974946),(4.139623,49.974522),(4.138383,49.989198),(4.132905,50.004494),(4.128151,50.005786),(4.132285,50.017568),(4.137349,50.025061),(4.144584,50.030797),(4.162877,50.041805),(4.186028,50.05245),(4.210006,50.06015),(4.210316,50.066713),(4.203392,50.074671),(4.197397,50.084076),(4.180551,50.127226),(4.170629,50.130481),(4.15988,50.129396),(4.139933,50.123557),(4.125774,50.128156),(4.128151,50.146243),(4.147374,50.186343),(4.152749,50.204534),(4.157296,50.212698),(4.167942,50.222465),(4.191506,50.234299),(4.201325,50.241534),(4.203702,50.251973),(4.197604,50.258484),(4.185201,50.26546),(4.171766,50.270886),(4.162774,50.272953),(4.150268,50.269543),(4.149751,50.263135),(4.150992,50.256262),(4.143654,50.251611),(4.125257,50.25714),(4.097868,50.294812),(4.077198,50.306646),(4.055907,50.314553),(4.022731,50.338117),(4.0033,50.34406),(3.982113,50.342613),(3.918551,50.325456),(3.895917,50.325301),(3.878037,50.330779),(3.86088,50.338479),(3.84021,50.345197),(3.798662,50.348452),(3.755047,50.346334),(3.741508,50.34313),(3.733446,50.337239),(3.715463,50.317653),(3.711122,50.309333),(3.708435,50.306336),(3.703887,50.304321),(3.702234,50.305251),(3.700787,50.304683),(3.696859,50.298223),(3.661719,50.319307),(3.652934,50.360183),(3.652831,50.406847),(3.644356,50.445501),(3.62813,50.464363),(3.608286,50.476507),(3.586375,50.483483),(3.563741,50.486532),(3.499145,50.48679),(3.486743,50.492681),(3.496458,50.503792),(3.498008,50.511853),(3.491497,50.517073),(3.477131,50.519863),(3.462868,50.51914),(3.452636,50.514851),(3.442714,50.508494),(3.429175,50.501828),(3.385354,50.491648),(3.361066,50.489787),(3.343599,50.49294),(3.299881,50.507461),(3.286755,50.514075),(3.271045,50.526943),(3.265878,50.538312),(3.264327,50.570196),(3.237869,50.626472),(3.229808,50.65541),(3.24376,50.672102),(3.232391,50.695925),(3.224433,50.705175),(3.210997,50.707965),(3.196941,50.709206),(3.188983,50.715097),(3.176684,50.734114),(3.162823,50.749925),(3.162811,50.749939),(3.146195,50.768892),(3.129245,50.779072),(3.103304,50.784085),(3.023817,50.768262),(2.971425,50.757833),(2.948378,50.748686),(2.930188,50.736232),(2.900112,50.703108),(2.886883,50.696648),(2.871276,50.698767),(2.866726,50.700091),(2.786734,50.723365),(2.768234,50.733235),(2.762963,50.739385),(2.749527,50.75959),(2.743842,50.766205),(2.706635,50.788787),(2.700021,50.79628),(2.69692,50.80305),(2.691856,50.808838),(2.67873,50.81323),(2.669222,50.813902),(2.650618,50.812248),(2.642453,50.812455),(2.627777,50.814419),(2.620439,50.816486),(2.615168,50.82217),(2.60659,50.834831),(2.602042,50.838087),(2.58995,50.842014),(2.586746,50.845425),(2.58778,50.850024),(2.595531,50.861134),(2.596668,50.867646),(2.576928,50.911519),(2.582715,50.920666),(2.605763,50.935238),(2.611654,50.941233),(2.60845,50.961128),(2.592741,50.976114),(2.55698,51.001177),(2.547059,51.020479),(2.537033,51.06461),(2.5218,51.087541),(2.521821,51.087551),(2.542003,51.096869),(2.579926,51.104804),(2.715668,51.169501),(2.923595,51.246487),(3.124848,51.329657),(3.348969,51.375149),(3.349415,51.375223),(3.358068,51.336713),(3.353934,51.311908),(3.353211,51.288602),(3.36737,51.263487),(3.391658,51.24677),(3.398798,51.244698),(3.421941,51.237985),(3.453877,51.235633),(3.501212,51.240284),(3.504106,51.249741),(3.501522,51.262402),(3.503383,51.273952),(3.514338,51.281031),(3.529014,51.283331),(3.545034,51.283925),(3.584825,51.289532),(3.609526,51.290436),(3.635054,51.287827),(3.757321,51.262324),(3.776234,51.254521),(3.781402,51.241421),(3.779748,51.230311),(3.781402,51.219872),(3.796285,51.208762),(3.808687,51.205325),(3.927026,51.206255),(3.949454,51.210777),(3.995032,51.23323),(4.118952,51.272401),(4.168562,51.29687),(4.207939,51.330589),(4.21352,51.340537),(4.220962,51.363817),(4.221491,51.368001),(4.221528,51.367987),(4.222179,51.367743),(4.241059,51.356594),(4.249034,51.346666),(4.256114,51.328437),(4.272634,51.315823),(4.290782,51.305894),(4.302989,51.296088),(4.306651,51.28974),(4.308116,51.283637),(4.305431,51.276597),(4.298676,51.269599),(4.296723,51.267564),(4.30836,51.271226),(4.316417,51.276842),(4.330821,51.296088),(4.29713,51.305162),(4.289317,51.309149),(4.285411,51.31802),(4.286143,51.339667),(4.283051,51.350084),(4.275645,51.3581),(4.261078,51.369371),(4.261068,51.369379),(4.281124,51.368947),(4.290105,51.368752),(4.326278,51.356427),(4.345605,51.352293),(4.392217,51.350407),(4.411234,51.356737),(4.416195,51.373971),(4.410097,51.38379),(4.38767,51.400533),(4.379918,51.409525),(4.380642,51.419653),(4.387153,51.427456),(4.38922,51.434588),(4.377128,51.442882),(4.429424,51.461976),(4.483064,51.474327),(4.512623,51.477376),(4.525232,51.475929),(4.533191,51.467583),(4.531847,51.450866),(4.523372,51.438412),(4.521512,51.428645),(4.540632,51.420067),(4.553861,51.419291),(4.582697,51.422599),(4.614633,51.41756),(4.630136,51.418206),(4.643571,51.42141),(4.653907,51.426216),(4.731215,51.485618),(4.764184,51.496238),(4.778654,51.495359),(4.796844,51.491018),(4.813587,51.48412),(4.823922,51.475645),(4.826093,51.460555),(4.819891,51.446215),(4.815447,51.431074)] +Benin [(3.341635,11.882893),(3.355071,11.889043),(3.369127,11.897311),(3.380909,11.895037),(3.391658,11.888836),(3.40282,11.88527),(3.447675,11.857985),(3.484262,11.84517),(3.495424,11.837521),(3.503486,11.829977),(3.536972,11.782899),(3.54369,11.77706),(3.549271,11.773753),(3.553715,11.76967),(3.557436,11.761815),(3.5625,11.746003),(3.566221,11.738354),(3.568185,11.729518),(3.571699,11.72187),(3.58007,11.717374),(3.589372,11.701509),(3.5964,11.695773),(3.574386,11.673035),(3.504933,11.556557),(3.493047,11.511495),(3.486743,11.496276),(3.466692,11.442481),(3.468449,11.419485),(3.483332,11.392303),(3.662546,11.143145),(3.686731,11.120485),(3.694999,11.119116),(3.704404,11.120795),(3.705583,11.120733),(3.713706,11.120304),(3.722077,11.112346),(3.711845,11.073511),(3.711845,11.051859),(3.715876,11.031886),(3.723318,11.013541),(3.733549,10.996462),(3.733549,10.996203),(3.754117,10.907139),(3.75298,10.877683),(3.731276,10.825025),(3.730035,10.807714),(3.7351,10.795776),(3.743161,10.787456),(3.751946,10.78017),(3.759491,10.771592),(3.764452,10.760869),(3.773857,10.728054),(3.783262,10.71697),(3.796078,10.71312),(3.810237,10.710484),(3.82295,10.70325),(3.832148,10.683923),(3.837109,10.654829),(3.837246,10.630609),(3.837419,10.599897),(3.829874,10.573077),(3.804346,10.523157),(3.795354,10.496492),(3.794321,10.444867),(3.787706,10.426367),(3.772513,10.407635),(3.756907,10.405257),(3.692828,10.438382),(3.671744,10.442077),(3.652107,10.435798),(3.632574,10.416652),(3.625959,10.407273),(3.623169,10.400917),(3.622135,10.381228),(3.618208,10.369342),(3.59299,10.330947),(3.572422,10.285704),(3.573352,10.266997),(3.587615,10.244182),(3.655621,10.174781),(3.664613,10.162197),(3.667507,10.146565),(3.66483,10.128654),(3.663993,10.123052),(3.654898,10.101116),(3.642392,10.091892),(3.627819,10.084993),(3.612317,10.070291),(3.605805,10.054116),(3.599604,9.968695),(3.589476,9.948825),(3.557126,9.910559),(3.530771,9.862965),(3.513098,9.846609),(3.452946,9.853095),(3.413982,9.842837),(3.342049,9.813588),(3.325926,9.801728),(3.317141,9.78173),(3.314867,9.759095),(3.318381,9.739432),(3.33068,9.708633),(3.338638,9.678222),(3.33161,9.652022),(3.299054,9.633961),(3.281381,9.634994),(3.261847,9.638612),(3.245724,9.633702),(3.238179,9.609053),(3.239419,9.602309),(3.24469,9.589571),(3.243554,9.584403),(3.182575,9.505338),(3.175134,9.498879),(3.159011,9.493478),(3.151776,9.488156),(3.132553,9.457279),(3.128625,9.429581),(3.135343,9.401675),(3.148055,9.370256),(3.151466,9.353565),(3.151363,9.288633),(3.145162,9.267859),(3.124594,9.228999),(3.091315,9.126421),(3.076019,9.095157),(3.051421,9.078207),(2.983104,9.060611),(2.971425,9.060508),(2.9614,9.065313),(2.951685,9.071902),(2.94073,9.07707),(2.929878,9.078362),(2.899182,9.07738),(2.888433,9.075364),(2.877788,9.068543),(2.869313,9.059707),(2.859701,9.052627),(2.846265,9.050767),(2.769164,9.057045),(2.772368,9.030535),(2.770197,8.967154),(2.76472,8.939766),(2.761516,8.933694),(2.75025,8.916873),(2.74777,8.914806),(2.749527,8.906615),(2.753764,8.904419),(2.758725,8.902662),(2.762549,8.895686),(2.762136,8.880415),(2.74963,8.851941),(2.745909,8.836516),(2.74715,8.827654),(2.752317,8.81228),(2.751077,8.803417),(2.745703,8.798146),(2.728856,8.790472),(2.723172,8.782928),(2.722862,8.772308),(2.722949,8.771218),(2.742439,8.527481),(2.744773,8.498294),(2.736918,8.464523),(2.72896,8.452741),(2.709012,8.430391),(2.703741,8.417885),(2.703535,8.409023),(2.706015,8.390548),(2.706015,8.381272),(2.698367,8.339854),(2.697127,8.320708),(2.700744,8.296885),(2.708496,8.274819),(2.728133,8.233194),(2.734954,8.211903),(2.734437,8.189966),(2.726582,8.171595),(2.716144,8.154904),(2.708392,8.13798),(2.705705,8.119686),(2.703535,8.059897),(2.690926,7.996567),(2.687102,7.933522),(2.683588,7.924634),(2.673356,7.905565),(2.671082,7.897917),(2.671695,7.893434),(2.672219,7.889597),(2.68028,7.87735),(2.691546,7.848669),(2.715524,7.822056),(2.724412,7.80769),(2.727203,7.793324),(2.717641,7.658549),(2.715317,7.625789),(2.720588,7.586566),(2.740638,7.549359),(2.770197,7.514271),(2.792315,7.477633),(2.789628,7.435826),(2.787251,7.426886),(2.786527,7.421254),(2.783323,7.419238),(2.761722,7.423527),(2.751284,7.423631),(2.743636,7.419238),(2.741155,7.408179),(2.762136,7.1622),(2.761102,7.14835),(2.757795,7.138894),(2.749837,7.128558),(2.740638,7.109593),(2.736298,7.102927),(2.735264,7.096002),(2.739088,7.08298),(2.747666,7.072231),(2.773918,7.050785),(2.779706,7.041328),(2.775778,7.030528),(2.765547,7.025102),(2.752731,7.02133),(2.741052,7.0158),(2.71511,6.979833),(2.718418,6.943557),(2.731957,6.905213),(2.736918,6.863303),(2.726272,6.821368),(2.723585,6.799715),(2.72865,6.780001),(2.736298,6.769846),(2.744773,6.763774),(2.755005,6.760725),(2.767407,6.759563),(2.773298,6.755041),(2.775262,6.744887),(2.778569,6.698765),(2.772988,6.687474),(2.760689,6.679387),(2.742602,6.663341),(2.73113,6.641844),(2.73082,6.621354),(2.739398,6.579186),(2.737331,6.558025),(2.718803,6.504298),(2.71542,6.494488),(2.71192,6.474048),(2.704258,6.429299),(2.703841,6.368352),(2.703298,6.368313),(2.306977,6.331488),(2.226817,6.313666),(1.884532,6.274807),(1.619663,6.213899),(1.612439,6.234763),(1.633109,6.245692),(1.761577,6.276026),(1.782351,6.277267),(1.76354,6.350647),(1.74411,6.425733),(1.718375,6.466997),(1.709797,6.473404),(1.6883,6.484437),(1.681685,6.489838),(1.679515,6.498571),(1.681995,6.520017),(1.680755,6.530068),(1.67445,6.538594),(1.657811,6.552263),(1.655227,6.559213),(1.653883,6.570659),(1.646648,6.573192),(1.63683,6.572261),(1.627425,6.573347),(1.61957,6.577998),(1.611198,6.58469),(1.603344,6.592596),(1.597349,6.600813),(1.594145,6.611045),(1.594765,6.620269),(1.596522,6.62864),(1.596316,6.636418),(1.58536,6.656442),(1.572441,6.666907),(1.566033,6.678146),(1.574301,6.700574),(1.589182,6.72046),(1.597039,6.73096),(1.60107,6.746437),(1.595179,6.77057),(1.587531,6.791034),(1.58319,6.808268),(1.58257,6.825347),(1.590114,6.867334),(1.588047,6.881235),(1.579056,6.892035),(1.564223,6.903089),(1.562623,6.904283),(1.551357,6.920871),(1.531927,6.991926),(1.607478,6.991409),(1.625668,6.996783),(1.624944,7.143648),(1.624324,7.288807),(1.623704,7.4381),(1.623251,7.536385),(1.622855,7.62246),(1.622774,7.640052),(1.621947,7.838282),(1.621327,7.996567),(1.623807,8.155886),(1.625564,8.270478),(1.614919,8.356261),(1.609855,8.365485),(1.603964,8.367449),(1.603945,8.367476),(1.60107,8.371635),(1.606031,8.396026),(1.606031,8.413389),(1.607581,8.421864),(1.640447,8.475815),(1.644168,8.493488),(1.63993,8.503255),(1.614092,8.535785),(1.609028,8.546973),(1.607581,8.558755),(1.607204,8.588617),(1.605514,8.722492),(1.604274,8.815225),(1.602827,8.924392),(1.601173,9.049526),(1.595799,9.076811),(1.587841,9.100893),(1.567273,9.13673),(1.505158,9.201455),(1.425267,9.284499),(1.420146,9.292317),(1.401185,9.321267),(1.386716,9.361135),(1.379895,9.462473),(1.368422,9.490843),(1.351266,9.482549),(1.336486,9.497509),(1.326358,9.521952),(1.323154,9.542313),(1.327288,9.555309),(1.345065,9.582388),(1.351266,9.595074),(1.352506,9.60528),(1.352196,9.625357),(1.354573,9.635304),(1.35602,9.647474),(1.348165,9.694164),(1.346925,9.771834),(1.345065,9.881103),(1.343942,9.954756),(1.343825,9.962442),(1.331009,9.996471),(1.225485,10.066053),(1.082238,10.16044),(0.997106,10.216553),(0.939508,10.254517),(0.844423,10.317175),(0.768769,10.367094),(0.760708,10.382158),(0.759881,10.405154),(0.773833,10.508145),(0.78851,10.563852),(0.789233,10.602946),(0.781275,10.693044),(0.795641,10.726478),(0.850005,10.77769),(0.862924,10.796086),(0.866024,10.80637),(0.867575,10.829211),(0.869538,10.839908),(0.885144,10.869389),(0.883698,10.880216),(0.875326,10.900524),(0.872949,10.911299),(0.875843,10.931169),(0.901474,10.992741),(0.931963,10.976101),(0.945399,10.974293),(0.963279,10.974137),(0.967517,10.979486),(0.969997,10.991165),(0.969067,11.002895),(0.963279,11.00827),(0.955321,11.01199),(0.951807,11.021086),(0.95129,11.032299),(0.952427,11.042402),(0.955941,11.044727),(0.964416,11.057414),(0.970307,11.06948),(0.976922,11.078369),(0.981366,11.080126),(0.986017,11.078498),(1.007928,11.075062),(1.014646,11.070359),(1.01971,11.065682),(1.025084,11.063512),(1.027978,11.061341),(1.033249,11.051575),(1.035006,11.049275),(1.041311,11.049585),(1.052163,11.055011),(1.05609,11.05607),(1.086889,11.052737),(1.097018,11.049275),(1.099705,11.044366),(1.106836,11.034418),(1.114174,11.027674),(1.117482,11.032196),(1.118619,11.048241),(1.10725,11.059791),(1.100945,11.070411),(1.099292,11.081289),(1.099085,11.092606),(1.097018,11.104491),(1.095158,11.10444),(1.085649,11.108729),(1.082755,11.110692),(1.082135,11.115292),(1.083892,11.12772),(1.082755,11.131802),(1.07335,11.133947),(1.067046,11.12834),(1.063325,11.126971),(1.062291,11.14206),(1.067459,11.144282),(1.100429,11.15162),(1.106216,11.155651),(1.113038,11.173867),(1.117482,11.178983),(1.128127,11.178879),(1.148074,11.1695),(1.158409,11.165935),(1.153242,11.183169),(1.149314,11.217249),(1.130608,11.247583),(1.135568,11.260115),(1.145904,11.269856),(1.156342,11.28554),(1.165954,11.277995),(1.173499,11.2666),(1.172155,11.261484),(1.18094,11.261355),(1.186211,11.263887),(1.191379,11.267014),(1.200061,11.268977),(1.218974,11.268047),(1.235201,11.263474),(1.268377,11.247893),(1.281089,11.271096),(1.28264,11.278873),(1.280366,11.288692),(1.270547,11.298278),(1.268377,11.30621),(1.273338,11.318225),(1.2845,11.312721),(1.296179,11.299621),(1.302483,11.288847),(1.309305,11.297089),(1.316333,11.29988),(1.323464,11.297089),(1.330389,11.288847),(1.347855,11.303497),(1.345892,11.316339),(1.336176,11.330033),(1.330389,11.347164),(1.33907,11.366103),(1.359017,11.378893),(1.381652,11.388686),(1.398085,11.398685),(1.388576,11.420002),(1.389817,11.428399),(1.398085,11.440311),(1.411107,11.449845),(1.423215,11.453748),(1.423613,11.453876),(1.433845,11.459405),(1.439633,11.473771),(1.455962,11.464702),(1.475289,11.460774),(1.56934,11.453307),(1.567273,11.446693),(1.565,11.432637),(1.563243,11.426022),(1.580606,11.427056),(1.601587,11.388686),(1.62112,11.395275),(1.638173,11.404215),(1.684372,11.413852),(1.703492,11.422921),(1.719099,11.427779),(1.763334,11.424678),(1.782247,11.426022),(1.821521,11.441602),(1.840642,11.445478),(1.858005,11.440311),(1.867617,11.446615),(1.879812,11.444858),(1.905754,11.432843),(1.948025,11.41672),(1.983372,11.414007),(2.010761,11.426901),(2.015429,11.43159),(2.14698,11.56374),(2.22005,11.622548),(2.273587,11.652055),(2.287436,11.665284),(2.291054,11.674792),(2.290227,11.685748),(2.290847,11.703214),(2.301596,11.731533),(2.340043,11.773856),(2.354099,11.799849),(2.390169,11.896536),(2.388205,11.906768),(2.376526,11.924079),(2.375183,11.935035),(2.380867,11.947902),(2.389342,11.950073),(2.398747,11.948781),(2.407429,11.95121),(2.414147,11.958703),(2.422002,11.973172),(2.428926,11.980355),(2.438951,11.981285),(2.44939,11.977513),(2.456728,11.979063),(2.457348,11.99622),(2.455281,12.008674),(2.44877,12.013376),(2.439262,12.015598),(2.428616,12.020353),(2.418281,12.028673),(2.41115,12.036786),(2.405568,12.046708),(2.371875,12.140449),(2.362057,12.196156),(2.36123,12.218894),(2.370015,12.236257),(2.3942,12.247212),(2.407946,12.248918),(2.43089,12.247987),(2.443706,12.249228),(2.446083,12.251811),(2.454351,12.263025),(2.459519,12.266746),(2.46696,12.265041),(2.472644,12.259253),(2.477709,12.257599),(2.483393,12.268038),(2.488044,12.280388),(2.495072,12.283231),(2.504477,12.281835),(2.516259,12.281422),(2.51905,12.279148),(2.5206,12.273671),(2.523701,12.269175),(2.531246,12.269691),(2.53693,12.27305),(2.546025,12.281629),(2.550573,12.284523),(2.586126,12.294031),(2.590053,12.293308),(2.598632,12.288347),(2.603593,12.28783),(2.60969,12.290775),(2.621679,12.299509),(2.628604,12.300801),(2.663847,12.291551),(2.672942,12.296718),(2.686895,12.318422),(2.690202,12.326174),(2.692166,12.334029),(2.69506,12.341212),(2.700434,12.347103),(2.711286,12.351237),(2.721828,12.344261),(2.732267,12.346793),(2.741465,12.354131),(2.757485,12.372941),(2.768544,12.380072),(2.778156,12.381933),(2.798413,12.381209),(2.808645,12.383225),(2.832416,12.384051),(2.844301,12.399244),(2.892257,12.357076),(2.912618,12.346328),(2.922643,12.335631),(2.930394,12.323332),(2.936802,12.300852),(2.944967,12.292481),(2.956026,12.286848),(2.967808,12.282559),(3.000984,12.27889),(3.009356,12.276306),(3.013077,12.271087),(3.022895,12.252483),(3.063409,12.193779),(3.235389,12.039525),(3.238489,12.034202),(3.252028,12.024125),(3.255129,12.018751),(3.257609,11.997408),(3.26257,11.974722),(3.269908,11.956532),(3.292749,11.918653),(3.307012,11.902375),(3.315487,11.894572),(3.327786,11.886407),(3.341635,11.882893)] +Burkina Faso [(-0.397671,15.002135),(-0.361472,15.017741),(-0.299176,15.054741),(-0.236699,15.065619),(-0.166988,15.049677),(-0.033404,14.995933),(-0.033197,14.995933),(0.218467,14.910977),(0.220844,14.888214),(0.211852,14.874804),(0.198003,14.863797),(0.185756,14.84819),(0.184102,14.819562),(0.213092,14.761632),(0.219707,14.731221),(0.152941,14.54671),(0.158832,14.496119),(0.18865,14.44775),(0.202382,14.435545),(0.346366,14.307577),(0.388792,14.251612),(0.391635,14.245927),(0.390601,14.237633),(0.381118,14.22567),(0.377424,14.216601),(0.372153,14.185647),(0.367398,14.173787),(0.343472,14.137536),(0.339157,14.12578),(0.343575,14.114333),(0.356262,14.095704),(0.362463,14.088857),(0.368742,14.084154),(0.37422,14.078883),(0.378457,14.070434),(0.37732,14.063949),(0.369052,14.047852),(0.369155,14.039067),(0.378354,14.028809),(0.391376,14.022582),(0.401866,14.013797),(0.403934,13.996072),(0.411866,13.978424),(0.428377,13.967495),(0.445921,13.958581),(0.456695,13.94685),(0.456256,13.938143),(0.448065,13.920108),(0.448634,13.909617),(0.454809,13.902357),(0.47566,13.888947),(0.483515,13.880343),(0.49199,13.861817),(0.499926,13.851015),(0.504082,13.845358),(0.519275,13.831637),(0.552968,13.810037),(0.5632,13.796782),(0.574466,13.785025),(0.593689,13.778101),(0.600511,13.768721),(0.594516,13.74986),(0.584801,13.729008),(0.58046,13.713789),(0.59431,13.688881),(0.620665,13.679967),(0.75337,13.684101),(0.763498,13.682034),(0.766392,13.67511),(0.766185,13.666971),(0.767012,13.660873),(0.766289,13.657178),(0.762878,13.653044),(0.763705,13.646429),(0.775694,13.635293),(0.795331,13.625965),(0.813108,13.625035),(0.850728,13.628601),(0.896927,13.614932),(0.95098,13.583203),(0.991391,13.541113),(0.996559,13.496051),(1.015266,13.465665),(1.048235,13.441945),(1.157169,13.392646),(1.175049,13.38691),(1.217424,13.381768),(1.23427,13.377583),(1.249567,13.367066),(1.268687,13.34606),(1.241505,13.335544),(1.222075,13.344613),(1.205745,13.358901),(1.187658,13.364121),(1.182387,13.358695),(1.177633,13.34761),(1.167608,13.313426),(1.160683,13.311307),(1.138462,13.320377),(1.084719,13.33358),(1.004724,13.364844),(0.983536,13.36841),(0.970411,13.328335),(0.970824,13.243534),(0.971341,13.149405),(0.971661,13.085782),(0.971754,13.067317),(0.974648,13.048326),(0.983536,13.032358),(1.012269,13.016881),(1.083789,13.01099),(1.113968,12.996236),(1.170915,12.949211),(1.230756,12.899756),(1.304806,12.838508),(1.330595,12.817177),(1.412037,12.749869),(1.467124,12.704394),(1.535854,12.647498),(1.563863,12.63215),(1.597039,12.623675),(1.699462,12.61489),(1.826069,12.604193),(1.843742,12.606105),(1.860692,12.61706),(1.872681,12.634217),(1.883223,12.653957),(1.900173,12.678452),(1.906994,12.691836),(1.911438,12.696642),(1.919603,12.698347),(1.926631,12.694989),(1.934486,12.693542),(1.945545,12.700828),(1.962495,12.719121),(1.971693,12.724237),(2.068948,12.716279),(2.109049,12.705634),(2.135197,12.67561),(2.140985,12.656128),(2.144809,12.650753),(2.155455,12.640005),(2.165997,12.631737),(2.18429,12.620626),(2.193282,12.609464),(2.2,12.595925),(2.203204,12.583316),(2.210852,12.523061),(2.215709,12.510349),(2.223874,12.494846),(2.229559,12.487146),(2.242271,12.473452),(2.246302,12.465907),(2.246302,12.461669),(2.243098,12.451179),(2.242994,12.446166),(2.244958,12.424152),(2.23793,12.413455),(2.223254,12.409735),(2.163826,12.404774),(2.158762,12.405652),(2.148013,12.410768),(2.145016,12.41175),(2.138711,12.408339),(2.131477,12.398521),(2.126929,12.39511),(2.069258,12.383328),(2.054169,12.370926),(2.051792,12.341935),(2.070912,12.306898),(2.113803,12.247987),(2.188527,12.145461),(2.258807,12.048775),(2.338079,11.940099),(2.390169,11.896536),(2.354099,11.799849),(2.340043,11.773856),(2.301596,11.731533),(2.290847,11.703214),(2.290227,11.685748),(2.291054,11.674792),(2.287436,11.665284),(2.273587,11.652055),(2.22005,11.622548),(2.14698,11.56374),(2.015429,11.43159),(2.010761,11.426901),(1.983372,11.414007),(1.948025,11.41672),(1.905754,11.432843),(1.879812,11.444858),(1.867617,11.446615),(1.858005,11.440311),(1.840642,11.445478),(1.821521,11.441602),(1.782247,11.426022),(1.763334,11.424678),(1.719099,11.427779),(1.703492,11.422921),(1.684372,11.413852),(1.638173,11.404215),(1.62112,11.395275),(1.601587,11.388686),(1.580606,11.427056),(1.563243,11.426022),(1.565,11.432637),(1.567273,11.446693),(1.56934,11.453307),(1.475289,11.460774),(1.455962,11.464702),(1.439633,11.473771),(1.433845,11.459405),(1.423613,11.453876),(1.423215,11.453748),(1.411107,11.449845),(1.398085,11.440311),(1.389817,11.428399),(1.388576,11.420002),(1.398085,11.398685),(1.381652,11.388686),(1.359017,11.378893),(1.33907,11.366103),(1.330389,11.347164),(1.336176,11.330033),(1.345892,11.316339),(1.347855,11.303497),(1.330389,11.288847),(1.323464,11.297089),(1.316333,11.29988),(1.309305,11.297089),(1.302483,11.288847),(1.296179,11.299621),(1.2845,11.312721),(1.273338,11.318225),(1.268377,11.30621),(1.270547,11.298278),(1.280366,11.288692),(1.28264,11.278873),(1.281089,11.271096),(1.268377,11.247893),(1.235201,11.263474),(1.218974,11.268047),(1.200061,11.268977),(1.191379,11.267014),(1.186211,11.263887),(1.18094,11.261355),(1.172155,11.261484),(1.173499,11.2666),(1.165954,11.277995),(1.156342,11.28554),(1.145904,11.269856),(1.135568,11.260115),(1.130608,11.247583),(1.149314,11.217249),(1.153242,11.183169),(1.158409,11.165935),(1.148074,11.1695),(1.128127,11.178879),(1.117482,11.178983),(1.113038,11.173867),(1.106216,11.155651),(1.100429,11.15162),(1.067459,11.144282),(1.062291,11.14206),(1.063325,11.126971),(1.067046,11.12834),(1.07335,11.133947),(1.082755,11.131802),(1.083892,11.12772),(1.082135,11.115292),(1.082755,11.110692),(1.085649,11.108729),(1.095158,11.10444),(1.097018,11.104491),(1.099085,11.092606),(1.099292,11.081289),(1.100945,11.070411),(1.10725,11.059791),(1.118619,11.048241),(1.117482,11.032196),(1.114174,11.027674),(1.106836,11.034418),(1.099705,11.044366),(1.097018,11.049275),(1.086889,11.052737),(1.05609,11.05607),(1.052163,11.055011),(1.041311,11.049585),(1.035006,11.049275),(1.033249,11.051575),(1.027978,11.061341),(1.025084,11.063512),(1.01971,11.065682),(1.014646,11.070359),(1.007928,11.075062),(0.986017,11.078498),(0.981366,11.080126),(0.976922,11.078369),(0.970307,11.06948),(0.964416,11.057414),(0.955941,11.044727),(0.952427,11.042402),(0.95129,11.032299),(0.951807,11.021086),(0.955321,11.01199),(0.963279,11.00827),(0.969067,11.002895),(0.969997,10.991165),(0.967517,10.979486),(0.963279,10.974137),(0.945399,10.974293),(0.931963,10.976101),(0.901474,10.992741),(0.77156,10.990364),(0.675338,10.988529),(0.612603,10.976566),(0.487649,10.933236),(0.499742,10.975688),(0.483619,10.979693),(0.487133,10.983672),(0.48858,10.987754),(0.489303,10.991914),(0.490647,10.996358),(0.49013,10.999511),(0.488786,11.001784),(0.486616,11.003205),(0.374779,11.025808),(0.287558,11.043436),(0.059588,11.089402),(-0.063118,11.114155),(-0.115062,11.124658),(-0.166109,11.13498),(-0.301682,11.162937),(-0.304473,11.146788),(-0.300545,11.137409),(-0.298297,11.128392),(-0.306126,11.113535),(-0.318813,11.101365),(-0.368939,11.065217),(-0.386923,11.086405),(-0.405888,11.101468),(-0.425215,11.101468),(-0.444387,11.077439),(-0.449038,11.062892),(-0.45126,11.040206),(-0.456686,11.029612),(-0.46852,11.020129),(-0.494823,11.007805),(-0.504228,10.996358),(-0.504228,10.996203),(-0.506709,10.993671),(-0.509706,10.991449),(-0.512961,10.989744),(-0.516475,10.988633),(-0.555439,10.98995),(-0.576213,10.987754),(-0.590579,10.982432),(-0.599829,10.965766),(-0.607116,10.94122),(-0.617244,10.918637),(-0.634763,10.907966),(-0.68277,10.953596),(-0.679773,10.960572),(-0.67228,10.968505),(-0.667991,10.976515),(-0.673933,10.983517),(-0.683235,10.984344),(-0.690212,10.981811),(-0.694656,10.982742),(-0.695999,10.994033),(-0.703017,10.994159),(-0.816974,10.996203),(-0.816974,10.996462),(-0.822141,11.003619),(-0.827774,11.005841),(-0.833665,11.003412),(-0.839401,10.996462),(-0.860795,10.992922),(-0.883171,10.968634),(-0.900586,10.966231),(-0.89392,10.979899),(-0.904359,10.979486),(-0.909475,10.98269),(-0.916451,10.996203),(-0.924047,11.001423),(-0.932471,11.003102),(-1.070343,11.013902),(-1.098714,11.009562),(-1.10755,10.994343),(-1.22806,10.99548),(-1.355287,10.99672),(-1.38035,11.001268),(-1.413553,11.01405),(-1.423584,11.017911),(-1.436057,11.022713),(-1.562406,11.026589),(-1.579821,11.021215),(-1.587004,11.003671),(-1.598683,10.997133),(-1.754074,10.995635),(-1.972872,10.993516),(-2.197871,10.991294),(-2.439769,10.988943),(-2.634951,10.986979),(-2.728798,10.986057),(-2.750706,10.985842),(-2.751119,10.996462),(-2.837341,10.998012),(-2.835946,10.992224),(-2.838711,10.985119),(-2.832716,10.966024),(-2.821761,10.948299),(-2.815767,10.929153),(-2.821399,10.90626),(-2.834861,10.89161),(-2.850803,10.879544),(-2.864239,10.864273),(-2.871629,10.843448),(-2.882662,10.797068),(-2.899482,10.76999),(-2.9031,10.747149),(-2.908577,10.737666),(-2.919274,10.727202),(-2.922323,10.721207),(-2.919959,10.711088),(-2.918913,10.706609),(-2.916949,10.706609),(-2.912634,10.705808),(-2.908035,10.703637),(-2.905141,10.699193),(-2.905115,10.692733),(-2.907337,10.688315),(-2.910154,10.684491),(-2.916251,10.668084),(-2.929661,10.644209),(-2.932504,10.634313),(-2.928266,10.615219),(-2.898294,10.562612),(-2.895865,10.552768),(-2.894211,10.531425),(-2.891524,10.521659),(-2.886899,10.515793),(-2.873386,10.502487),(-2.87044,10.497784),(-2.867391,10.47825),(-2.859562,10.465616),(-2.824448,10.435023),(-2.812149,10.428822),(-2.795871,10.426109),(-2.771428,10.425489),(-2.767552,10.4212),(-2.771893,10.41182),(-2.78104,10.402415),(-2.791995,10.398152),(-2.80494,10.397118),(-2.81463,10.393708),(-2.822329,10.387584),(-2.829461,10.378282),(-2.836282,10.363658),(-2.841295,10.343272),(-2.841295,10.322291),(-2.833182,10.305987),(-2.824448,10.302215),(-2.814216,10.301078),(-2.80569,10.299011),(-2.802098,10.292319),(-2.799669,10.280924),(-2.793184,10.278547),(-2.784451,10.278805),(-2.774839,10.27524),(-2.764865,10.269116),(-2.758354,10.266119),(-2.754943,10.260796),(-2.754375,10.247954),(-2.757682,10.234648),(-2.765124,10.225837),(-2.785381,10.210101),(-2.798455,10.189534),(-2.79892,10.169613),(-2.788481,10.124448),(-2.788481,10.038768),(-2.783572,10.018511),(-2.760886,9.984766),(-2.754375,9.966783),(-2.755564,9.941151),(-2.764865,9.895754),(-2.760524,9.870536),(-2.736753,9.832579),(-2.733911,9.822787),(-2.740267,9.812606),(-2.774839,9.77434),(-2.791582,9.740931),(-2.795303,9.720002),(-2.788481,9.699254),(-2.780317,9.690237),(-2.774839,9.689306),(-2.769258,9.689926),(-2.760524,9.685586),(-2.75546,9.677498),(-2.75422,9.668352),(-2.751016,9.659179),(-2.743404,9.653325),(-2.740164,9.650833),(-2.752928,9.639904),(-2.761506,9.625253),(-2.766467,9.608898),(-2.768018,9.592801),(-2.766261,9.576523),(-2.761093,9.566239),(-2.725281,9.533864),(-2.689211,9.488724),(-2.720475,9.459217),(-2.744918,9.408109),(-2.763677,9.391883),(-2.787603,9.393717),(-2.810418,9.411106),(-2.910154,9.542726),(-2.959892,9.638612),(-2.977824,9.685172),(-2.989994,9.708427),(-3.005677,9.724162),(-3.024643,9.728606),(-3.059059,9.718555),(-3.077094,9.719408),(-3.094561,9.733851),(-3.104379,9.757132),(-3.116911,9.805294),(-3.136936,9.82953),(-3.160112,9.834698),(-3.182566,9.835163),(-3.200007,9.845369),(-3.204399,9.865368),(-3.202229,9.888958),(-3.202565,9.908234),(-3.21476,9.915623),(-3.230237,9.90472),(-3.26406,9.857074),(-3.277857,9.843457),(-3.301732,9.841132),(-3.311809,9.854128),(-3.313566,9.874566),(-3.312739,9.894513),(-3.317183,9.901335),(-3.327518,9.897304),(-3.339249,9.890095),(-3.348344,9.886995),(-3.359015,9.892498),(-3.376559,9.908492),(-3.389168,9.913246),(-3.546471,9.926139),(-3.606261,9.918181),(-3.62334,9.921747),(-3.634011,9.92924),(-3.640548,9.937379),(-3.648171,9.944588),(-3.661658,9.948929),(-3.665043,9.946603),(-3.674319,9.93526),(-3.679641,9.932211),(-3.685946,9.933452),(-3.698994,9.94079),(-3.706462,9.941823),(-3.755037,9.93588),(-3.76961,9.931333),(-3.779739,9.924692),(-3.795758,9.907665),(-3.804259,9.901386),(-3.823483,9.895702),(-3.889706,9.894462),(-3.891625,9.8939),(-3.910093,9.888493),(-3.947739,9.86436),(-3.969185,9.858986),(-3.984042,9.851157),(-3.988253,9.834801),(-3.994609,9.820771),(-4.026675,9.820306),(-4.034969,9.817619),(-4.050317,9.810307),(-4.05135,9.807568),(-4.051712,9.802349),(-4.053675,9.79762),(-4.059877,9.796277),(-4.065716,9.798085),(-4.076155,9.803795),(-4.13305,9.820409),(-4.150259,9.818291),(-4.168294,9.804829),(-4.196974,9.764961),(-4.215423,9.754858),(-4.253095,9.750052),(-4.270329,9.743928),(-4.283636,9.732017),(-4.279191,9.731138),(-4.267513,9.727263),(-4.297795,9.695843),(-4.303299,9.686723),(-4.303454,9.677912),(-4.300482,9.654296),(-4.302988,9.641712),(-4.315933,9.616623),(-4.322477,9.608981),(-4.322548,9.608898),(-4.349678,9.620034),(-4.365026,9.624168),(-4.368023,9.608381),(-4.367817,9.591974),(-4.371175,9.582956),(-4.38487,9.589416),(-4.391588,9.600294),(-4.400166,9.633134),(-4.409106,9.647733),(-4.433368,9.653469),(-4.469206,9.651763),(-4.50171,9.655019),(-4.515921,9.67569),(-4.513647,9.694009),(-4.503829,9.719899),(-4.501607,9.737107),(-4.503958,9.742016),(-4.509953,9.745065),(-4.517782,9.746615),(-4.535946,9.746615),(-4.539098,9.744703),(-4.539899,9.740776),(-4.543051,9.734006),(-4.547961,9.720261),(-4.548426,9.706799),(-4.552198,9.696464),(-4.566719,9.692407),(-4.57832,9.696515),(-4.592712,9.717832),(-4.604029,9.727159),(-4.616949,9.713853),(-4.628731,9.707703),(-4.641107,9.706024),(-4.655809,9.706075),(-4.654724,9.703543),(-4.658264,9.6976),(-4.664827,9.690857),(-4.672914,9.685586),(-4.681079,9.682072),(-4.681803,9.682847),(-4.681544,9.686723),(-4.686608,9.692407),(-4.700096,9.69791),(-4.70547,9.702096),(-4.707641,9.70977),(-4.709088,9.720312),(-4.712808,9.726849),(-4.724384,9.737107),(-4.730017,9.744238),(-4.733324,9.749639),(-4.738337,9.753153),(-4.748646,9.754496),(-4.758594,9.753308),(-4.762134,9.749949),(-4.760454,9.745324),(-4.75477,9.740208),(-4.769963,9.737365),(-4.783192,9.758372),(-4.796447,9.754496),(-4.799315,9.762532),(-4.801227,9.766459),(-4.810115,9.77434),(-4.810115,9.781781),(-4.8004,9.78111),(-4.791899,9.78235),(-4.775905,9.788008),(-4.785414,9.804829),(-4.790323,9.827515),(-4.798462,9.842527),(-4.817557,9.836455),(-4.824274,9.856971),(-4.83846,9.86945),(-4.858329,9.875703),(-4.881739,9.877409),(-4.890059,9.879501),(-4.893495,9.884204),(-4.898017,9.888907),(-4.909386,9.891051),(-4.917085,9.886478),(-4.922356,9.87746),(-4.928015,9.870949),(-4.936671,9.873998),(-4.966075,9.901025),(-4.967315,9.912368),(-4.952949,9.953373),(-4.954809,9.959703),(-4.965713,9.983113),(-4.976927,9.997608),(-4.981397,10.007737),(-4.960209,10.008486),(-4.956411,10.021999),(-4.963336,10.040319),(-4.974524,10.055537),(-4.986642,10.063263),(-4.999793,10.069464),(-5.010516,10.07905),(-5.015581,10.097111),(-5.025528,10.088739),(-5.037233,10.083753),(-5.048343,10.085355),(-5.056483,10.097111),(-5.042866,10.103338),(-5.049377,10.105353),(-5.055139,10.10804),(-5.061702,10.110056),(-5.070099,10.110159),(-5.06103,10.118453),(-5.037595,10.126489),(-5.039455,10.134344),(-5.064725,10.150803),(-5.070719,10.161009),(-5.06395,10.179044),(-5.090718,10.177933),(-5.09015,10.188811),(-5.081597,10.206897),(-5.084414,10.227439),(-5.087333,10.220824),(-5.091907,10.214339),(-5.097849,10.209275),(-5.104903,10.206949),(-5.117073,10.208034),(-5.11821,10.212479),(-5.114412,10.218292),(-5.111802,10.223718),(-5.111802,10.27865),(-5.119192,10.293533),(-5.119882,10.293983),(-5.135677,10.304282),(-5.152058,10.305625),(-5.159499,10.292319),(-5.168439,10.291337),(-5.217584,10.31994),(-5.233552,10.315676),(-5.279802,10.32242),(-5.296649,10.32304),(-5.304142,10.318415),(-5.309206,10.311491),(-5.315511,10.305264),(-5.327086,10.302576),(-5.338507,10.302215),(-5.343778,10.303093),(-5.34817,10.305987),(-5.353338,10.308261),(-5.357058,10.304385),(-5.360831,10.298752),(-5.365533,10.295703),(-5.385739,10.296479),(-5.402534,10.300561),(-5.416228,10.307537),(-5.426977,10.316865),(-5.430077,10.322937),(-5.433488,10.331877),(-5.437829,10.340016),(-5.443772,10.34353),(-5.453022,10.343943),(-5.459946,10.345158),(-5.474157,10.350325),(-5.475294,10.367715),(-5.48749,10.392933),(-5.505111,10.415567),(-5.522578,10.425489),(-5.5171,10.439984),(-5.508987,10.490937),(-5.505163,10.499179),(-5.48165,10.535327),(-5.468111,10.58783),(-5.471057,10.597365),(-5.47855,10.604238),(-5.477413,10.61956),(-5.470488,10.635605),(-5.460566,10.644571),(-5.475914,10.650385),(-5.477154,10.658808),(-5.482115,10.675215),(-5.482632,10.684233),(-5.473072,10.737873),(-5.467956,10.752678),(-5.461186,10.760042),(-5.45297,10.763969),(-5.446459,10.768698),(-5.445012,10.778568),(-5.445322,10.786991),(-5.431421,10.844688),(-5.43509,10.856909),(-5.447027,10.877993),(-5.465579,10.947886),(-5.479118,10.975533),(-5.501804,10.97021),(-5.495603,10.996203),(-5.505602,11.047985),(-5.507334,11.056949),(-5.504233,11.072684),(-5.489764,11.082115),(-5.390131,11.094699),(-5.373026,11.099763),(-5.356283,11.106894),(-5.332512,11.12157),(-5.322332,11.135549),(-5.316182,11.176322),(-5.306726,11.199395),(-5.275255,11.230711),(-5.262852,11.251588),(-5.26094,11.267737),(-5.267865,11.37202),(-5.263472,11.390184),(-5.248176,11.403181),(-5.22642,11.41349),(-5.218307,11.422198),(-5.219186,11.435143),(-5.224612,11.45801),(-5.224663,11.54077),(-5.233914,11.575987),(-5.269467,11.604099),(-5.280732,11.605753),(-5.290964,11.604461),(-5.299956,11.606424),(-5.307604,11.617638),(-5.307811,11.629007),(-5.302281,11.639859),(-5.294788,11.650298),(-5.289259,11.660426),(-5.280681,11.699494),(-5.278562,11.721456),(-5.279544,11.739026),(-5.28714,11.758922),(-5.298974,11.772668),(-5.314787,11.782486),(-5.334269,11.790806),(-5.344656,11.793907),(-5.353286,11.794527),(-5.370649,11.791064),(-5.374525,11.79525),(-5.400415,11.810185),(-5.405996,11.812303),(-5.412197,11.823569),(-5.412352,11.82853),(-5.405944,11.830442),(-5.392302,11.832354),(-5.387909,11.830804),(-5.37561,11.822225),(-5.369874,11.820158),(-5.364552,11.82176),(-5.357058,11.829615),(-5.353803,11.831734),(-5.319025,11.837418),(-5.314839,11.83933),(-5.311066,11.842896),(-5.306519,11.846048),(-5.300163,11.846358),(-5.293445,11.843206),(-5.288019,11.839123),(-5.282489,11.836436),(-5.275151,11.837418),(-5.268227,11.843051),(-5.248228,11.870439),(-5.209471,11.901497),(-5.182909,11.930901),(-5.167819,11.943665),(-5.136994,11.953122),(-5.103947,11.972759),(-5.089323,11.97927),(-5.073768,11.98051),(-5.034313,11.97927),(-5.016046,11.981285),(-5.004703,11.980665),(-4.994238,11.983249),(-4.984523,11.988572),(-4.975454,11.996271),(-4.95375,12.005108),(-4.932071,12.003144),(-4.910677,11.998132),(-4.889955,11.997925),(-4.847245,12.013066),(-4.826238,12.012705),(-4.806808,11.996271),(-4.789522,12.001801),(-4.761281,12.006607),(-4.746889,12.015082),(-4.738983,12.02521),(-4.732281,12.037263),(-4.725133,12.050118),(-4.714617,12.059007),(-4.704023,12.061487),(-4.683715,12.059058),(-4.673586,12.05973),(-4.653716,12.069135),(-4.652737,12.071627),(-4.648678,12.081951),(-4.646663,12.098022),(-4.636121,12.117556),(-4.600309,12.137555),(-4.570233,12.138898),(-4.560466,12.149492),(-4.585529,12.197241),(-4.497421,12.26871),(-4.493545,12.272844),(-4.492253,12.278838),(-4.49401,12.290104),(-4.490496,12.305762),(-4.490703,12.313823),(-4.488171,12.320696),(-4.47719,12.327311),(-4.462488,12.328189),(-4.452669,12.320283),(-4.444814,12.309431),(-4.435823,12.301731),(-4.406135,12.307467),(-4.415359,12.350307),(-4.451636,12.435314),(-4.443678,12.459447),(-4.426624,12.479653),(-4.407607,12.497946),(-4.393448,12.516446),(-4.386885,12.530192),(-4.387247,12.533965),(-4.392647,12.537427),(-4.401406,12.550398),(-4.42249,12.597217),(-4.439078,12.613288),(-4.482538,12.646258),(-4.491323,12.662794),(-4.485251,12.714677),(-4.481711,12.717416),(-4.474942,12.715762),(-4.46437,12.717251),(-4.464296,12.717261),(-4.435254,12.728423),(-4.402026,12.736562),(-4.36885,12.738991),(-4.339446,12.73279),(-4.310921,12.716021),(-4.297227,12.712145),(-4.276298,12.714677),(-4.257642,12.72093),(-4.245472,12.728936),(-4.243974,12.729922),(-4.23413,12.74235),(-4.213278,12.807178),(-4.211883,12.819193),(-4.224647,12.864513),(-4.221314,12.921254),(-4.229324,12.948952),(-4.24785,12.971948),(-4.276918,12.996236),(-4.289733,13.01347),(-4.316398,13.070857),(-4.345363,13.097057),(-4.351073,13.106075),(-4.351073,13.118322),(-4.345906,13.127133),(-4.339601,13.135298),(-4.327044,13.168551),(-4.310197,13.175553),(-4.24617,13.172479),(-4.234801,13.175605),(-4.227773,13.184442),(-4.230021,13.193149),(-4.251209,13.204751),(-4.258107,13.21413),(-4.253508,13.22909),(-4.23878,13.246789),(-4.220668,13.262835),(-4.205501,13.272989),(-4.195837,13.274695),(-4.186458,13.272834),(-4.176872,13.272369),(-4.16602,13.278157),(-4.147106,13.299603),(-4.131578,13.323839),(-4.114654,13.364534),(-4.104267,13.382698),(-4.087549,13.397995),(-4.079307,13.402129),(-4.052539,13.409002),(-4.043495,13.414454),(-4.028199,13.431533),(-4.016029,13.43577),(-4.005358,13.439517),(-3.990217,13.449129),(-3.97691,13.460627),(-3.971613,13.469954),(-3.979468,13.47538),(-3.992232,13.476233),(-3.997968,13.480522),(-3.984481,13.496051),(-3.981251,13.49897),(-3.977737,13.499926),(-3.974094,13.498945),(-3.970321,13.496154),(-3.965468,13.489217),(-3.964482,13.487808),(-3.959288,13.467939),(-3.956059,13.46166),(-3.94748,13.458198),(-3.923399,13.453754),(-3.917973,13.451066),(-3.918593,13.440318),(-3.925544,13.436313),(-3.934923,13.434892),(-3.942726,13.431946),(-3.963009,13.413162),(-3.971613,13.40833),(-3.984042,13.39647),(-3.971613,13.386755),(-3.948411,13.380838),(-3.928825,13.38027),(-3.908878,13.381975),(-3.8926,13.378926),(-3.85808,13.365516),(-3.817101,13.35469),(-3.798626,13.347145),(-3.724419,13.288828),(-3.678711,13.26175),(-3.596882,13.199402),(-3.589802,13.197387),(-3.576599,13.199299),(-3.569958,13.196767),(-3.553913,13.180256),(-3.54505,13.174494),(-3.538487,13.173409),(-3.516111,13.1739),(-3.473922,13.167601),(-3.461593,13.165761),(-3.449475,13.16881),(-3.439475,13.184855),(-3.440586,13.202839),(-3.452265,13.237514),(-3.448544,13.265781),(-3.42653,13.27423),(-3.262406,13.283919),(-3.248634,13.292781),(-3.283955,13.542198),(-3.269176,13.579095),(-3.263905,13.602659),(-3.259719,13.658315),(-3.266282,13.682344),(-3.286952,13.69777),(-3.267057,13.717045),(-3.240418,13.707976),(-3.195821,13.674903),(-3.167941,13.672112),(-3.146031,13.67666),(-3.125102,13.67728),(-3.100039,13.662733),(-3.08221,13.646222),(-3.077301,13.636791),(-3.07451,13.622141),(-3.067508,13.606767),(-3.05601,13.61085),(-3.038621,13.629583),(-3.026968,13.635345),(-3.019113,13.637515),(-2.994774,13.634983),(-2.986402,13.632063),(-2.979322,13.627567),(-2.97232,13.624467),(-2.965008,13.625655),(-2.930473,13.638523),(-2.895245,13.651648),(-2.923383,13.746035),(-2.928059,13.799624),(-2.912169,13.837942),(-2.89447,13.866571),(-2.855377,13.996175),(-2.85703,13.997777),(-2.858606,14.000232),(-2.861552,14.00173),(-2.867288,14.000542),(-2.840855,14.042994),(-2.69319,14.123196),(-2.676265,14.141729),(-2.619758,14.203604),(-2.597382,14.222311),(-2.516147,14.267864),(-2.46168,14.280912),(-2.385612,14.264712),(-2.151879,14.15614),(-2.11984,14.148776),(-2.104337,14.151179),(-2.085008,14.159668),(-2.035918,14.181229),(-2.027288,14.188127),(-2.023412,14.198643),(-2.005015,14.444236),(-1.997057,14.470694),(-1.967033,14.483742),(-1.919129,14.485861),(-1.836963,14.479582),(-1.766683,14.483174),(-1.69692,14.496119),(-1.350275,14.714969),(-1.307745,14.734657),(-1.116697,14.780443),(-1.07856,14.796359),(-1.043317,14.817908),(-1.043138,14.818062),(-0.836404,14.995985),(-0.836249,14.996088),(-0.782816,15.048385),(-0.771272,15.056619),(-0.752895,15.069727),(-0.719719,15.078461),(-0.500343,15.079721),(-0.4679,15.079908),(-0.458649,15.075463),(-0.435602,15.015157),(-0.425732,15.0026),(-0.397671,15.002135)] +Bulgaria [(22.919562,43.834225),(23.052551,43.84282),(23.131849,43.847945),(23.161924,43.857324),(23.196961,43.86275),(23.234478,43.877297),(23.325151,43.886592),(23.484695,43.880604),(23.592699,43.837429),(23.620854,43.83401),(23.636107,43.832158),(23.720753,43.845826),(23.742871,43.8427),(23.799922,43.818463),(24.149606,43.75472),(24.159383,43.752938),(24.336705,43.759251),(24.358234,43.760017),(24.375494,43.763867),(24.431201,43.794176),(24.466341,43.802418),(24.500137,43.799498),(24.661763,43.755657),(24.705603,43.743765),(24.752628,43.738804),(24.963675,43.749605),(25.0816,43.718935),(25.211308,43.711881),(25.252339,43.704646),(25.285405,43.690391),(25.28872,43.688962),(25.323033,43.669713),(25.35962,43.654287),(25.403131,43.65005),(25.426075,43.654391),(25.467417,43.667749),(25.48245,43.669715),(25.488759,43.67054),(25.533821,43.668679),(25.556558,43.670359),(25.575059,43.677387),(25.593869,43.680668),(25.616503,43.687748),(25.637897,43.697282),(25.653503,43.708134),(25.671384,43.717359),(25.732948,43.718781),(25.739596,43.718935),(25.781144,43.732009),(25.804399,43.759914),(25.806259,43.763661),(25.839332,43.788439),(25.869304,43.800893),(25.916433,43.844379),(25.924495,43.858616),(25.934003,43.870321),(26.054306,43.934322),(26.061644,43.949773),(26.079317,43.969049),(26.116214,43.998866),(26.150734,44.012405),(26.231453,44.027495),(26.310518,44.052609),(26.332335,44.054926),(26.415791,44.063789),(26.614168,44.084855),(26.647758,44.093382),(26.667808,44.095087),(26.677317,44.097051),(26.697212,44.106094),(26.708685,44.10811),(26.753695,44.10811),(26.789455,44.115965),(26.884126,44.156531),(27.001535,44.165109),(27.027476,44.177046),(27.100237,44.14449),(27.205553,44.129246),(27.226741,44.120719),(27.251132,44.122373),(27.252662,44.121519),(27.269012,44.112399),(27.26431,44.089765),(27.285342,44.072453),(27.341669,44.053074),(27.353555,44.045271),(27.372882,44.020725),(27.383837,44.015092),(27.574523,44.016281),(27.633434,44.029768),(27.656275,44.023877),(27.676119,43.993543),(27.682515,43.987256),(27.721698,43.94874),(27.787327,43.960419),(27.85647,43.988634),(27.912074,43.993336),(27.912074,43.993233),(27.935845,43.964398),(27.98101,43.84934),(28.014806,43.830039),(28.221254,43.761981),(28.434574,43.735213),(28.57838,43.741278),(28.576182,43.727525),(28.57309,43.606147),(28.575531,43.593329),(28.585704,43.575832),(28.595876,43.563707),(28.602712,43.55272),(28.603526,43.538153),(28.594574,43.512519),(28.578461,43.48078),(28.560313,43.453843),(28.545177,43.442532),(28.535004,43.438625),(28.488617,43.40644),(28.479259,43.396796),(28.473888,43.384263),(28.473155,43.366848),(28.459483,43.380683),(28.414561,43.398871),(28.404959,43.40469),(28.393809,43.414293),(28.368663,43.42178),(28.321625,43.42829),(28.299164,43.425035),(28.261567,43.410956),(28.243175,43.407782),(28.177989,43.40998),(28.157237,43.407782),(28.118826,43.391547),(28.091563,43.363959),(28.087006,43.355251),(28.031098,43.248969),(28.017589,43.232733),(28.000173,43.223212),(27.931977,43.209784),(27.920584,43.204047),(27.913829,43.202338),(27.903982,43.202338),(27.903982,43.195502),(27.938731,43.1765),(27.945567,43.16885),(27.944347,43.157131),(27.925141,43.113593),(27.911388,43.065172),(27.904307,43.055854),(27.895518,43.049262),(27.887706,43.042141),(27.883556,43.030992),(27.885427,43.008612),(27.900401,42.962877),(27.903982,42.942288),(27.898448,42.874661),(27.903982,42.859687),(27.883962,42.848375),(27.883556,42.831936),(27.891612,42.81037),(27.897146,42.784003),(27.897146,42.736233),(27.894705,42.717475),(27.892263,42.710517),(27.841075,42.708319),(27.787364,42.715155),(27.743175,42.716051),(27.732677,42.714504),(27.725597,42.708482),(27.719005,42.694566),(27.715831,42.683743),(27.71697,42.674506),(27.724132,42.666978),(27.739513,42.661078),(27.712738,42.65766),(27.6692,42.643704),(27.646739,42.64057),(27.628429,42.628974),(27.630382,42.602729),(27.641449,42.574774),(27.650157,42.558051),(27.634044,42.563707),(27.540863,42.565497),(27.511485,42.553046),(27.498546,42.532457),(27.491466,42.507758),(27.480154,42.482896),(27.46225,42.489569),(27.452891,42.480129),(27.45338,42.465237),(27.465668,42.455634),(27.462087,42.448717),(27.461111,42.443549),(27.465668,42.42829),(27.468435,42.435777),(27.4699,42.437079),(27.469412,42.437201),(27.465668,42.441352),(27.472667,42.461859),(27.503917,42.437323),(27.514171,42.435126),(27.526378,42.443671),(27.534434,42.455268),(27.544444,42.460028),(27.562022,42.448188),(27.571056,42.458482),(27.5796,42.457221),(27.587738,42.451483),(27.595551,42.448188),(27.60963,42.451158),(27.619477,42.455878),(27.629405,42.458645),(27.643321,42.455634),(27.642833,42.450507),(27.641775,42.44953),(27.639822,42.449774),(27.636485,42.448188),(27.642426,42.430894),(27.652192,42.418524),(27.667735,42.416083),(27.691661,42.42829),(27.693533,42.418891),(27.699067,42.413886),(27.707856,42.412746),(27.719005,42.4147),(27.719005,42.407213),(27.713227,42.405951),(27.698009,42.400377),(27.705414,42.390611),(27.709646,42.388129),(27.719005,42.386705),(27.709483,42.376776),(27.708344,42.363105),(27.714366,42.349189),(27.725841,42.338935),(27.740408,42.334296),(27.752126,42.335395),(27.764496,42.338324),(27.780447,42.338935),(27.780447,42.332709),(27.774587,42.327216),(27.774425,42.321723),(27.779145,42.316311),(27.787852,42.310981),(27.76295,42.2956),(27.75115,42.277045),(27.75587,42.25849),(27.780447,42.243354),(27.776052,42.240668),(27.775645,42.239651),(27.773692,42.235907),(27.809744,42.218411),(27.815278,42.211982),(27.819998,42.204657),(27.831391,42.195014),(27.8449,42.186103),(27.856212,42.181301),(27.854177,42.177924),(27.85141,42.170111),(27.849376,42.16706),(27.87908,42.154242),(27.886729,42.147366),(27.903982,42.119818),(27.957774,42.094306),(27.964366,42.084621),(27.972667,42.075385),(27.986583,42.072089),(27.982432,42.061103),(27.987315,42.051744),(27.996918,42.044013),(28.007009,42.037909),(28.007579,42.032904),(28.006114,42.031562),(28.003429,42.03148),(28.000173,42.030463),(28.011567,42.021389),(28.019054,42.00845),(28.020356,41.994574),(28.013845,41.982652),(28.016775,41.972561),(28.016783,41.972531),(27.98101,41.978524),(27.96592,41.982141),(27.917035,41.977904),(27.903392,41.981056),(27.876934,41.99072),(27.852232,41.995448),(27.843034,41.995758),(27.824017,41.993484),(27.819935,41.994699),(27.815955,41.995138),(27.811925,41.994699),(27.807997,41.993484),(27.804948,41.983433),(27.804897,41.969894),(27.802726,41.96005),(27.818281,41.952867),(27.815335,41.946795),(27.80283,41.943074),(27.789807,41.942686),(27.776165,41.946123),(27.723971,41.967595),(27.687074,41.968602),(27.609301,41.953487),(27.606873,41.943513),(27.603359,41.93863),(27.598088,41.938604),(27.590543,41.942893),(27.582378,41.934883),(27.572198,41.929845),(27.550752,41.924212),(27.552096,41.921835),(27.554886,41.920336),(27.557935,41.91907),(27.560674,41.917675),(27.55747,41.915505),(27.551269,41.913102),(27.548892,41.91088),(27.562741,41.906435),(27.546411,41.901164),(27.533182,41.908063),(27.509463,41.933178),(27.494321,41.942841),(27.420837,41.973718),(27.39686,41.989324),(27.374845,42.008703),(27.332471,42.057434),(27.305289,42.077588),(27.273353,42.091747),(27.238213,42.097922),(27.216405,42.095623),(27.203796,42.08813),(27.181576,42.065883),(27.178992,42.061878),(27.178165,42.058364),(27.173824,42.057072),(27.149588,42.061826),(27.127212,42.062576),(27.11605,42.061826),(27.10065,42.071102),(27.0837,42.078415),(27.06551,42.082704),(27.047903,42.08292),(27.046545,42.082936),(27.022619,42.073893),(27.000398,42.04281),(26.981071,42.032862),(26.96717,42.028495),(26.95823,42.018237),(26.950065,42.006171),(26.938903,41.996223),(26.930221,41.994518),(26.911463,41.996792),(26.901076,41.993484),(26.890327,41.985423),(26.881129,41.985526),(26.871724,41.988136),(26.860768,41.987903),(26.85002,41.982865),(26.837899,41.97522),(26.827695,41.968783),(26.819427,41.965657),(26.80842,41.967879),(26.78992,41.979945),(26.780566,41.983433),(26.768578,41.980772),(26.746977,41.964494),(26.736745,41.958965),(26.717573,41.957311),(26.623573,41.969041),(26.605693,41.967414),(26.589467,41.958758),(26.560632,41.935684),(26.553293,41.931576),(26.547092,41.926899),(26.542958,41.920362),(26.544715,41.916435),(26.556807,41.91075),(26.559805,41.90734),(26.558978,41.901733),(26.55474,41.892948),(26.553604,41.887703),(26.552895,41.881643),(26.552053,41.874448),(26.547816,41.856283),(26.539548,41.83799),(26.526112,41.824244),(26.478363,41.813289),(26.375527,41.816622),(26.334185,41.789543),(26.320026,41.765462),(26.316305,41.743758),(26.32323,41.723682),(26.333359,41.713036),(26.294911,41.710323),(26.273931,41.714897),(26.261012,41.723062),(26.23445,41.745825),(26.226182,41.749675),(26.211816,41.750476),(26.189905,41.734689),(26.135128,41.733397),(26.108359,41.727893),(26.081488,41.711512),(26.074046,41.709135),(26.067225,41.708851),(26.060507,41.7073),(26.053686,41.701513),(26.048105,41.689084),(26.047485,41.674615),(26.050275,41.660456),(26.055029,41.648751),(26.05949,41.643777),(26.066915,41.635496),(26.081178,41.630457),(26.095234,41.62839),(26.106706,41.624282),(26.115284,41.616634),(26.121072,41.608211),(26.13027,41.582683),(26.130994,41.575138),(26.129443,41.559377),(26.1312,41.552659),(26.136781,41.549196),(26.152491,41.547026),(26.158072,41.542323),(26.163136,41.529146),(26.16448,41.517725),(26.16293,41.50646),(26.159312,41.493799),(26.147634,41.484756),(26.145877,41.478038),(26.156212,41.460416),(26.160449,41.455869),(26.174299,41.445998),(26.177399,41.439952),(26.175642,41.431891),(26.170578,41.429565),(26.164273,41.42786),(26.159002,41.421814),(26.14784,41.396906),(26.132441,41.371533),(26.120865,41.357787),(26.114664,41.355203),(26.107326,41.356598),(26.021853,41.341664),(26.008934,41.336806),(25.982269,41.323267),(25.959635,41.314999),(25.948576,41.313965),(25.93514,41.315929),(25.921187,41.316032),(25.896279,41.306265),(25.882017,41.304043),(25.86269,41.310089),(25.833337,41.334636),(25.811013,41.341044),(25.800781,41.338046),(25.763471,41.319029),(25.728744,41.317066),(25.717479,41.31412),(25.70518,41.307299),(25.698049,41.301925),(25.691227,41.298411),(25.679962,41.29717),(25.670453,41.299186),(25.649576,41.308487),(25.639758,41.311071),(25.551494,41.31567),(25.537955,41.312208),(25.530203,41.302751),(25.523692,41.291693),(25.514907,41.283476),(25.505089,41.280582),(25.497337,41.281202),(25.489482,41.283063),(25.479096,41.283786),(25.453464,41.280427),(25.285722,41.239396),(25.262261,41.238104),(25.23911,41.240895),(25.21968,41.249731),(25.177098,41.293863),(25.157875,41.30611),(25.153847,41.307535),(25.116534,41.320735),(25.112606,41.324145),(25.104855,41.334067),(25.101858,41.336651),(25.096793,41.336703),(25.08036,41.334067),(24.916959,41.386364),(24.886367,41.400627),(24.872931,41.401867),(24.863009,41.400316),(24.842132,41.394735),(24.803271,41.392668),(24.800171,41.379336),(24.802858,41.361921),(24.794279,41.3474),(24.774436,41.348072),(24.752628,41.362748),(24.718728,41.395717),(24.699195,41.408946),(24.680901,41.415509),(24.661264,41.41768),(24.638217,41.41768),(24.644314,41.427653),(24.609484,41.42724),(24.595842,41.429772),(24.580442,41.440521),(24.579719,41.44419),(24.582199,41.455249),(24.581062,41.460209),(24.577238,41.463568),(24.56773,41.468116),(24.564113,41.471062),(24.558738,41.476849),(24.553571,41.480777),(24.549436,41.485428),(24.546543,41.493644),(24.543339,41.521343),(24.530936,41.547543),(24.510162,41.56165),(24.481327,41.553227),(24.459209,41.549506),(24.438849,41.527699),(24.423966,41.525218),(24.402882,41.527854),(24.387483,41.526665),(24.353893,41.519121),(24.345005,41.518397),(24.318236,41.520774),(24.309554,41.519792),(24.303043,41.51695),(24.296119,41.515245),(24.286817,41.517622),(24.28506,41.523151),(24.287334,41.531626),(24.286403,41.54036),(24.26687,41.549765),(24.250747,41.563459),(24.23328,41.561805),(24.214366,41.555759),(24.197698,41.547711),(24.19628,41.547026),(24.181604,41.537362),(24.17747,41.531006),(24.173129,41.515297),(24.170235,41.511576),(24.162793,41.512041),(24.158453,41.51633),(24.154008,41.522118),(24.146257,41.526769),(24.116491,41.533383),(24.076597,41.536019),(24.047348,41.525735),(24.049829,41.493644),(24.052516,41.471475),(24.051999,41.463),(24.045901,41.455455),(24.034739,41.451321),(24.022854,41.453078),(24.000736,41.464137),(23.997119,41.457006),(23.992365,41.454628),(23.986887,41.453698),(23.981306,41.450856),(23.964666,41.43835),(23.949887,41.437575),(23.902861,41.463517),(23.894799,41.464344),(23.867721,41.445482),(23.851598,41.439591),(23.830927,41.435611),(23.80974,41.433803),(23.792067,41.434475),(23.777081,41.429049),(23.754446,41.400678),(23.73822,41.397474),(23.705354,41.403159),(23.672177,41.402952),(23.65285,41.397629),(23.627736,41.378509),(23.624847,41.377094),(23.612439,41.371016),(23.578953,41.371998),(23.513014,41.397733),(23.414519,41.399903),(23.395502,41.395252),(23.365116,41.378561),(23.347236,41.371223),(23.326049,41.369311),(23.31561,41.376855),(23.306205,41.388379),(23.287705,41.398198),(23.269928,41.397268),(23.24657,41.389723),(23.224246,41.379026),(23.209777,41.368587),(23.206366,41.360939),(23.204816,41.342697),(23.199545,41.332982),(23.190656,41.326057),(23.179701,41.321355),(23.15717,41.316342),(23.115209,41.312673),(22.916978,41.335773),(22.940852,41.349829),(22.94447,41.368432),(22.939406,41.389413),(22.937339,41.410755),(22.940542,41.416905),(22.952118,41.427705),(22.954598,41.432408),(22.953358,41.438195),(22.94757,41.448376),(22.946227,41.453233),(22.943599,41.523201),(22.943023,41.538551),(22.94788,41.555139),(22.948707,41.560978),(22.946434,41.567748),(22.936925,41.57891),(22.933721,41.584595),(22.932068,41.597953),(22.932998,41.612345),(22.936098,41.626168),(22.940852,41.63764),(22.945813,41.641077),(22.961523,41.644488),(22.967001,41.647046),(22.970101,41.652032),(22.976613,41.666553),(22.985435,41.677198),(22.998627,41.693115),(23.009582,41.71637),(23.008859,41.739934),(22.991185,41.760992),(22.98054,41.764739),(22.956872,41.765669),(22.945917,41.769338),(22.939716,41.776702),(22.918322,41.814348),(22.907676,41.848584),(22.901372,41.860418),(22.896721,41.864448),(22.885042,41.869151),(22.882088,41.871618),(22.880804,41.872691),(22.878221,41.880261),(22.878634,41.895015),(22.877084,41.902043),(22.866335,41.924884),(22.858894,41.94788),(22.857137,41.971884),(22.85476,41.982632),(22.846905,41.993484),(22.846595,41.993639),(22.845768,42.006869),(22.845621,42.007408),(22.843701,42.014465),(22.838223,42.019478),(22.826958,42.025085),(22.821273,42.025369),(22.805977,42.02139),(22.798949,42.021235),(22.791094,42.025808),(22.787684,42.032578),(22.785306,42.039141),(22.780862,42.043171),(22.77063,42.043998),(22.725052,42.042474),(22.718437,42.044463),(22.713993,42.048623),(22.710272,42.05299),(22.705725,42.055935),(22.675856,42.060612),(22.627177,42.079127),(22.617771,42.082704),(22.531058,42.129109),(22.510181,42.144793),(22.506939,42.148927),(22.494678,42.164559),(22.481449,42.193317),(22.443622,42.214427),(22.345023,42.313439),(22.364144,42.320984),(22.405795,42.321552),(22.423985,42.325893),(22.438454,42.340052),(22.454371,42.376768),(22.46977,42.391703),(22.485066,42.397155),(22.497572,42.399196),(22.508838,42.404932),(22.519483,42.420926),(22.533125,42.45759),(22.536536,42.47839),(22.532505,42.493402),(22.532505,42.493557),(22.524857,42.507665),(22.512145,42.519189),(22.481449,42.535622),(22.429669,42.571408),(22.425328,42.572855),(22.428842,42.592776),(22.441318,42.632891),(22.444552,42.64329),(22.449203,42.667965),(22.442072,42.681685),(22.468116,42.718324),(22.481449,42.727677),(22.482586,42.730675),(22.482896,42.733775),(22.482586,42.736824),(22.481449,42.739821),(22.466566,42.748529),(22.45313,42.763592),(22.429359,42.806122),(22.425845,42.809843),(22.427395,42.813615),(22.430446,42.817077),(22.436801,42.824286),(22.445482,42.830178),(22.470907,42.840125),(22.481449,42.84674),(22.497055,42.864413),(22.506047,42.870123),(22.519793,42.870356),(22.53757,42.868341),(22.544494,42.871389),(22.544785,42.871706),(22.549972,42.877358),(22.563615,42.884283),(22.5909,42.886892),(22.666244,42.871932),(22.69663,42.87741),(22.727015,42.886892),(22.738798,42.897383),(22.739579,42.898858),(22.745516,42.910069),(22.763189,42.958645),(22.76939,42.97128),(22.776418,42.979729),(22.788097,42.984897),(22.815796,42.989703),(22.828818,42.993449),(22.828921,42.993449),(22.829025,42.993501),(22.829025,42.993656),(22.842254,43.007505),(22.884215,43.036651),(22.889486,43.044376),(22.896721,43.062721),(22.901682,43.069749),(22.910157,43.075279),(22.927107,43.081144),(22.935271,43.085562),(22.955632,43.108274),(22.974029,43.141192),(22.984571,43.174627),(22.982902,43.187318),(22.981367,43.198992),(22.964727,43.204418),(22.915531,43.212247),(22.897754,43.220335),(22.883802,43.230592),(22.857343,43.256947),(22.833159,43.274647),(22.826958,43.28139),(22.823857,43.289297),(22.820756,43.307539),(22.817139,43.315497),(22.80453,43.328984),(22.73301,43.381513),(22.724343,43.38606),(22.719367,43.388671),(22.702934,43.394045),(22.693219,43.394872),(22.674202,43.394148),(22.664694,43.396732),(22.658926,43.401295),(22.656529,43.403192),(22.645367,43.420297),(22.637822,43.426369),(22.62852,43.428255),(22.606919,43.427402),(22.596274,43.429159),(22.586766,43.43443),(22.57271,43.44815),(22.565785,43.453344),(22.532609,43.464842),(22.518863,43.474247),(22.509354,43.493341),(22.490647,43.540883),(22.478452,43.559229),(22.477625,43.564164),(22.478658,43.569176),(22.481449,43.574111),(22.482689,43.576695),(22.483103,43.579279),(22.482689,43.581734),(22.481449,43.584137),(22.478142,43.587573),(22.477108,43.591294),(22.478142,43.594911),(22.481449,43.598529),(22.481759,43.598942),(22.481966,43.599459),(22.481759,43.599975),(22.481449,43.600647),(22.473801,43.612998),(22.472871,43.635942),(22.466256,43.64912),(22.455921,43.656406),(22.426465,43.668214),(22.41396,43.676663),(22.404865,43.687179),(22.396906,43.699401),(22.390498,43.712449),(22.386054,43.725498),(22.385848,43.733817),(22.389568,43.750509),(22.388535,43.758286),(22.362593,43.780843),(22.349467,43.807921),(22.354738,43.829703),(22.367554,43.852751),(22.377063,43.883524),(22.379026,43.913496),(22.382024,43.918561),(22.391945,43.931867),(22.394529,43.936337),(22.396803,43.951944),(22.39732,43.980934),(22.399594,43.993336),(22.411789,44.006927),(22.43432,44.013955),(22.465885,44.017624),(22.481449,44.019433),(22.50367,44.019898),(22.514935,44.030285),(22.522583,44.044703),(22.534159,44.057157),(22.554623,44.062428),(22.57519,44.061394),(22.592967,44.063926),(22.604749,44.079378),(22.604646,44.088163),(22.598134,44.109298),(22.597101,44.119065),(22.599065,44.130331),(22.6094,44.159941),(22.607953,44.159993),(22.605989,44.163145),(22.604852,44.168468),(22.606196,44.174566),(22.608573,44.175858),(22.624799,44.189397),(22.639992,44.207329),(22.648777,44.213995),(22.69164,44.228435),(22.906436,44.122889),(22.942609,44.111469),(22.988085,44.107025),(23.008307,44.100446),(23.030976,44.093072),(23.040071,44.062325),(23.023018,44.031629),(22.988085,44.017676),(22.966277,44.015557),(22.926486,44.006152),(22.905816,44.003982),(22.885869,43.994525),(22.874707,43.972046),(22.850522,43.896986),(22.851039,43.874352),(22.863441,43.855412),(22.888763,43.839522),(22.919562,43.834225)] +Bahrain [(50.551606,26.194241),(50.594737,26.160305),(50.604871,26.174732),(50.619898,26.185466),(50.626339,26.170438),(50.632779,26.146823),(50.64566,26.14575),(50.635507,26.134382),(50.634926,26.115694),(50.614757,26.111151),(50.620616,26.052965),(50.618419,25.964748),(50.603526,25.85456),(50.594493,25.832709),(50.56544,25.7897),(50.565278,25.789537),(50.558604,25.81977),(50.547211,25.852932),(50.531423,25.88524),(50.511404,25.913031),(50.467784,25.957587),(50.46046,25.985256),(50.46046,25.985297),(50.479991,26.018866),(50.485444,26.033433),(50.490896,26.048),(50.490896,26.048041),(50.485199,26.085639),(50.469981,26.122626),(50.452973,26.149563),(50.448904,26.161607),(50.449555,26.177965),(50.461192,26.225246),(50.468516,26.236884),(50.481456,26.24258),(50.481619,26.24254),(50.482595,26.24254),(50.503917,26.242011),(50.516368,26.239691),(50.5324,26.2331),(50.545421,26.227729),(50.545502,26.227769),(50.586681,26.242499),(50.593272,26.238593),(50.597423,26.225531),(50.604747,26.216498),(50.606944,26.212388),(50.609141,26.208319),(50.609141,26.208279),(50.603526,26.197659),(50.594086,26.195299),(50.565603,26.198879),(50.551606,26.194241)] +Bosnia and Herzegovina [(16.941529,45.241219),(16.947317,45.23569),(16.967987,45.237292),(16.9653,45.244216),(16.961166,45.250934),(16.975945,45.247162),(16.988141,45.236516),(16.998683,45.2314),(17.008295,45.244165),(17.012015,45.236465),(17.013566,45.230574),(17.012532,45.224476),(17.008295,45.216156),(17.014393,45.219773),(17.030206,45.226956),(17.036303,45.23047),(17.055734,45.200446),(17.098418,45.177657),(17.124628,45.169058),(17.187095,45.148563),(17.197844,45.152956),(17.24549,45.155384),(17.249727,45.15988),(17.268951,45.189543),(17.307811,45.171404),(17.326518,45.165926),(17.359384,45.150682),(17.368583,45.145101),(17.382432,45.139623),(17.400829,45.141018),(17.434109,45.148563),(17.436176,45.151922),(17.438759,45.158123),(17.443307,45.162051),(17.451162,45.158485),(17.45695,45.151819),(17.458086,45.146134),(17.454986,45.140605),(17.447751,45.1343),(17.46036,45.131252),(17.472349,45.13275),(17.496224,45.14169),(17.487025,45.120865),(17.481858,45.114405),(17.489299,45.116265),(17.539528,45.120968),(17.561439,45.119366),(17.572395,45.120399),(17.593065,45.129598),(17.629962,45.157348),(17.651563,45.165358),(17.684739,45.163963),(17.714505,45.152025),(17.741377,45.133267),(17.797497,45.081952),(17.815584,45.07017),(17.835738,45.064434),(17.84566,45.065261),(17.875219,45.073994),(17.902607,45.077766),(17.911185,45.081074),(17.927722,45.092029),(17.988493,45.143809),(18.003479,45.149338),(18.019086,45.149442),(18.035002,45.143344),(18.090296,45.107997),(18.112413,45.100607),(18.131844,45.097869),(18.143698,45.0977),(18.143704,45.0977),(18.153651,45.097558),(18.174942,45.100762),(18.192512,45.108514),(18.199333,45.119004),(18.200057,45.131613),(18.20233,45.144067),(18.213286,45.153782),(18.237884,45.157451),(18.261965,45.150682),(18.30744,45.127531),(18.322323,45.12288),(18.392913,45.118642),(18.412033,45.112441),(18.429293,45.102209),(18.45183,45.084959),(18.451842,45.08495),(18.466087,45.074046),(18.481708,45.066921),(18.490788,45.06278),(18.51704,45.055856),(18.541121,45.055287),(18.539261,45.069343),(18.534403,45.081539),(18.534803,45.088412),(18.53492,45.090427),(18.549596,45.094768),(18.557658,45.094406),(18.573781,45.091564),(18.581842,45.091357),(18.58856,45.093218),(18.602513,45.099264),(18.609127,45.100091),(18.616672,45.097662),(18.621116,45.093114),(18.627937,45.08004),(18.633622,45.071979),(18.640547,45.065364),(18.648711,45.062677),(18.658116,45.066294),(18.661217,45.0711),(18.663284,45.077146),(18.666075,45.082986),(18.671346,45.086861),(18.678167,45.087378),(18.684058,45.084794),(18.689019,45.080247),(18.726329,45.026142),(18.738318,45.01591),(18.750101,45.012241),(18.778006,45.010329),(18.78493,45.008468),(18.788961,45.005729),(18.791752,45.001544),(18.794646,44.995446),(18.795162,44.993327),(18.795162,44.988004),(18.795783,44.985059),(18.797953,44.982217),(18.803017,44.977307),(18.804568,44.973845),(18.80157,44.963975),(18.779866,44.952244),(18.772631,44.942478),(18.78338,44.913745),(18.817797,44.887545),(18.842129,44.876239),(18.842144,44.876233),(18.858724,44.868529),(18.889627,44.86119),(18.974916,44.862757),(19.004969,44.863309),(19.015821,44.865635),(19.047757,44.872714),(19.068427,44.874833),(19.08455,44.878967),(19.174261,44.925424),(19.18687,44.927543),(19.193174,44.921549),(19.196895,44.913177),(19.201856,44.908371),(19.211881,44.908371),(19.229554,44.913745),(19.239476,44.915141),(19.283815,44.908371),(19.293013,44.909405),(19.301281,44.91235),(19.31017,44.91235),(19.33022,44.898708),(19.340142,44.896227),(19.350271,44.897002),(19.352958,44.898087),(19.353165,44.899018),(19.356982,44.895877),(19.356993,44.895869),(19.362776,44.891111),(19.368667,44.887132),(19.372802,44.881448),(19.375695,44.873128),(19.376626,44.862999),(19.373112,44.86026),(19.367841,44.859278),(19.363707,44.854628),(19.32836,44.733963),(19.318025,44.715463),(19.308413,44.705128),(19.288259,44.693035),(19.277614,44.684871),(19.270069,44.67562),(19.255703,44.645648),(19.208677,44.588391),(19.20413,44.585135),(19.193278,44.580587),(19.188317,44.57604),(19.18625,44.569322),(19.187283,44.553302),(19.185319,44.546223),(19.179635,44.538264),(19.173124,44.531443),(19.165269,44.526689),(19.129922,44.518317),(19.127339,44.502556),(19.143358,44.458218),(19.141394,44.430829),(19.129612,44.416153),(19.115763,44.403596),(19.107185,44.382718),(19.108942,44.36365),(19.116693,44.343703),(19.138914,44.309338),(19.157001,44.293577),(19.177155,44.286962),(19.220046,44.280244),(19.240717,44.272699),(19.249502,44.270736),(19.263661,44.270167),(19.295907,44.2758),(19.307379,44.274198),(19.324329,44.263966),(19.341589,44.245828),(19.353991,44.22433),(19.356058,44.204021),(19.362363,44.191206),(19.381173,44.177098),(19.424891,44.153792),(19.435537,44.146092),(19.442565,44.143198),(19.448456,44.144438),(19.459721,44.152707),(19.465716,44.15281),(19.474191,44.144903),(19.476361,44.127023),(19.482666,44.120667),(19.498169,44.110229),(19.516189,44.091194),(19.522043,44.08501),(19.554599,44.071265),(19.570929,44.056898),(19.580231,44.051524),(19.583848,44.054315),(19.589946,44.060309),(19.598938,44.062583),(19.611443,44.054521),(19.618885,44.035711),(19.61041,44.019278),(19.593357,44.005584),(19.552222,43.983415),(19.528554,43.977213),(19.50406,43.975663),(19.447112,43.979797),(19.393989,43.977058),(19.379106,43.973854),(19.364637,43.973286),(19.351718,43.979125),(19.325879,43.996592),(19.300558,44.009511),(19.287329,44.013025),(19.272756,44.012405),(19.252085,44.007496),(19.243507,44.002018),(19.238029,43.99251),(19.238133,43.985378),(19.242887,43.972821),(19.240717,43.965741),(19.229348,43.95768),(19.241027,43.952357),(19.275443,43.933263),(19.305932,43.904737),(19.359469,43.842209),(19.461685,43.762136),(19.481735,43.729218),(19.505713,43.67364),(19.507367,43.647182),(19.481735,43.628914),(19.477498,43.616977),(19.475638,43.602559),(19.476878,43.588684),(19.481735,43.578116),(19.48897,43.573181),(19.491761,43.568608),(19.48959,43.564448),(19.481735,43.560831),(19.443908,43.571864),(19.431816,43.57114),(19.41931,43.549255),(19.410732,43.540754),(19.402877,43.549643),(19.394609,43.566463),(19.38045,43.585584),(19.363396,43.601577),(19.34655,43.608838),(19.335801,43.606513),(19.31265,43.593154),(19.300868,43.588297),(19.289189,43.587935),(19.263661,43.590958),(19.252706,43.588633),(19.238856,43.572122),(19.229451,43.549746),(19.217462,43.532796),(19.195345,43.532796),(19.147699,43.538145),(19.122791,43.535948),(19.096023,43.512901),(19.076386,43.507242),(19.054991,43.5067),(19.038145,43.511015),(19.025019,43.523029),(19.01427,43.537783),(19.000214,43.547886),(18.977477,43.546232),(18.962697,43.5383),(18.938926,43.518947),(18.920529,43.512203),(18.911021,43.507268),(18.90513,43.499051),(18.905647,43.490628),(18.915258,43.485383),(18.930658,43.482282),(18.937893,43.478949),(18.951225,43.463808),(18.950708,43.457297),(18.946368,43.44908),(18.946264,43.443938),(18.968278,43.448098),(18.975306,43.444274),(19.00993,43.410995),(19.039592,43.350714),(19.069668,43.30883),(19.062536,43.304386),(19.036285,43.303327),(19.024709,43.298728),(19.022535,43.296546),(19.017164,43.291157),(19.01086,43.28232),(19.002902,43.273949),(18.992463,43.267102),(18.989506,43.272016),(18.988949,43.272941),(18.968589,43.292216),(18.959493,43.303456),(18.957116,43.311828),(18.957943,43.318985),(18.957323,43.325858),(18.950295,43.333067),(18.923423,43.346838),(18.899135,43.351903),(18.839604,43.34782),(18.821207,43.341387),(18.824618,43.337408),(18.830302,43.328157),(18.833506,43.324153),(18.807151,43.318029),(18.679511,43.24948),(18.664318,43.233176),(18.688399,43.224469),(18.645301,43.180182),(18.629074,43.154886),(18.621128,43.124578),(18.620599,43.122563),(18.621116,43.09644),(18.638996,43.020243),(18.598379,43.024455),(18.538951,43.023887),(18.483037,43.014637),(18.452754,42.993398),(18.433531,42.954201),(18.434047,42.936889),(18.443969,42.916865),(18.467637,42.881699),(18.473322,42.862553),(18.465984,42.852812),(18.453478,42.845655),(18.443659,42.834467),(18.444589,42.817078),(18.453891,42.793151),(18.46743,42.769199),(18.502157,42.727445),(18.522518,42.71189),(18.539674,42.695457),(18.550009,42.668069),(18.549596,42.638923),(18.542832,42.626429),(18.538434,42.618304),(18.517247,42.602982),(18.506798,42.59849),(18.486654,42.58983),(18.493682,42.579831),(18.495852,42.570865),(18.492132,42.564767),(18.481797,42.563682),(18.470531,42.569056),(18.458956,42.569728),(18.44769,42.566214),(18.437355,42.559212),(18.421025,42.56363),(18.385265,42.566524),(18.370485,42.57363),(18.369791,42.574384),(18.369783,42.574393),(18.349608,42.59629),(18.338653,42.602517),(18.311574,42.601225),(18.257107,42.614893),(18.224138,42.628071),(18.049368,42.714758),(17.995315,42.740441),(17.971853,42.754962),(17.928859,42.7908),(17.904467,42.804546),(17.869431,42.811807),(17.858475,42.816974),(17.827159,42.853122),(17.825092,42.864542),(17.826229,42.888649),(17.823335,42.898365),(17.81176,42.909863),(17.802665,42.90963),(17.794707,42.904592),(17.786748,42.901388),(17.765458,42.904126),(17.7236,42.916245),(17.701586,42.9195),(17.679468,42.915676),(17.665929,42.90516),(17.653349,42.890928),(17.653331,42.890937),(17.652843,42.891181),(17.556488,42.93476),(17.573985,42.934272),(17.601085,42.925238),(17.617931,42.92178),(17.603038,42.932563),(17.580679,42.942075),(17.63451,42.950403),(17.662725,42.965699),(17.659314,42.993398),(17.659211,42.993449),(17.659108,42.99363),(17.659004,42.993656),(17.628412,43.046573),(17.598026,43.072902),(17.587381,43.082126),(17.450913,43.148152),(17.442067,43.152432),(17.42677,43.165713),(17.415195,43.184962),(17.406823,43.205426),(17.400209,43.216045),(17.389667,43.223099),(17.36941,43.232556),(17.328689,43.260358),(17.289931,43.30343),(17.267607,43.353324),(17.286417,43.437376),(17.270501,43.463214),(17.239495,43.478407),(17.142757,43.489336),(17.084569,43.513237),(17.062314,43.527747),(17.030516,43.54848),(16.98194,43.589692),(16.82381,43.707307),(16.712602,43.771515),(16.698236,43.788078),(16.689761,43.809317),(16.686144,43.826137),(16.678599,43.840684),(16.637361,43.868409),(16.604805,43.901068),(16.555816,43.937474),(16.527447,43.967859),(16.516542,43.979539),(16.501039,43.992716),(16.483469,44.002535),(16.439647,44.014007),(16.431482,44.025789),(16.426935,44.040517),(16.414016,44.055813),(16.403991,44.058759),(16.377946,44.057364),(16.367197,44.058139),(16.357378,44.062169),(16.346113,44.068474),(16.326889,44.082375),(16.312213,44.099997),(16.289992,44.139116),(16.275523,44.157357),(16.232115,44.190999),(16.215785,44.208155),(16.197078,44.25115),(16.18757,44.282414),(16.186639,44.297607),(16.189533,44.308511),(16.199662,44.324686),(16.203176,44.333057),(16.205863,44.349801),(16.205644,44.350531),(16.202866,44.359774),(16.192117,44.367422),(16.171343,44.377086),(16.153153,44.380445),(16.141991,44.380755),(16.13827,44.377602),(16.138787,44.385406),(16.145402,44.389591),(16.153877,44.39357),(16.159871,44.400702),(16.159664,44.416101),(16.152946,44.435067),(16.128348,44.484314),(16.123077,44.5039),(16.116463,44.52147),(16.104887,44.532373),(16.0837,44.534905),(16.04732,44.52333),(16.026649,44.52519),(16.006082,44.541003),(16.013937,44.557023),(16.030473,44.572216),(16.034917,44.585393),(16.043186,44.588442),(16.044736,44.589372),(16.041119,44.602808),(16.036158,44.615314),(16.028303,44.624719),(16.016004,44.628957),(15.991613,44.631437),(15.979107,44.634383),(15.968978,44.63924),(15.955646,44.653193),(15.948101,44.678101),(15.937352,44.688953),(15.929808,44.68947),(15.921539,44.686111),(15.913064,44.684509),(15.905416,44.690142),(15.902006,44.698823),(15.899318,44.70921),(15.895598,44.718564),(15.888776,44.724248),(15.876271,44.724816),(15.869243,44.718564),(15.863868,44.709985),(15.856427,44.703577),(15.847849,44.70151),(15.829969,44.700528),(15.820357,44.698255),(15.805681,44.696653),(15.796999,44.703267),(15.790488,44.713396),(15.78284,44.722594),(15.759275,44.73417),(15.753694,44.739286),(15.728476,44.769103),(15.717314,44.786466),(15.716074,44.80321),(15.730647,44.817007),(15.751214,44.821555),(15.76868,44.827342),(15.773435,44.845016),(15.76403,44.864033),(15.74801,44.882016),(15.734264,44.902118),(15.730853,44.927233),(15.734108,44.93444),(15.738811,44.944855),(15.763616,44.97555),(15.76744,44.993224),(15.755555,45.023558),(15.755968,45.042213),(15.779429,45.085363),(15.78377,45.100917),(15.780049,45.160294),(15.780979,45.167993),(15.792348,45.189801),(15.802569,45.196473),(15.824801,45.210988),(15.878855,45.217241),(15.974559,45.215381),(15.997504,45.218533),(16.008459,45.218171),(16.020448,45.213934),(16.029233,45.205045),(16.028716,45.19626),(16.024996,45.188922),(16.024375,45.184323),(16.033057,45.179724),(16.054968,45.176417),(16.067474,45.169595),(16.08277,45.151612),(16.104061,45.112545),(16.121527,45.096163),(16.212994,45.031464),(16.24121,45.018959),(16.279347,45.007176),(16.316244,45.001234),(16.340635,45.005936),(16.346019,45.02001),(16.346023,45.02002),(16.356965,45.048621),(16.377325,45.075596),(16.381976,45.083709),(16.384043,45.09544),(16.381976,45.101951),(16.38177,45.107584),(16.389211,45.116834),(16.398513,45.121433),(16.424764,45.127272),(16.435513,45.132853),(16.449156,45.148098),(16.481919,45.199516),(16.528944,45.222254),(16.587028,45.220858),(16.786293,45.178846),(16.811718,45.181223),(16.824223,45.189077),(16.825774,45.196364),(16.82505,45.205045),(16.830734,45.216983),(16.84076,45.224011),(16.851922,45.227421),(16.86174,45.232227),(16.867321,45.243389),(16.875383,45.246955),(16.885822,45.255223),(16.893986,45.263543),(16.896984,45.268142),(16.924372,45.284524),(16.93264,45.278788),(16.940702,45.257755),(16.942149,45.249849),(16.941529,45.241219)] +Bajo Nuevo Bank (Petrel Is.) [(-79.989288,15.794949),(-79.987823,15.79621),(-79.986399,15.79442),(-79.988149,15.794176),(-79.989288,15.794949)] +Saint Barthelemy [(-62.838857,17.881985),(-62.850942,17.890448),(-62.861318,17.905422),(-62.86734,17.920396),(-62.866119,17.929145),(-62.857411,17.925035),(-62.791656,17.915473),(-62.79894,17.904486),(-62.810129,17.892279),(-62.823842,17.883246),(-62.838857,17.881985)] +Belarus [(28.148907,56.142414),(28.169112,56.125257),(28.238462,56.082624),(28.269364,56.058207),(28.289828,56.046606),(28.310912,56.042679),(28.333443,56.050249),(28.366516,56.07911),(28.389771,56.088567),(28.537824,56.097714),(28.594719,56.092391),(28.611462,56.088464),(28.620713,56.082986),(28.637094,56.065726),(28.671924,56.037563),(28.680606,56.027382),(28.690011,56.003895),(28.695488,55.98015),(28.706392,55.959841),(28.73192,55.946793),(28.80897,55.934571),(28.830881,55.937672),(28.833051,55.960978),(28.859716,55.976455),(28.922141,55.992139),(28.922245,55.992191),(28.922296,55.992191),(28.922451,55.992242),(28.980846,56.013533),(29.030765,56.024178),(29.088643,56.023222),(29.145435,56.012034),(29.192926,55.992139),(29.224035,55.978186),(29.377411,55.954028),(29.395601,55.947723),(29.413067,55.937982),(29.431567,55.924184),(29.441076,55.914934),(29.444435,55.906925),(29.440559,55.900543),(29.433738,55.899535),(29.425573,55.9),(29.417408,55.89801),(29.407796,55.893876),(29.399631,55.891887),(29.391983,55.888373),(29.384128,55.879949),(29.380718,55.871242),(29.375654,55.846799),(29.371933,55.836386),(29.348162,55.802848),(29.343614,55.786984),(29.350745,55.766055),(29.363406,55.751482),(29.413067,55.727762),(29.461023,55.6873),(29.480867,55.681099),(29.5081,55.685491),(29.585356,55.73802),(29.684162,55.770602),(29.710827,55.773754),(29.779867,55.763807),(29.805705,55.771455),(29.844772,55.812563),(29.869474,55.830547),(29.907817,55.843208),(29.947712,55.848194),(29.988226,55.846799),(30.106255,55.821917),(30.132352,55.826878),(30.177258,55.851372),(30.200254,55.857987),(30.217773,55.855145),(30.251517,55.837626),(30.270793,55.83065),(30.468817,55.793521),(30.477395,55.787733),(30.477808,55.779129),(30.471814,55.770964),(30.469282,55.762644),(30.480702,55.753962),(30.569586,55.729519),(30.580128,55.724765),(30.587466,55.718306),(30.5916,55.705697),(30.588396,55.696601),(30.583745,55.68854),(30.583745,55.679135),(30.596354,55.665286),(30.616611,55.657431),(30.639142,55.654485),(30.679967,55.656346),(30.693713,55.65216),(30.703324,55.642341),(30.71304,55.626683),(30.742185,55.594385),(30.77071,55.591543),(30.804093,55.602344),(30.847657,55.611025),(30.886156,55.600483),(30.907122,55.57777),(30.912821,55.571596),(30.919745,55.534492),(30.899385,55.499146),(30.914371,55.493306),(30.919435,55.492325),(30.913234,55.479715),(30.887189,55.468088),(30.881298,55.451448),(30.889101,55.433413),(30.905276,55.420856),(30.918608,55.407627),(30.918298,55.387783),(30.905948,55.376001),(30.845641,55.351145),(30.811225,55.323084),(30.797169,55.304274),(30.794275,55.285515),(30.804093,55.272958),(30.821353,55.26438),(30.856803,55.253476),(30.869826,55.241539),(30.886517,55.204538),(30.900728,55.192136),(30.947237,55.171362),(30.959795,55.162577),(30.96119,55.158546),(30.956849,55.149503),(30.958813,55.144439),(30.962223,55.142888),(30.972455,55.140873),(30.975039,55.13953),(30.979483,55.134259),(30.984031,55.1309),(30.985478,55.125835),(30.98062,55.115345),(30.972662,55.108575),(30.970285,55.101444),(30.973075,55.093951),(30.98062,55.086303),(30.994211,55.067027),(31.006407,55.04243),(31.005632,55.022999),(30.98062,55.018658),(30.933491,55.025635),(30.913234,55.024601),(30.90662,55.012561),(30.916955,54.996024),(30.931424,54.985172),(30.936075,54.973235),(30.917368,54.953959),(30.899488,54.946363),(30.838613,54.93918),(30.814842,54.928018),(30.817426,54.917631),(30.827451,54.902541),(30.826108,54.877478),(30.810708,54.86151),(30.787867,54.847713),(30.768127,54.829936),(30.762649,54.801979),(30.770607,54.786011),(30.786058,54.779345),(30.827296,54.771025),(30.98062,54.705654),(30.995503,54.689841),(30.999017,54.671341),(31.020928,54.673666),(31.10516,54.668292),(31.128621,54.640387),(31.167947,54.621577),(31.139474,54.582871),(31.089554,54.535897),(31.064646,54.492282),(31.093585,54.479415),(31.167896,54.467064),(31.179017,54.453353),(31.179213,54.453111),(31.20903,54.448047),(31.22536,54.428048),(31.248717,54.376785),(31.26174,54.364486),(31.274142,54.356632),(31.284788,54.347381),(31.292022,54.331258),(31.299154,54.272606),(31.309799,54.244339),(31.324682,54.229249),(31.480641,54.156644),(31.506376,54.143931),(31.530871,54.13742),(31.583116,54.129514),(31.666935,54.101867),(31.697837,54.097939),(31.725794,54.097474),(31.73675,54.094167),(31.748119,54.086312),(31.755767,54.074943),(31.762588,54.060319),(31.77127,54.048537),(31.783517,54.045798),(31.808477,54.055978),(31.813851,54.057063),(31.822636,54.053446),(31.823876,54.050139),(31.823566,54.045488),(31.84651,53.992313),(31.841446,53.984561),(31.839689,53.977223),(31.839276,53.969782),(31.837932,53.962134),(31.82646,53.940171),(31.81013,53.882604),(31.79256,53.857437),(31.753803,53.81961),(31.744656,53.794857),(31.787289,53.794392),(31.873175,53.777132),(32.083602,53.809637),(32.10603,53.806949),(32.164837,53.78168),(32.290411,53.760854),(32.325809,53.745454),(32.357384,53.71972),(32.371801,53.714397),(32.421566,53.715792),(32.442133,53.713932),(32.461563,53.7068),(32.48058,53.692073),(32.487815,53.684683),(32.490192,53.677138),(32.487815,53.669645),(32.48058,53.66241),(32.406115,53.639414),(32.399087,53.635384),(32.398001,53.627425),(32.401102,53.609855),(32.411489,53.582364),(32.429421,53.56159),(32.452933,53.546397),(32.48058,53.535648),(32.53081,53.521437),(32.554271,53.510792),(32.569877,53.492602),(32.569877,53.492395),(32.576802,53.486039),(32.584295,53.48423),(32.592511,53.486452),(32.600573,53.492395),(32.618143,53.494255),(32.635713,53.492653),(32.650286,53.487641),(32.647599,53.479321),(32.641656,53.468985),(32.646772,53.457978),(32.658244,53.455653),(32.688526,53.462216),(32.701239,53.462113),(32.719532,53.439478),(32.717794,53.431062),(32.704443,53.366408),(32.717465,53.334937),(32.697931,53.325893),(32.681808,53.326798),(32.666719,53.331345),(32.649872,53.333671),(32.579954,53.324369),(32.583468,53.321217),(32.591891,53.311837),(32.595922,53.308272),(32.569154,53.298841),(32.537321,53.295068),(32.505643,53.297187),(32.48058,53.305171),(32.454845,53.300443),(32.447197,53.288764),(32.455982,53.277783),(32.479133,53.274915),(32.469211,53.255458),(32.455672,53.236674),(32.423633,53.204402),(32.405546,53.192672),(32.389113,53.187633),(32.352836,53.18045),(32.32028,53.162777),(32.295165,53.140866),(32.267983,53.124769),(32.215687,53.125518),(32.210519,53.121772),(32.209072,53.116346),(32.206695,53.112392),(32.206488,53.10986),(32.207005,53.105158),(32.20592,53.100352),(32.201114,53.097561),(32.197393,53.097742),(32.188608,53.099241),(32.152332,53.096347),(32.126545,53.084229),(32.117295,53.081102),(32.082775,53.081955),(32.009911,53.099964),(31.980559,53.098026),(31.954721,53.089991),(31.930743,53.088337),(31.907179,53.091928),(31.855502,53.110248),(31.842635,53.112186),(31.806823,53.110015),(31.796281,53.112392),(31.780468,53.127869),(31.769719,53.169262),(31.756283,53.186574),(31.738558,53.192542),(31.694478,53.192904),(31.674945,53.19523),(31.614018,53.209751),(31.593606,53.210681),(31.573659,53.207089),(31.535935,53.194868),(31.512061,53.194067),(31.464002,53.199984),(31.416356,53.199984),(31.378529,53.182026),(31.359925,53.133838),(31.361165,53.121306),(31.361573,53.120038),(31.364886,53.109731),(31.367057,53.098931),(31.363698,53.088776),(31.354137,53.08211),(31.329436,53.079345),(31.319204,53.076374),(31.269285,53.028418),(31.247064,53.014388),(31.322615,52.977129),(31.339151,52.958061),(31.36623,52.908555),(31.387934,52.887987),(31.418113,52.870237),(31.450979,52.857214),(31.480641,52.850935),(31.505136,52.848894),(31.512784,52.841039),(31.515161,52.828379),(31.523946,52.811661),(31.538364,52.799853),(31.55056,52.794737),(31.560843,52.787063),(31.569525,52.767504),(31.570248,52.725258),(31.547924,52.705699),(31.480641,52.682522),(31.480641,52.68247),(31.4917,52.667096),(31.536142,52.630484),(31.565907,52.59015),(31.579033,52.577825),(31.615207,52.558576),(31.628643,52.54806),(31.624302,52.53806),(31.610763,52.535993),(31.574382,52.541264),(31.559293,52.540541),(31.563634,52.537053),(31.575933,52.524728),(31.558156,52.519999),(31.55056,52.511886),(31.552988,52.502249),(31.565494,52.492637),(31.587922,52.482612),(31.589369,52.458039),(31.583322,52.4283),(31.582857,52.402772),(31.59035,52.391842),(31.600531,52.383393),(31.608075,52.372463),(31.608592,52.354428),(31.602753,52.340915),(31.592262,52.328616),(31.579602,52.318513),(31.567354,52.311382),(31.59712,52.284303),(31.613656,52.273012),(31.631433,52.26477),(31.648693,52.260997),(31.68342,52.257199),(31.699439,52.251463),(31.688897,52.243221),(31.681921,52.230456),(31.679492,52.215858),(31.682386,52.201931),(31.689517,52.19157),(31.698716,52.185446),(31.749049,52.163949),(31.762588,52.149841),(31.766619,52.130075),(31.764345,52.100568),(31.649933,52.096847),(31.474854,52.117776),(31.383076,52.117492),(31.304425,52.097493),(31.284271,52.081241),(31.268871,52.061242),(31.252438,52.044499),(31.228977,52.03822),(31.204896,52.04393),(31.159214,52.068115),(31.134823,52.076667),(31.096324,52.079613),(30.959329,52.074678),(30.934421,52.069717),(30.918815,52.059175),(30.924706,52.042277),(30.919745,52.037264),(30.916851,52.032355),(30.914629,52.027575),(30.91127,52.022562),(30.940519,52.020082),(30.950131,52.006775),(30.941243,51.993804),(30.915198,51.99259),(30.908377,51.998352),(30.902795,51.99998),(30.896904,51.998326),(30.888739,51.994347),(30.880885,51.988171),(30.879024,51.982022),(30.879644,51.97688),(30.879334,51.97365),(30.869102,51.96502),(30.858044,51.957631),(30.845641,51.951352),(30.831379,51.9459),(30.80306,51.939131),(30.802543,51.935539),(30.80523,51.929338),(30.810605,51.925178),(30.810605,51.918382),(30.797065,51.906729),(30.788177,51.900606),(30.779495,51.897919),(30.74973,51.899624),(30.741668,51.897919),(30.737844,51.891588),(30.737224,51.882235),(30.734537,51.873734),(30.71397,51.866964),(30.707562,51.860376),(30.702808,51.853761),(30.69733,51.850738),(30.694539,51.847276),(30.672732,51.829602),(30.666324,51.822393),(30.661983,51.819422),(30.662293,51.815598),(30.669631,51.806064),(30.670562,51.790535),(30.652785,51.77914),(30.630461,51.770019),(30.618162,51.761338),(30.638109,51.755111),(30.64617,51.754542),(30.64617,51.747075),(30.63506,51.739685),(30.632011,51.727981),(30.630564,51.715604),(30.624983,51.706096),(30.613821,51.702918),(30.582815,51.702297),(30.570309,51.69992),(30.575994,51.686407),(30.564315,51.665297),(30.570309,51.6515),(30.563488,51.647314),(30.555323,51.639769),(30.549949,51.637185),(30.552843,51.633335),(30.556615,51.62362),(30.543851,51.620132),(30.515119,51.603673),(30.515119,51.596257),(30.534549,51.585845),(30.543127,51.582589),(30.543127,51.576388),(30.535273,51.575018),(30.531087,51.573313),(30.527728,51.571298),(30.52256,51.568921),(30.52256,51.562719),(30.534136,51.553263),(30.567415,51.547268),(30.584004,51.542256),(30.576407,51.531119),(30.571446,51.526417),(30.562868,51.521766),(30.575064,51.516056),(30.585399,51.509389),(30.58974,51.501974),(30.584004,51.493835),(30.588913,51.48182),(30.597284,51.474275),(30.60762,51.469831),(30.618162,51.467144),(30.618162,51.459651),(30.604829,51.461227),(30.593564,51.458901),(30.586019,51.451848),(30.584004,51.439213),(30.587879,51.427353),(30.595579,51.42495),(30.606018,51.424562),(30.618162,51.418723),(30.622606,51.412108),(30.632424,51.383971),(30.637489,51.378596),(30.644517,51.372679),(30.64555,51.36746),(30.632424,51.364101),(30.638315,51.33586),(30.610462,51.317541),(30.579921,51.303665),(30.577234,51.289015),(30.559354,51.269326),(30.556615,51.267311),(30.555323,51.243462),(30.554657,51.242507),(30.550672,51.236796),(30.539613,51.235168),(30.532017,51.244625),(30.520803,51.252402),(30.508091,51.257673),(30.494655,51.259921),(30.480702,51.258862),(30.465044,51.261937),(30.442772,51.283047),(30.428096,51.291754),(30.413523,51.294054),(30.383757,51.293924),(30.368461,51.297671),(30.355129,51.305267),(30.324536,51.329969),(30.317095,51.340588),(30.319885,51.341596),(30.328257,51.362473),(30.330014,51.370354),(30.330117,51.380715),(30.329032,51.388622),(30.32619,51.395262),(30.320195,51.402083),(30.30738,51.409602),(30.256892,51.425053),(30.242784,51.434407),(30.20537,51.466498),(30.17731,51.479495),(30.14863,51.48443),(30.00869,51.482078),(29.985745,51.477867),(29.925077,51.457868),(29.912572,51.457429),(29.896552,51.464198),(29.886268,51.464793),(29.873608,51.459186),(29.856761,51.439859),(29.846633,51.432908),(29.828649,51.429963),(29.737905,51.439497),(29.725296,51.450452),(29.716511,51.465671),(29.699975,51.483706),(29.682715,51.491199),(29.660804,51.493137),(29.637756,51.490889),(29.618016,51.485644),(29.597345,51.473965),(29.583186,51.460813),(29.5682,51.449626),(29.545049,51.443657),(29.519004,51.441797),(29.505465,51.437456),(29.495543,51.425648),(29.480867,51.401256),(29.466294,51.385056),(29.446399,51.384901),(29.402732,51.39614),(29.379684,51.391541),(29.35326,51.377055),(29.340565,51.370096),(29.319946,51.365574),(29.297002,51.373713),(29.2846,51.391748),(29.276125,51.413581),(29.264859,51.432908),(29.244395,51.447894),(29.227756,51.45562),(29.221038,51.466963),(29.230443,51.492879),(29.226515,51.519053),(29.214836,51.53546),(29.181453,51.567009),(29.160421,51.603311),(29.147967,51.615636),(29.123886,51.625041),(29.083682,51.631217),(29.063218,51.630596),(29.043581,51.626178),(29.023634,51.614034),(28.999966,51.582408),(28.980846,51.569463),(28.954594,51.563262),(28.892892,51.562874),(28.863643,51.558921),(28.831914,51.548276),(28.799875,51.532618),(28.771866,51.511276),(28.752229,51.483706),(28.749439,51.46686),(28.751609,51.428748),(28.746751,51.413995),(28.728768,51.401256),(28.718226,51.411618),(28.711095,51.430247),(28.703963,51.442623),(28.691148,51.443424),(28.677918,51.438076),(28.663552,51.433993),(28.647016,51.439006),(28.637301,51.449626),(28.630893,51.46363),(28.615183,51.51957),(28.612703,51.53993),(28.603918,51.553547),(28.578079,51.56011),(28.488369,51.572021),(28.461239,51.571659),(28.435349,51.56613),(28.385533,51.545046),(28.359643,51.529362),(28.346879,51.525151),(28.333857,51.52838),(28.328172,51.536364),(28.317424,51.56396),(28.310912,51.57445),(28.29851,51.582977),(28.269726,51.594268),(28.257789,51.601761),(28.249366,51.613078),(28.248384,51.622096),(28.248901,51.630596),(28.245128,51.640622),(28.2304,51.651138),(28.21004,51.651965),(28.187612,51.645195),(28.166218,51.633103),(28.146685,51.614396),(28.114232,51.575613),(28.090151,51.562048),(28.070824,51.557629),(27.973155,51.55781),(27.954758,51.560782),(27.936051,51.567009),(27.87559,51.60804),(27.854196,51.615326),(27.831252,51.612923),(27.812545,51.602019),(27.799522,51.585199),(27.793218,51.565019),(27.793735,51.552307),(27.796267,51.541532),(27.797145,51.530603),(27.792546,51.517296),(27.787327,51.510914),(27.74056,51.471407),(27.730121,51.465154),(27.714256,51.463707),(27.700045,51.467531),(27.683767,51.475515),(27.670331,51.484817),(27.666182,51.490194),(27.66413,51.492853),(27.697306,51.543186),(27.705161,51.568352),(27.692655,51.589229),(27.676842,51.59481),(27.620619,51.595896),(27.512426,51.623099),(27.512305,51.623129),(27.477268,51.623672),(27.458768,51.617496),(27.430966,51.598428),(27.409004,51.59171),(27.388385,51.590728),(27.32906,51.596955),(27.289269,51.588971),(27.267462,51.587498),(27.254026,51.595379),(27.25971,51.612303),(27.27449,51.6338),(27.277487,51.651138),(27.247928,51.655659),(27.22364,51.653696),(27.20359,51.655143),(27.189017,51.663773),(27.181059,51.68341),(27.181472,51.710126),(27.184159,51.731443),(27.177855,51.747075),(27.151086,51.756764),(27.109952,51.762423),(27.021585,51.764542),(26.920816,51.742528),(26.854774,51.749349),(26.665741,51.801387),(26.4456,51.805599),(26.431544,51.810224),(26.419245,51.820921),(26.416971,51.830636),(26.419968,51.839731),(26.419762,51.846862),(26.407773,51.850609),(26.175332,51.856707),(26.14536,51.864846),(26.080764,51.900657),(26.050585,51.904817),(25.981132,51.903474),(25.767915,51.928511),(25.683476,51.918021),(25.547396,51.919442),(25.351971,51.921483),(25.1833,51.94975),(25.138031,51.948949),(25.092659,51.939751),(25.002742,51.910476),(24.721829,51.882338),(24.701055,51.882907),(24.639767,51.892131),(24.39079,51.880013),(24.369602,51.875103),(24.347898,51.861151),(24.311518,51.827561),(24.296119,51.808131),(24.272347,51.742889),(24.244132,51.718214),(24.130754,51.669793),(23.981306,51.586),(23.941308,51.581917),(23.912886,51.598583),(23.884878,51.619874),(23.845293,51.629821),(23.820282,51.631268),(23.749692,51.644472),(23.726231,51.644859),(23.628976,51.629046),(23.616677,51.624783),(23.606445,51.618117),(23.594353,51.604965),(23.593319,51.596955),(23.599107,51.588971),(23.626289,51.540886),(23.628666,51.531223),(23.624118,51.515901),(23.615437,51.51311),(23.606238,51.517399),(23.602311,51.530783),(23.588668,51.535899),(23.572752,51.539672),(23.56035,51.555304),(23.567171,51.55489),(23.573992,51.555304),(23.552081,51.578817),(23.5434,51.592743),(23.539886,51.607109),(23.545157,51.63411),(23.543813,51.6438),(23.532444,51.6515),(23.532444,51.658967),(23.541436,51.659742),(23.547534,51.662067),(23.56035,51.671963),(23.555389,51.676304),(23.549291,51.683203),(23.546087,51.689637),(23.550014,51.692427),(23.559213,51.695166),(23.556939,51.701393),(23.550221,51.708421),(23.546604,51.713589),(23.552288,51.736636),(23.556319,51.747359),(23.56035,51.754542),(23.577299,51.766686),(23.59828,51.77467),(23.617504,51.786504),(23.628666,51.809759),(23.610269,51.825184),(23.594559,51.843297),(23.605721,51.851591),(23.609856,51.873269),(23.621845,51.877429),(23.621328,51.882028),(23.620604,51.883217),(23.618847,51.883268),(23.61492,51.88425),(23.621431,51.895567),(23.622155,51.927943),(23.628666,51.946339),(23.647579,51.97409),(23.660705,51.98688),(23.676415,51.994088),(23.664943,52.011168),(23.650783,52.048943),(23.642515,52.061397),(23.641482,52.072921),(23.637451,52.084471),(23.625255,52.089716),(23.61585,52.0923),(23.609856,52.09863),(23.604791,52.106769),(23.598177,52.11452),(23.579366,52.121548),(23.531928,52.120644),(23.512497,52.124442),(23.484695,52.158626),(23.488726,52.16214),(23.491517,52.174103),(23.487693,52.181622),(23.470949,52.171623),(23.464335,52.176351),(23.454413,52.181467),(23.450485,52.185911),(23.43674,52.175679),(23.427231,52.17679),(23.418239,52.182501),(23.405734,52.185911),(23.391368,52.182501),(23.388474,52.184154),(23.395812,52.193379),(23.395812,52.19958),(23.374831,52.200949),(23.312716,52.215289),(23.29959,52.223428),(23.284191,52.219734),(23.212257,52.231671),(23.189726,52.240533),(23.197684,52.25831),(23.19448,52.271462),(23.183525,52.281306),(23.176099,52.285136),(23.168746,52.288928),(23.165645,52.289393),(23.21205,52.347504),(23.230447,52.365074),(23.270548,52.395123),(23.392298,52.509638),(23.480458,52.554416),(23.569031,52.585887),(23.736153,52.614903),(23.868961,52.670042),(23.908752,52.699859),(23.922498,52.742596),(23.920426,52.772625),(23.912059,52.893853),(23.909476,52.901501),(23.905445,52.906539),(23.902034,52.912534),(23.901104,52.923257),(23.903894,52.931137),(23.914953,52.944625),(23.91795,52.9508),(23.917537,52.95881),(23.909062,52.986664),(23.908959,52.993046),(23.911336,53.00506),(23.909682,53.012734),(23.89821,53.02754),(23.867928,53.051027),(23.859349,53.067976),(23.860693,53.087484),(23.870305,53.101256),(23.882397,53.113297),(23.891389,53.127714),(23.893663,53.151951),(23.883121,53.163991),(23.865964,53.172001),(23.848084,53.183809),(23.836198,53.199286),(23.828447,53.213833),(23.818628,53.227967),(23.800645,53.242462),(23.782972,53.270936),(23.742974,53.365478),(23.722924,53.397104),(23.675795,53.455705),(23.590942,53.611251),(23.567068,53.681014),(23.564794,53.742405),(23.56469,53.742405),(23.56469,53.742457),(23.540402,53.763593),(23.52986,53.78416),(23.520662,53.837335),(23.51043,53.862502),(23.497201,53.885549),(23.486866,53.909992),(23.485625,53.939293),(23.520145,53.93397),(23.609959,53.901827),(23.627116,53.89821),(23.642618,53.898985),(23.691918,53.911491),(23.754446,53.916762),(23.77181,53.924307),(23.787209,53.927924),(23.794134,53.927097),(23.812117,53.920844),(23.820592,53.919294),(23.828344,53.920069),(23.904721,53.946062),(23.919811,53.947768),(23.935417,53.943944),(23.964873,53.93273),(23.981306,53.930404),(24.045385,53.930869),(24.074943,53.935727),(24.136748,53.955416),(24.169615,53.95893),(24.201137,53.95247),(24.229146,53.932368),(24.246406,53.903636),(24.257051,53.894024),(24.276378,53.891802),(24.310175,53.892681),(24.341904,53.887048),(24.377871,53.886841),(24.414044,53.897693),(24.528663,53.958361),(24.579099,53.975621),(24.642971,53.983011),(24.666845,53.993863),(24.670566,53.994276),(24.674287,53.993708),(24.677904,53.992313),(24.690823,53.972831),(24.705603,53.964201),(24.723896,53.963426),(24.788698,53.969678),(24.806372,53.975311),(24.819084,53.992313),(24.819187,53.992416),(24.819291,53.992519),(24.819394,53.992571),(24.821358,54.019908),(24.81247,54.038925),(24.799034,54.05603),(24.787148,54.077631),(24.782497,54.092875),(24.784254,54.096234),(24.790559,54.096596),(24.799447,54.10321),(24.818154,54.110135),(24.818671,54.113959),(24.81743,54.120625),(24.817534,54.128222),(24.821565,54.134526),(24.850984,54.144951),(24.855981,54.146722),(24.902283,54.149771),(24.948275,54.145895),(25.027133,54.12786),(25.071989,54.132201),(25.115603,54.148789),(25.156531,54.175712),(25.173068,54.19659),(25.193532,54.243667),(25.206244,54.256793),(25.224124,54.25855),(25.287583,54.245217),(25.369748,54.247904),(25.394036,54.257154),(25.434137,54.291829),(25.459355,54.298909),(25.472068,54.297152),(25.478682,54.293328),(25.483488,54.287695),(25.553975,54.231265),(25.5455,54.227492),(25.522142,54.228629),(25.501678,54.221756),(25.499301,54.211834),(25.523382,54.204238),(25.528963,54.195659),(25.521729,54.188218),(25.493203,54.18243),(25.485762,54.175402),(25.493307,54.157522),(25.516044,54.144758),(25.543019,54.136955),(25.631593,54.128325),(25.653503,54.128739),(25.663942,54.132356),(25.679755,54.145327),(25.690607,54.148221),(25.728124,54.145223),(25.74001,54.146257),(25.763057,54.156437),(25.771016,54.172147),(25.771946,54.21788),(25.775046,54.22248),(25.786829,54.231781),(25.789206,54.236225),(25.786622,54.242323),(25.781764,54.244442),(25.776287,54.245631),(25.772256,54.248938),(25.765641,54.259997),(25.757786,54.268988),(25.748898,54.276326),(25.739286,54.282579),(25.734739,54.283199),(25.723267,54.280977),(25.719236,54.281546),(25.715412,54.285215),(25.704766,54.302991),(25.701769,54.312758),(25.695981,54.320975),(25.682339,54.325626),(25.667353,54.3233),(25.607408,54.304852),(25.564,54.303146),(25.542296,54.308056),(25.528653,54.320975),(25.529997,54.346141),(25.548807,54.367742),(25.594696,54.400091),(25.612576,54.421796),(25.616296,54.441071),(25.615573,54.461896),(25.619914,54.488096),(25.630869,54.508354),(25.646165,54.520394),(25.70735,54.54153),(25.726471,54.55295),(25.740423,54.568505),(25.745591,54.5884),(25.739906,54.607727),(25.715102,54.643229),(25.708384,54.663021),(25.709521,54.67563),(25.713862,54.685552),(25.719133,54.69475),(25.72306,54.705344),(25.72461,54.715679),(25.7212,54.766736),(25.7243,54.78012),(25.734946,54.78906),(25.756753,54.800377),(25.766571,54.803271),(25.773393,54.803374),(25.778457,54.805286),(25.782901,54.81371),(25.782281,54.821978),(25.773703,54.841925),(25.772256,54.850865),(25.782695,54.869675),(25.802538,54.881612),(25.825793,54.891999),(25.84667,54.90621),(25.853078,54.916442),(25.854835,54.925486),(25.858452,54.932979),(25.870234,54.938818),(25.907855,54.948068),(25.926148,54.947758),(25.962529,54.942901),(25.981132,54.942694),(26.102572,54.957008),(26.138642,54.968946),(26.153628,54.978506),(26.170325,54.99326),(26.187838,55.008736),(26.224631,55.054884),(26.229386,55.06341),(26.231246,55.075451),(26.230316,55.100255),(26.233003,55.111624),(26.264422,55.140098),(26.309484,55.144645),(26.420278,55.128109),(26.428753,55.128212),(26.438572,55.130021),(26.444773,55.133948),(26.450664,55.13984),(26.459139,55.144749),(26.473402,55.145679),(26.578925,55.118549),(26.600939,55.120823),(26.616339,55.135395),(26.627501,55.164438),(26.633909,55.192188),(26.641143,55.202833),(26.656956,55.215339),(26.685689,55.231617),(26.701088,55.236836),(26.739901,55.242776),(26.76558,55.246706),(26.789661,55.257197),(26.80072,55.27332),(26.791574,55.290166),(26.768629,55.300243),(26.602696,55.316883),(26.542338,55.307581),(26.525388,55.308098),(26.465754,55.320862),(26.450044,55.327063),(26.445496,55.337502),(26.455212,55.356105),(26.479086,55.381375),(26.486011,55.390832),(26.49924,55.428091),(26.507818,55.439149),(26.543268,55.459613),(26.546472,55.471241),(26.527662,55.492169),(26.532106,55.516251),(26.55164,55.534492),(26.576134,55.550564),(26.595565,55.56803),(26.605177,55.590096),(26.607657,55.616451),(26.603833,55.643271),(26.594531,55.666991),(26.615615,55.687971),(26.64011,55.695568),(26.666878,55.693966),(26.720105,55.681874),(26.743049,55.682856),(26.822838,55.70611),(26.842785,55.719339),(26.900146,55.778715),(26.957817,55.818584),(26.979426,55.826291),(26.981071,55.826878),(27.110779,55.836283),(27.151448,55.832459),(27.173204,55.825741),(27.235526,55.795846),(27.263018,55.787216),(27.282448,55.791867),(27.329163,55.817576),(27.349627,55.831219),(27.374587,55.814837),(27.405851,55.804347),(27.438821,55.79874),(27.564601,55.792229),(27.592713,55.794244),(27.601498,55.809618),(27.610128,55.83096),(27.617156,55.878554),(27.64501,55.922841),(27.744435,55.959738),(27.776991,55.992397),(27.781229,56.016375),(27.812545,56.034514),(27.880654,56.063866),(27.892747,56.077095),(27.901532,56.089342),(27.911453,56.100246),(27.92706,56.109367),(27.939669,56.113062),(27.98101,56.118023),(28.023798,56.12965),(28.0511,56.140666),(28.06824,56.147582),(28.110976,56.156806),(28.148907,56.142414)] +Bolivia [(-65.29247,-11.504723),(-65.257562,-11.495318),(-65.233042,-11.50834),(-65.222655,-11.517435),(-65.215989,-11.530148),(-65.215989,-11.539966),(-65.223611,-11.55795),(-65.223404,-11.571076),(-65.219244,-11.584511),(-65.214542,-11.587509),(-65.207359,-11.587612),(-65.195447,-11.59216),(-65.173976,-11.606526),(-65.167439,-11.615517),(-65.190926,-11.623165),(-65.193354,-11.632364),(-65.189272,-11.657065),(-65.191339,-11.666884),(-65.200253,-11.681973),(-65.20232,-11.691482),(-65.201855,-11.727965),(-65.196197,-11.741814),(-65.182451,-11.756697),(-65.164467,-11.769823),(-65.151497,-11.77313),(-65.143538,-11.763829),(-65.138009,-11.715253),(-65.133978,-11.702644),(-65.127855,-11.694582),(-65.113411,-11.690551),(-65.110465,-11.699957),(-65.113566,-11.722591),(-65.0992,-11.736233),(-65.081062,-11.743468),(-65.065559,-11.75308),(-65.056309,-11.785636),(-65.043312,-11.80765),(-65.038454,-11.818709),(-65.037447,-11.828424),(-65.039204,-11.848681),(-65.038454,-11.8585),(-65.033674,-11.879791),(-65.028093,-11.888886),(-65.017939,-11.89364),(-65.014528,-11.893847),(-65.00458,-11.898394),(-64.998121,-11.908936),(-64.996493,-11.921235),(-65.00086,-11.931054),(-65.014632,-11.950277),(-65.016337,-11.968467),(-65.009438,-11.98428),(-64.997449,-11.996269),(-64.983445,-12.003917),(-64.967606,-12.007948),(-64.925154,-12.009912),(-64.904483,-12.014046),(-64.883503,-12.021384),(-64.862083,-12.024795),(-64.839836,-12.016733),(-64.827615,-12.022314),(-64.809295,-12.025828),(-64.7925,-12.032546),(-64.785188,-12.047429),(-64.780486,-12.067686),(-64.768574,-12.086496),(-64.736793,-12.119776),(-64.744183,-12.133625),(-64.739532,-12.144581),(-64.728396,-12.149852),(-64.716278,-12.146544),(-64.713642,-12.138483),(-64.710283,-12.111921),(-64.706382,-12.106133),(-64.689923,-12.104376),(-64.68646,-12.109957),(-64.681577,-12.126597),(-64.681577,-12.134865),(-64.688579,-12.147164),(-64.688992,-12.153882),(-64.685944,-12.159153),(-64.677184,-12.167628),(-64.67535,-12.171039),(-64.66486,-12.180961),(-64.640572,-12.19512),(-64.593417,-12.215997),(-64.58104,-12.217444),(-64.554892,-12.217754),(-64.548433,-12.219098),(-64.532103,-12.232224),(-64.511484,-12.242662),(-64.510347,-12.239562),(-64.510244,-12.237288),(-64.508848,-12.236048),(-64.49425,-12.238012),(-64.489392,-12.239459),(-64.473037,-12.253204),(-64.469058,-12.261059),(-64.468153,-12.272635),(-64.469316,-12.294856),(-64.474432,-12.316456),(-64.492441,-12.356557),(-64.48978,-12.373611),(-64.48363,-12.377641),(-64.461642,-12.385289),(-64.452521,-12.390354),(-64.444072,-12.399759),(-64.432367,-12.420946),(-64.424874,-12.431385),(-64.411335,-12.445131),(-64.395729,-12.457326),(-64.376763,-12.465905),(-64.353199,-12.469212),(-64.312659,-12.461874),(-64.297699,-12.465698),(-64.287544,-12.497117),(-64.278242,-12.499288),(-64.268708,-12.497221),(-64.26385,-12.495257),(-64.256822,-12.490813),(-64.245712,-12.479444),(-64.236565,-12.475413),(-64.215223,-12.473759),(-64.19755,-12.47872),(-64.183106,-12.487919),(-64.155252,-12.516961),(-64.144788,-12.520372),(-64.134763,-12.510863),(-64.119828,-12.489676),(-64.104455,-12.507142),(-64.044458,-12.509106),(-64.022832,-12.537838),(-64.004176,-12.535461),(-63.972447,-12.523886),(-63.959321,-12.52802),(-63.950019,-12.536805),(-63.939064,-12.544143),(-63.921236,-12.544349),(-63.909143,-12.534324),(-63.902477,-12.525436),(-63.896896,-12.515721),(-63.863203,-12.474793),(-63.862893,-12.469212),(-63.845581,-12.466938),(-63.814989,-12.457223),(-63.801398,-12.454949),(-63.657738,-12.475413),(-63.654844,-12.478307),(-63.600428,-12.506109),(-63.558726,-12.539905),(-63.542189,-12.547967),(-63.520227,-12.551171),(-63.507514,-12.551584),(-63.496145,-12.553341),(-63.485758,-12.557475),(-63.476198,-12.564813),(-63.468757,-12.575769),(-63.467,-12.585794),(-63.46638,-12.595302),(-63.462504,-12.605121),(-63.454236,-12.612046),(-63.445347,-12.614836),(-63.438164,-12.619177),(-63.435219,-12.630339),(-63.431446,-12.636954),(-63.393309,-12.664549),(-63.371088,-12.669923),(-63.359461,-12.674677),(-63.330419,-12.697002),(-63.317913,-12.701963),(-63.247323,-12.701342),(-63.235955,-12.698552),(-63.232027,-12.691111),(-63.222674,-12.682532),(-63.201848,-12.667856),(-63.197301,-12.666823),(-63.18557,-12.668476),(-63.180712,-12.667856),(-63.176113,-12.663619),(-63.171669,-12.652353),(-63.16707,-12.647392),(-63.139475,-12.63561),(-63.136684,-12.63375),(-63.125057,-12.63592),(-63.105213,-12.645222),(-63.075034,-12.652663),(-63.064751,-12.666202),(-63.057826,-12.701963),(-63.053588,-12.70837),(-63.047077,-12.713538),(-63.04346,-12.719119),(-63.051108,-12.730798),(-63.052193,-12.736482),(-63.051108,-12.742167),(-63.047904,-12.746714),(-63.025683,-12.765731),(-63.014728,-12.77772),(-63.010025,-12.787952),(-63.00708,-12.809966),(-62.999173,-12.829087),(-62.988011,-12.843866),(-62.975299,-12.852858),(-62.964498,-12.856578),(-62.955145,-12.857509),(-62.946515,-12.855235),(-62.93804,-12.849447),(-62.928893,-12.846036),(-62.923777,-12.852858),(-62.92047,-12.862263),(-62.867915,-12.929029),(-62.865073,-12.93554),(-62.860112,-12.940294),(-62.849001,-12.942155),(-62.838925,-12.942775),(-62.831431,-12.944945),(-62.826677,-12.950009),(-62.825075,-12.958691),(-62.820166,-12.974918),(-62.807402,-12.98887),(-62.789832,-13.000652),(-62.770453,-13.010471),(-62.768645,-12.990627),(-62.757896,-12.985149),(-62.741308,-12.985356),(-62.722032,-12.982566),(-62.709165,-12.974607),(-62.698985,-12.966649),(-62.686634,-12.964996),(-62.667462,-12.976364),(-62.657902,-12.984633),(-62.651339,-12.992487),(-62.647515,-13.001583),(-62.64519,-13.025354),(-62.641676,-13.030005),(-62.554601,-13.066798),(-62.492692,-13.065041),(-62.472125,-13.068452),(-62.458483,-13.07796),(-62.430939,-13.109793),(-62.428717,-13.114547),(-62.427477,-13.124572),(-62.424118,-13.126536),(-62.410269,-13.125709),(-62.406703,-13.126536),(-62.389701,-13.137078),(-62.381846,-13.139869),(-62.335028,-13.14514),(-62.321592,-13.143693),(-62.310533,-13.133978),(-62.290328,-13.142039),(-62.273636,-13.138422),(-62.259167,-13.130774),(-62.22165,-13.121265),(-62.211521,-13.120335),(-62.200927,-13.122712),(-62.173952,-13.140799),(-62.172454,-13.117855),(-62.162377,-13.120748),(-62.139846,-13.147),(-62.129149,-13.150927),(-62.120467,-13.148757),(-62.114679,-13.150204),(-62.112509,-13.164777),(-62.112457,-13.231801),(-62.109408,-13.248958),(-62.099228,-13.2626),(-62.077731,-13.277896),(-62.033599,-13.325542),(-62.019698,-13.33257),(-62.018665,-13.336808),(-62.003265,-13.360475),(-61.997787,-13.364093),(-61.97536,-13.374118),(-61.958358,-13.385487),(-61.909834,-13.431892),(-61.899499,-13.43923),(-61.879913,-13.449152),(-61.872317,-13.456077),(-61.868596,-13.463932),(-61.847977,-13.530801),(-61.83635,-13.540619),(-61.813974,-13.544237),(-61.794285,-13.540309),(-61.774235,-13.533385),(-61.75434,-13.530284),(-61.735116,-13.538036),(-61.715737,-13.526563),(-61.692896,-13.517985),(-61.668092,-13.512507),(-61.597114,-13.5061),(-61.59306,-13.506794),(-61.588071,-13.50765),(-61.560863,-13.532661),(-61.550812,-13.538036),(-61.503425,-13.548164),(-61.45875,-13.54372),(-61.415471,-13.528114),(-61.347724,-13.493697),(-61.332376,-13.494834),(-61.317131,-13.500932),(-61.281216,-13.507236),(-61.260029,-13.520052),(-61.248556,-13.524393),(-61.237885,-13.524393),(-61.215044,-13.517468),(-61.149105,-13.519845),(-61.139312,-13.514058),(-61.133576,-13.494007),(-61.118719,-13.484499),(-61.076009,-13.478298),(-61.072185,-13.47437),(-61.060118,-13.467136),(-61.047225,-13.464552),(-61.041256,-13.474577),(-61.041256,-13.515195),(-61.022007,-13.535245),(-60.977875,-13.542997),(-60.929299,-13.5462),(-60.896743,-13.552918),(-60.878243,-13.570385),(-60.870673,-13.575449),(-60.801969,-13.604181),(-60.725572,-13.662845),(-60.652701,-13.7188),(-60.618078,-13.736886),(-60.595082,-13.741641),(-60.588623,-13.744535),(-60.584876,-13.749082),(-60.579579,-13.761071),(-60.575135,-13.765619),(-60.566066,-13.769959),(-60.490618,-13.787736),(-60.472635,-13.797865),(-60.465271,-13.816572),(-60.463126,-13.843443),(-60.457313,-13.870935),(-60.448812,-13.896773),(-60.438554,-13.918374),(-60.430441,-13.926746),(-60.408634,-13.944522),(-60.406722,-13.950414),(-60.411605,-13.960542),(-60.40543,-13.966743),(-60.39574,-13.970981),(-60.389694,-13.974908),(-60.387188,-13.98328),(-60.387963,-13.989378),(-60.396515,-14.008394),(-60.409409,-14.055317),(-60.419434,-14.076917),(-60.437236,-14.092007),(-60.461395,-14.098622),(-60.468268,-14.103686),(-60.473513,-14.117225),(-60.477647,-14.139963),(-60.478939,-14.1627),(-60.475684,-14.176033),(-60.462403,-14.19846),(-60.462015,-14.223885),(-60.465633,-14.251067),(-60.464341,-14.278352),(-60.454316,-14.296646),(-60.399926,-14.340777),(-60.391348,-14.357107),(-60.376698,-14.419946),(-60.343806,-14.490949),(-60.338431,-14.5326),(-60.369204,-14.542832),(-60.35272,-14.575388),(-60.30404,-14.608151),(-60.291716,-14.630062),(-60.288822,-14.69073),(-60.284869,-14.772689),(-60.280889,-14.854648),(-60.276859,-14.936607),(-60.272905,-15.018565),(-60.269805,-15.083368),(-60.274972,-15.09515),(-60.389307,-15.096493),(-60.582241,-15.098871),(-60.529479,-15.143726),(-60.460181,-15.224238),(-60.352125,-15.349605),(-60.260451,-15.456058),(-60.246395,-15.478279),(-60.237972,-15.50267),(-60.224821,-15.651395),(-60.206992,-15.853036),(-60.193763,-16.001451),(-60.186968,-16.108731),(-60.17981,-16.222006),(-60.16069,-16.264794),(-60.129839,-16.273062),(-60.060412,-16.27544),(-59.87001,-16.282157),(-59.679557,-16.288772),(-59.489103,-16.295387),(-59.298675,-16.302105),(-59.108248,-16.308719),(-58.917769,-16.315437),(-58.727444,-16.322155),(-58.536965,-16.32877),(-58.464721,-16.33125),(-58.442242,-16.32846),(-58.421623,-16.318434),(-58.414233,-16.308926),(-58.400332,-16.284225),(-58.392943,-16.279367),(-58.349741,-16.2804),(-58.339561,-16.289289),(-58.334548,-16.386647),(-58.338837,-16.400497),(-58.362299,-16.419307),(-58.36359,-16.43667),(-58.342661,-16.473154),(-58.356097,-16.509534),(-58.455885,-16.619088),(-58.472679,-16.649577),(-58.480276,-16.683683),(-58.476658,-16.726988),(-58.456246,-16.802436),(-58.452939,-16.841296),(-58.455109,-16.848324),(-58.464049,-16.866101),(-58.466633,-16.875506),(-58.466272,-16.887289),(-58.45635,-16.937001),(-58.439193,-16.967284),(-58.432475,-16.98537),(-58.426791,-17.055237),(-58.421623,-17.070636),(-58.410978,-17.088206),(-58.406275,-17.110117),(-58.404828,-17.199621),(-58.399144,-17.237448),(-58.38116,-17.267214),(-58.343695,-17.286954),(-58.312172,-17.290881),(-58.302147,-17.293775),(-58.292277,-17.299666),(-58.274397,-17.314032),(-58.264527,-17.320027),(-58.256155,-17.322507),(-58.239929,-17.325195),(-58.231557,-17.329742),(-58.22024,-17.344315),(-58.204065,-17.377388),(-58.188407,-17.38855),(-58.174558,-17.392064),(-58.163189,-17.393407),(-58.152234,-17.396405),(-58.139366,-17.40457),(-58.11203,-17.433508),(-58.101126,-17.44126),(-58.065727,-17.455936),(-58.053687,-17.462344),(-58.010175,-17.49676),(-57.981495,-17.508749),(-57.943564,-17.517844),(-57.905686,-17.520325),(-57.877005,-17.512263),(-57.854113,-17.508543),(-57.836749,-17.511023),(-57.814425,-17.519705),(-57.800731,-17.533451),(-57.790757,-17.555775),(-57.788277,-17.58058),(-57.789569,-17.604144),(-57.787553,-17.620474),(-57.787967,-17.658921),(-57.7859,-17.677525),(-57.777941,-17.695508),(-57.767554,-17.708737),(-57.754894,-17.720623),(-57.740373,-17.730234),(-57.724456,-17.736642),(-57.732983,-17.768475),(-57.729314,-17.779327),(-57.711331,-17.800824),(-57.696809,-17.825112),(-57.698773,-17.843096),(-57.730089,-17.846093),(-57.636916,-18.001122),(-57.585498,-18.122769),(-57.551082,-18.183643),(-57.511188,-18.205554),(-57.490724,-18.205554),(-57.474549,-18.208035),(-57.465661,-18.21775),(-57.466798,-18.239557),(-57.535734,-18.240488),(-57.553872,-18.244518),(-57.56674,-18.256094),(-57.583018,-18.305703),(-57.630043,-18.448434),(-57.677017,-18.59106),(-57.723991,-18.733687),(-57.771068,-18.876314),(-57.782334,-18.910421),(-57.742233,-18.913625),(-57.731794,-18.921996),(-57.727557,-18.941943),(-57.721769,-19.001165),(-57.715826,-19.044573),(-57.771895,-19.048707),(-57.789,-19.059249),(-57.812048,-19.105034),(-57.843105,-19.166839),(-57.911628,-19.302852),(-57.980048,-19.438864),(-58.011209,-19.500669),(-58.011209,-19.500772),(-58.011209,-19.500876),(-58.011261,-19.500876),(-58.02356,-19.52568),(-58.050483,-19.580147),(-58.077458,-19.634718),(-58.089757,-19.659419),(-58.124639,-19.729906),(-58.116939,-19.758018),(-58.04113,-19.82344),(-57.960463,-19.8931),(-57.859745,-19.980123),(-57.86977,-19.992939),(-57.881139,-20.009165),(-57.895609,-20.024151),(-57.917933,-20.034177),(-57.943203,-20.028079),(-57.959171,-20.026218),(-57.966354,-20.031076),(-57.968938,-20.039758),(-57.975811,-20.047509),(-57.985681,-20.05309),(-57.997101,-20.055261),(-58.022371,-20.064976),(-58.053532,-20.10766),(-58.079577,-20.117376),(-58.086243,-20.12089),(-58.098284,-20.13815),(-58.103555,-20.144041),(-58.116319,-20.150449),(-58.158797,-20.165125),(-58.15952,-20.13908),(-58.144741,-20.086163),(-58.143139,-20.065286),(-58.144482,-20.023118),(-58.141847,-20.000897),(-58.145154,-19.969581),(-58.162207,-19.912324),(-58.164223,-19.880284),(-58.161174,-19.847211),(-58.164429,-19.832949),(-58.175282,-19.821373),(-58.214452,-19.798325),(-58.30778,-19.743652),(-58.401004,-19.688875),(-58.49428,-19.634201),(-58.587504,-19.579424),(-58.680832,-19.52475),(-58.774108,-19.470077),(-58.867436,-19.4153),(-58.96066,-19.360523),(-59.011096,-19.330964),(-59.039673,-19.311637),(-59.069646,-19.291483),(-59.089541,-19.286729),(-59.170725,-19.287762),(-59.359085,-19.290139),(-59.547498,-19.292413),(-59.735858,-19.29479),(-59.924322,-19.297064),(-60.006384,-19.298097),(-60.156995,-19.329),(-60.495476,-19.398453),(-60.833931,-19.467906),(-61.17236,-19.537463),(-61.51084,-19.606916),(-61.532286,-19.610016),(-61.579544,-19.616838),(-61.626725,-19.623659),(-61.648222,-19.62676),(-61.737235,-19.639575),(-61.753203,-19.64588),(-61.761213,-19.657765),(-61.780074,-19.706961),(-61.808186,-19.780342),(-61.836298,-19.853826),(-61.86441,-19.927413),(-61.892522,-20.000897),(-61.892574,-20.000897),(-61.905545,-20.026735),(-61.918412,-20.052573),(-61.92474,-20.065128),(-61.931383,-20.078308),(-61.94425,-20.104146),(-61.960942,-20.128021),(-61.977582,-20.151792),(-61.99417,-20.175667),(-62.01081,-20.199541),(-62.05551,-20.260416),(-62.10021,-20.321187),(-62.144962,-20.382062),(-62.189662,-20.442834),(-62.210573,-20.471305),(-62.232398,-20.501021),(-62.26883,-20.553111),(-62.277305,-20.579776),(-62.276168,-20.670727),(-62.275031,-20.75868),(-62.273791,-20.854798),(-62.271886,-21.000424),(-62.271879,-21.000939),(-62.275703,-21.066568),(-62.307898,-21.169301),(-62.340402,-21.272861),(-62.37549,-21.384482),(-62.411974,-21.500857),(-62.446184,-21.606897),(-62.492796,-21.751798),(-62.529228,-21.865073),(-62.572843,-22.000775),(-62.599404,-22.089865),(-62.627516,-22.184536),(-62.650357,-22.234456),(-62.658987,-22.231665),(-62.661829,-22.224534),(-62.663225,-22.215542),(-62.667462,-22.20655),(-62.679296,-22.194768),(-62.722032,-22.166243),(-62.769368,-22.144745),(-62.783476,-22.130896),(-62.790917,-22.113223),(-62.791072,-22.081597),(-62.79779,-22.069401),(-62.795051,-22.061133),(-62.795,-22.051211),(-62.801356,-22.013487),(-62.804353,-22.004082),(-62.818564,-22.000878),(-62.862024,-21.99323),(-63.009922,-22.000671),(-63.010439,-22.000775),(-63.324916,-21.999121),(-63.639392,-21.997468),(-63.67784,-22.003669),(-63.693911,-22.01204),(-63.74042,-22.050591),(-63.751789,-22.045733),(-63.793026,-22.011524),(-63.813129,-22.003049),(-63.906405,-21.997157),(-63.933173,-22.001808),(-63.947591,-22.007596),(-63.95095,-22.0108),(-63.951466,-22.016691),(-63.961027,-22.039119),(-63.964644,-22.058549),(-63.968106,-22.066507),(-63.975806,-22.073845),(-63.983454,-22.077359),(-63.990379,-22.079323),(-63.99565,-22.08294),(-64.004383,-22.09927),(-64.019783,-22.155391),(-64.051021,-22.229185),(-64.058798,-22.240347),(-64.078875,-22.250579),(-64.086239,-22.257917),(-64.160549,-22.438474),(-64.184708,-22.471237),(-64.236333,-22.516712),(-64.250828,-22.54069),(-64.293978,-22.690862),(-64.294598,-22.762899),(-64.303486,-22.782329),(-64.326947,-22.859224),(-64.325294,-22.871936),(-64.343897,-22.863668),(-64.347721,-22.816952),(-64.359994,-22.803),(-64.352321,-22.779125),(-64.355731,-22.751943),(-64.368986,-22.729723),(-64.390768,-22.720524),(-64.401723,-22.712359),(-64.428285,-22.659029),(-64.438233,-22.651898),(-64.447224,-22.648694),(-64.45371,-22.642906),(-64.456242,-22.628023),(-64.455208,-22.616655),(-64.450454,-22.597121),(-64.449421,-22.587096),(-64.445545,-22.576244),(-64.437251,-22.567355),(-64.429835,-22.557123),(-64.428285,-22.542344),(-64.483734,-22.491184),(-64.498126,-22.472787),(-64.504043,-22.449946),(-64.507815,-22.443952),(-64.525747,-22.432997),(-64.531328,-22.425658),(-64.531069,-22.41553),(-64.523292,-22.396203),(-64.524558,-22.385351),(-64.537891,-22.374292),(-64.558871,-22.36065),(-64.572023,-22.343183),(-64.562075,-22.319825),(-64.549156,-22.305356),(-64.542257,-22.291506),(-64.542774,-22.275487),(-64.551843,-22.255023),(-64.560215,-22.243137),(-64.58688,-22.212752),(-64.596207,-22.20655),(-64.616284,-22.20221),(-64.638711,-22.191668),(-64.65778,-22.178438),(-64.679045,-22.175441),(-64.687442,-22.172857),(-64.695245,-22.174201),(-64.713694,-22.181746),(-64.722892,-22.183296),(-64.762321,-22.174408),(-64.832472,-22.137511),(-65.020368,-22.096583),(-65.190478,-22.098474),(-65.457344,-22.101441),(-65.510467,-22.095859),(-65.579894,-22.086454),(-65.588524,-22.087281),(-65.593433,-22.091105),(-65.597878,-22.095653),(-65.605319,-22.099063),(-65.744613,-22.11405),(-65.775309,-22.105058),(-65.804557,-22.085834),(-65.932689,-21.944551),(-65.954497,-21.933079),(-66.046532,-21.917989),(-66.051752,-21.912615),(-66.063586,-21.864039),(-66.094488,-21.83293),(-66.137819,-21.812466),(-66.222465,-21.786938),(-66.240009,-21.792415),(-66.287551,-21.956953),(-66.297163,-22.050281),(-66.301504,-22.064957),(-66.307602,-22.077049),(-66.309824,-22.078186),(-66.314061,-22.075809),(-66.32667,-22.077359),(-66.335249,-22.08232),(-66.343,-22.090485),(-66.349175,-22.1002),(-66.353232,-22.109605),(-66.377468,-22.127072),(-66.510328,-22.162935),(-66.626755,-22.192598),(-66.630579,-22.197352),(-66.633267,-22.204897),(-66.636315,-22.211305),(-66.64138,-22.212545),(-66.657813,-22.207377),(-66.677398,-22.205103),(-66.688457,-22.201693),(-66.699309,-22.200763),(-66.712848,-22.206447),(-66.735896,-22.225051),(-66.748867,-22.244894),(-66.756101,-22.268252),(-66.767935,-22.342563),(-66.77517,-22.365197),(-66.788037,-22.38008),(-66.790518,-22.388348),(-66.784472,-22.417287),(-66.785092,-22.427622),(-66.796461,-22.434857),(-66.90865,-22.467516),(-66.935315,-22.480539),(-66.955572,-22.500693),(-66.965236,-22.514335),(-66.978155,-22.5225),(-66.993555,-22.525807),(-67.015672,-22.523844),(-67.032725,-22.524567),(-67.024354,-22.617585),(-67.026628,-22.639392),(-67.037686,-22.654585),(-67.113237,-22.710086),(-67.142693,-22.742745),(-67.193904,-22.822223),(-67.510267,-22.885785),(-67.547113,-22.892503),(-67.616772,-22.897258),(-67.77144,-22.888679),(-67.803583,-22.878654),(-67.811283,-22.871626),(-67.833038,-22.840103),(-67.837948,-22.840827),(-67.876343,-22.833592),(-67.887092,-22.818709),(-67.891484,-22.792871),(-67.891329,-22.715667),(-67.858721,-22.566838),(-67.859187,-22.547305),(-67.889676,-22.491184),(-67.898202,-22.441471),(-67.906936,-22.420077),(-67.94528,-22.354242),(-67.951894,-22.334088),(-67.952204,-22.314141),(-67.934789,-22.251716),(-67.935978,-22.232285),(-67.944969,-22.208307),(-67.97303,-22.170584),(-67.976595,-22.159835),(-67.973288,-22.15043),(-67.960627,-22.133687),(-67.957165,-22.124592),(-67.960627,-22.102887),(-67.972616,-22.078806),(-67.990186,-22.057619),(-68.010237,-22.044907),(-68.058761,-22.000775),(-68.082739,-21.980311),(-68.092041,-21.968425),(-68.096226,-21.953956),(-68.107595,-21.789625),(-68.128369,-21.712317),(-68.190588,-21.60638),(-68.198442,-21.57186),(-68.19374,-21.328464),(-68.207537,-21.284333),(-68.41631,-20.959805),(-68.432071,-20.945025),(-68.453931,-20.939754),(-68.495995,-20.941615),(-68.510206,-20.940168),(-68.531554,-20.927688),(-68.555113,-20.913916),(-68.57196,-20.872368),(-68.572786,-20.742867),(-68.565087,-20.719509),(-68.550204,-20.699046),(-68.481629,-20.643028),(-68.480957,-20.624735),(-68.510206,-20.601894),(-68.536303,-20.591765),(-68.583328,-20.563033),(-68.685544,-20.516834),(-68.707559,-20.500918),(-68.729676,-20.479214),(-68.750708,-20.451825),(-68.76541,-20.421233),(-68.769028,-20.390537),(-68.757685,-20.364286),(-68.735154,-20.347542),(-68.678516,-20.328629),(-68.718049,-20.261966),(-68.729469,-20.228687),(-68.728281,-20.189619),(-68.723268,-20.16099),(-68.726265,-20.150965),(-68.759028,-20.144144),(-68.789466,-20.125851),(-68.792592,-20.106627),(-68.775539,-20.089677),(-68.652885,-20.054227),(-68.622137,-20.051333),(-68.607771,-20.053607),(-68.597178,-20.056707),(-68.588341,-20.055571),(-68.579349,-20.045442),(-68.574543,-20.03521),(-68.56612,-20.000897),(-68.564932,-19.981363),(-68.544623,-19.934751),(-68.541574,-19.920385),(-68.542917,-19.914184),(-68.546948,-19.908189),(-68.551547,-19.894443),(-68.552529,-19.864885),(-68.553511,-19.857857),(-68.561108,-19.844317),(-68.570823,-19.837599),(-68.60157,-19.825404),(-68.618882,-19.813415),(-68.650353,-19.781582),(-68.698412,-19.746339),(-68.70544,-19.733833),(-68.703218,-19.71554),(-68.690299,-19.695386),(-68.648596,-19.660349),(-68.630974,-19.641952),(-68.576736,-19.564607),(-68.532117,-19.500979),(-68.532117,-19.500876),(-68.510206,-19.471627),(-68.496357,-19.458398),(-68.456101,-19.441241),(-68.447626,-19.434627),(-68.455016,-19.415403),(-68.472586,-19.395456),(-68.493205,-19.376956),(-68.600072,-19.303368),(-68.635728,-19.290553),(-68.663324,-19.273603),(-68.698464,-19.215622),(-68.721253,-19.191747),(-68.815407,-19.113303),(-68.847369,-19.092012),(-68.894782,-19.076509),(-68.908502,-19.067931),(-68.91969,-19.053771),(-68.943151,-19.001165),(-68.961703,-18.969435),(-68.973976,-18.956206),(-68.989609,-18.946491),(-68.959843,-18.907837),(-68.951781,-18.889337),(-68.951445,-18.867323),(-68.954649,-18.856987),(-69.01015,-18.745263),(-69.010537,-18.744539),(-69.010667,-18.743713),(-69.010537,-18.742989),(-69.003174,-18.729553),(-69.001107,-18.716221),(-69.003484,-18.702682),(-69.01015,-18.689762),(-69.033844,-18.649455),(-69.042835,-18.600466),(-69.041647,-18.548893),(-69.034903,-18.50104),(-69.034386,-18.478303),(-69.041698,-18.457735),(-69.07782,-18.398824),(-69.081877,-18.382494),(-69.079293,-18.328027),(-69.081024,-18.319139),(-69.095752,-18.276764),(-69.096837,-18.267979),(-69.09694,-18.257541),(-69.100351,-18.234286),(-69.110661,-18.217957),(-69.141201,-18.186847),(-69.155438,-18.140235),(-69.125931,-18.11109),(-69.089215,-18.083081),(-69.081722,-18.039983),(-69.082284,-18.039078),(-69.092057,-18.023343),(-69.104175,-18.023757),(-69.119885,-18.029854),(-69.14084,-18.030785),(-69.157712,-18.02572),(-69.173887,-18.018899),(-69.204169,-18.001122),(-69.227785,-17.995541),(-69.234813,-17.992957),(-69.241893,-17.986756),(-69.262047,-17.964019),(-69.277601,-17.967533),(-69.290029,-17.976628),(-69.302406,-17.976214),(-69.317857,-17.951616),(-69.326875,-17.915133),(-69.32765,-17.841546),(-69.334239,-17.805785),(-69.359405,-17.75938),(-69.394778,-17.721139),(-69.47578,-17.65241),(-69.497123,-17.621404),(-69.506114,-17.585127),(-69.510036,-17.506588),(-69.510094,-17.505442),(-69.508337,-17.434025),(-69.511385,-17.398678),(-69.522599,-17.36912),(-69.537094,-17.351136),(-69.556938,-17.331499),(-69.597272,-17.300493),(-69.613007,-17.295119),(-69.664416,-17.288562),(-69.666492,-17.288298),(-69.649413,-17.262769),(-69.633833,-17.207269),(-69.6228,-17.185565),(-69.618356,-17.184221),(-69.601147,-17.181534),(-69.59505,-17.179674),(-69.540996,-17.132235),(-69.510094,-17.112081),(-69.482808,-17.101746),(-69.454154,-17.096578),(-69.427437,-17.086863),(-69.406017,-17.062988),(-69.401263,-17.047175),(-69.406017,-17.040871),(-69.413304,-17.03777),(-69.416559,-17.031983),(-69.413588,-17.022267),(-69.407154,-17.015653),(-69.364314,-16.991158),(-69.352455,-16.977722),(-69.325945,-16.922222),(-69.224452,-16.818249),(-69.210654,-16.797061),(-69.191663,-16.743008),(-69.182362,-16.728745),(-69.166368,-16.719133),(-69.130582,-16.715826),(-69.112056,-16.711485),(-69.053816,-16.68234),(-69.037073,-16.670247),(-69.020511,-16.649474),(-69.008341,-16.634177),(-69.035135,-16.598004),(-69.040122,-16.581364),(-69.037642,-16.550255),(-69.038882,-16.49186),(-69.036815,-16.4715),(-69.027875,-16.454137),(-69.001727,-16.422821),(-68.96837,-16.406388),(-68.855844,-16.363186),(-68.833494,-16.328976),(-68.843648,-16.302001),(-68.86667,-16.286912),(-68.91876,-16.266655),(-68.959507,-16.22335),(-68.982038,-16.210017),(-69.01015,-16.219112),(-69.042732,-16.209294),(-69.053558,-16.208364),(-69.064514,-16.212084),(-69.083892,-16.226554),(-69.095183,-16.231205),(-69.120815,-16.231205),(-69.144689,-16.223453),(-69.166264,-16.210431),(-69.184868,-16.195031),(-69.219646,-16.15276),(-69.242125,-16.098189),(-69.284578,-15.995043),(-69.327133,-15.892),(-69.369611,-15.788958),(-69.412218,-15.685811),(-69.424337,-15.656253),(-69.430021,-15.62628),(-69.421184,-15.596411),(-69.356408,-15.50143),(-69.351111,-15.481896),(-69.348527,-15.461846),(-69.343411,-15.442209),(-69.330363,-15.424225),(-69.32026,-15.418851),(-69.292923,-15.409859),(-69.285921,-15.405415),(-69.285404,-15.396733),(-69.296954,-15.366968),(-69.291166,-15.350845),(-69.275198,-15.330278),(-69.255897,-15.313328),(-69.222592,-15.302166),(-69.20913,-15.263615),(-69.189726,-15.262375),(-69.166135,-15.263925),(-69.150426,-15.251626),(-69.1481,-15.233333),(-69.171768,-15.210802),(-69.196495,-15.176592),(-69.21267,-15.161296),(-69.272201,-15.118198),(-69.288583,-15.101971),(-69.346098,-15.016498),(-69.362816,-15.001305),(-69.384313,-14.981772),(-69.390669,-14.964408),(-69.386225,-14.945805),(-69.369844,-14.908288),(-69.367751,-14.900536),(-69.371988,-14.818681),(-69.370541,-14.801524),(-69.36142,-14.787985),(-69.339045,-14.774756),(-69.283518,-14.759666),(-69.267628,-14.750675),(-69.25383,-14.721839),(-69.2475,-14.593682),(-69.234658,-14.574251),(-69.214944,-14.572288),(-69.192232,-14.576939),(-69.170399,-14.577559),(-69.164507,-14.566397),(-69.167427,-14.520301),(-69.164275,-14.503041),(-69.158203,-14.498494),(-69.14115,-14.494153),(-69.134018,-14.490742),(-69.094563,-14.446404),(-69.075133,-14.432451),(-69.01015,-14.397105),(-68.990254,-14.379018),(-68.994621,-14.358967),(-69.008315,-14.33902),(-69.01617,-14.32114),(-69.01723,-14.282486),(-69.015705,-14.263159),(-69.01015,-14.245899),(-68.984906,-14.228329),(-68.951316,-14.219958),(-68.883724,-14.211483),(-68.864448,-14.191226),(-68.868892,-14.156189),(-68.893723,-14.089216),(-68.899976,-14.0548),(-68.905764,-14.039297),(-68.916176,-14.024931),(-68.969713,-13.990514),(-68.982968,-13.972221),(-68.98904,-13.940078),(-68.989195,-13.903698),(-68.992993,-13.869798),(-69.01015,-13.844373),(-69.023095,-13.80603),(-69.024283,-13.79249),(-69.020821,-13.776367),(-69.015964,-13.764585),(-69.015964,-13.753113),(-69.027048,-13.73823),(-69.08105,-13.695442),(-69.101591,-13.666607),(-69.087587,-13.643869),(-69.074539,-13.642629),(-69.044024,-13.648003),(-69.032629,-13.645936),(-69.023844,-13.634981),(-69.023612,-13.623302),(-69.025524,-13.610693),(-69.023198,-13.596947),(-69.015395,-13.585475),(-68.994259,-13.563047),(-68.985655,-13.550231),(-68.976819,-13.526253),(-68.970747,-13.501449),(-68.974441,-13.478814),(-68.962788,-13.283581),(-68.977025,-13.204929),(-68.979661,-13.16457),(-68.972142,-13.046128),(-68.973936,-13.03176),(-68.986224,-12.93337),(-68.986585,-12.890478),(-68.980953,-12.867947),(-68.94943,-12.843866),(-68.938733,-12.819681),(-68.926615,-12.800975),(-68.904627,-12.803972),(-68.891992,-12.775757),(-68.876566,-12.754983),(-68.856206,-12.741443),(-68.77373,-12.719429),(-68.766134,-12.710541),(-68.742957,-12.665789),(-68.752982,-12.65473),(-68.785332,-12.645945),(-68.794608,-12.63654),(-68.793419,-12.62021),(-68.783885,-12.605741),(-68.770113,-12.594372),(-68.74027,-12.578559),(-68.726059,-12.56595),(-68.714535,-12.551171),(-68.706267,-12.535978),(-68.70022,-12.516031),(-68.694381,-12.506832),(-68.684252,-12.502492),(-68.689463,-12.493418),(-68.714225,-12.450298),(-68.81856,-12.269224),(-68.922868,-12.08815),(-69.027281,-11.907076),(-69.13159,-11.726001),(-69.23595,-11.544927),(-69.340336,-11.36375),(-69.444568,-11.182675),(-69.548954,-11.001705),(-69.552494,-10.995607),(-69.556111,-10.989406),(-69.559729,-10.983101),(-69.563269,-10.9769),(-69.566834,-10.970699),(-69.570503,-10.964601),(-69.574017,-10.958503),(-69.577635,-10.952302),(-69.502885,-10.955299),(-69.463378,-10.951268),(-69.39594,-10.935042),(-69.363074,-10.940106),(-69.329588,-10.949408),(-69.293518,-10.954989),(-69.236803,-10.952922),(-69.158513,-10.96212),(-69.121487,-10.970595),(-69.086889,-10.967185),(-69.071309,-10.969975),(-68.996998,-11.001705),(-68.992502,-11.002428),(-68.983382,-11.002428),(-68.978937,-11.001705),(-68.955425,-11.000464),(-68.908141,-11.013383),(-68.884034,-11.016381),(-68.858919,-11.01049),(-68.831685,-11.000361),(-68.804659,-10.994677),(-68.774557,-11.003462),(-68.757633,-11.011937),(-68.773989,-11.035088),(-68.785642,-11.059272),(-68.791171,-11.08511),(-68.787011,-11.126038),(-68.783988,-11.13534),(-68.775926,-11.140611),(-68.758331,-11.141128),(-68.61573,-11.112499),(-68.588031,-11.09865),(-68.536096,-11.061546),(-68.493308,-11.047387),(-68.476565,-11.044803),(-68.459667,-11.044803),(-68.442407,-11.047697),(-68.428196,-11.043666),(-68.396415,-11.014417),(-68.378276,-11.005012),(-68.331147,-11.000464),(-68.313836,-10.993436),(-68.29332,-10.978967),(-68.274355,-10.960053),(-68.257509,-10.938763),(-68.243763,-10.916955),(-68.217563,-10.858044),(-68.203558,-10.838924),(-68.147283,-10.779599),(-68.112091,-10.714074),(-68.09788,-10.697744),(-68.074574,-10.681724),(-68.043775,-10.666945),(-68.027135,-10.661777),(-68.010237,-10.65971),(-67.981815,-10.664361),(-67.862649,-10.65878),(-67.847766,-10.66095),(-67.833348,-10.664981),(-67.81428,-10.675936),(-67.774954,-10.706529),(-67.755782,-10.714177),(-67.721727,-10.705495),(-67.705139,-10.67666),(-67.696044,-10.640486),(-67.684675,-10.610514),(-67.673823,-10.599352),(-67.643489,-10.574547),(-67.630828,-10.559561),(-67.61114,-10.528762),(-67.599978,-10.515429),(-67.58463,-10.501787),(-67.565096,-10.495896),(-67.529336,-10.478532),(-67.488201,-10.464786),(-67.468048,-10.452281),(-67.450529,-10.435951),(-67.436628,-10.417451),(-67.432236,-10.406082),(-67.431874,-10.397917),(-67.42929,-10.390372),(-67.418335,-10.381484),(-67.409188,-10.378797),(-67.365005,-10.378073),(-67.353481,-10.376213),(-67.342836,-10.372492),(-67.335291,-10.366291),(-67.333689,-10.356679),(-67.339425,-10.334872),(-67.337823,-10.326087),(-67.323509,-10.318852),(-67.300668,-10.315132),(-67.259172,-10.313685),(-67.241033,-10.316372),(-67.201759,-10.32681),(-67.184706,-10.326707),(-67.172303,-10.319576),(-67.164862,-10.308517),(-67.159074,-10.297148),(-67.151736,-10.288983),(-67.141763,-10.285573),(-67.12073,-10.284539),(-67.110033,-10.282575),(-67.0643,-10.256944),(-66.902656,-10.09313),(-66.770623,-9.992567),(-66.751606,-9.982645),(-66.670009,-9.951536),(-66.660087,-9.945335),(-66.654816,-9.93717),(-66.65249,-9.926111),(-66.648925,-9.915879),(-66.648904,-9.915854),(-66.64262,-9.907921),(-66.631871,-9.904304),(-66.513842,-9.883943),(-66.452864,-9.888698),(-66.43271,-9.886114),(-66.41328,-9.879189),(-66.371732,-9.855935),(-66.355273,-9.84963),(-66.257321,-9.834851),(-66.238975,-9.828133),(-66.20797,-9.808082),(-66.190658,-9.800848),(-66.135467,-9.795163),(-66.131695,-9.797024),(-66.127923,-9.801158),(-66.123582,-9.805085),(-66.118182,-9.806015),(-66.113117,-9.802398),(-66.106064,-9.790409),(-66.101981,-9.787412),(-66.086995,-9.784518),(-66.081724,-9.785655),(-66.069322,-9.790099),(-66.042786,-9.804878),(-66.029479,-9.808289),(-66.010385,-9.804052),(-65.965659,-9.776766),(-65.946952,-9.771392),(-65.92933,-9.770255),(-65.915274,-9.771702),(-65.874424,-9.781314),(-65.862461,-9.781831),(-65.85042,-9.77532),(-65.834065,-9.758266),(-65.831662,-9.765294),(-65.827398,-9.773976),(-65.822127,-9.781831),(-65.816521,-9.785965),(-65.806418,-9.784415),(-65.803705,-9.775526),(-65.803886,-9.764778),(-65.802645,-9.757336),(-65.794506,-9.737699),(-65.788564,-9.733048),(-65.782207,-9.746277),(-65.779959,-9.755993),(-65.77735,-9.763434),(-65.772441,-9.768808),(-65.76319,-9.772322),(-65.725493,-9.756819),(-65.709964,-9.755993),(-65.713736,-9.77873),(-65.717302,-9.791236),(-65.713116,-9.794233),(-65.705054,-9.793303),(-65.69707,-9.794336),(-65.694357,-9.793716),(-65.683609,-9.789892),(-65.678958,-9.789376),(-65.672628,-9.792579),(-65.663713,-9.802915),(-65.658494,-9.807359),(-65.628883,-9.826893),(-65.614388,-9.833921),(-65.596121,-9.837951),(-65.583977,-9.837228),(-65.579377,-9.832784),(-65.577052,-9.826169),(-65.571884,-9.818831),(-65.570618,-9.815834),(-65.569921,-9.806015),(-65.567983,-9.802088),(-65.562815,-9.799194),(-65.5508,-9.797024),(-65.546821,-9.795163),(-65.535323,-9.782451),(-65.525427,-9.767878),(-65.521396,-9.758576),(-65.517133,-9.743177),(-65.510777,-9.734082),(-65.465224,-9.696461),(-65.45184,-9.681372),(-65.442487,-9.679821),(-65.416235,-9.680132),(-65.397993,-9.686746),(-65.370501,-9.710621),(-65.356058,-9.741626),(-65.353732,-9.745037),(-65.340064,-9.789686),(-65.330323,-9.800744),(-65.316603,-9.812527),(-65.304381,-9.825652),(-65.29911,-9.841259),(-65.30358,-9.864513),(-65.325233,-9.905131),(-65.333294,-9.926835),(-65.336834,-9.967246),(-65.332932,-10.00838),(-65.324148,-10.046414),(-65.30557,-10.098401),(-65.301462,-10.119691),(-65.29911,-10.162996),(-65.296811,-10.173331),(-65.286837,-10.196482),(-65.284822,-10.206818),(-65.288077,-10.216223),(-65.305363,-10.242164),(-65.315621,-10.291257),(-65.327817,-10.314408),(-65.365024,-10.332185),(-65.379235,-10.351408),(-65.39019,-10.374043),(-65.394646,-10.39207),(-65.394738,-10.392439),(-65.393084,-10.400191),(-65.39143,-10.403498),(-65.38727,-10.406702),(-65.410938,-10.44918),(-65.425382,-10.463133),(-65.44998,-10.468094),(-65.44998,-10.474915),(-65.437913,-10.492588),(-65.435691,-10.499203),(-65.436725,-10.504061),(-65.441479,-10.513362),(-65.442487,-10.519357),(-65.441634,-10.527832),(-65.439308,-10.538167),(-65.435898,-10.546952),(-65.431996,-10.550673),(-65.429232,-10.561421),(-65.435639,-10.610824),(-65.435691,-10.62581),(-65.418612,-10.644517),(-65.400784,-10.655473),(-65.386753,-10.669529),(-65.381069,-10.698054),(-65.382258,-10.715624),(-65.389777,-10.753761),(-65.404737,-10.799236),(-65.399698,-10.812259),(-65.360295,-10.822594),(-65.342183,-10.834893),(-65.327119,-10.850499),(-65.31898,-10.865382),(-65.312779,-10.950958),(-65.310117,-10.956539),(-65.30451,-10.962017),(-65.299601,-10.969665),(-65.29911,-10.982068),(-65.302986,-10.990749),(-65.309652,-10.99664),(-65.317843,-11.002015),(-65.326447,-11.009353),(-65.341976,-11.032814),(-65.342699,-11.050591),(-65.337041,-11.067747),(-65.333294,-11.088521),(-65.341046,-11.106608),(-65.379674,-11.136373),(-65.394738,-11.153427),(-65.398148,-11.178025),(-65.385203,-11.193631),(-65.368331,-11.205413),(-65.360011,-11.218849),(-65.366057,-11.234042),(-65.378614,-11.242),(-65.388614,-11.253162),(-65.38727,-11.277553),(-65.37448,-11.295847),(-65.353913,-11.310626),(-65.334819,-11.321168),(-65.326447,-11.327783),(-65.330064,-11.340495),(-65.347505,-11.360752),(-65.353732,-11.372431),(-65.354766,-11.382353),(-65.353009,-11.390621),(-65.319548,-11.476404),(-65.29247,-11.504723)] +Barbados [(-59.42691,13.160386),(-59.430043,13.125922),(-59.455719,13.100043),(-59.475779,13.086493),(-59.487538,13.078559),(-59.50886,13.057318),(-59.516713,13.056383),(-59.523101,13.056464),(-59.529286,13.055406),(-59.536122,13.051174),(-59.545969,13.067694),(-59.564443,13.07803),(-59.586903,13.083197),(-59.60025,13.084133),(-59.608144,13.084662),(-59.621571,13.09398),(-59.633127,13.115912),(-59.646067,13.160386),(-59.654205,13.295111),(-59.652211,13.310614),(-59.645131,13.323717),(-59.63093,13.337958),(-59.612864,13.34455),(-59.594472,13.334784),(-59.580719,13.314521),(-59.575917,13.304389),(-59.568959,13.289659),(-59.549794,13.249172),(-59.53661,13.231391),(-59.518056,13.217515),(-59.491811,13.197943),(-59.476674,13.189399),(-59.457102,13.183173),(-59.438629,13.174872),(-59.42691,13.160386)] +Bhutan [(90.261804,28.335354),(90.261804,28.299141),(90.29147,28.261351),(90.329504,28.255796),(90.353984,28.299141),(90.386905,28.299141),(90.416535,28.28268),(90.45604,28.28268),(90.505422,28.249758),(90.54822,28.246466),(90.587726,28.233298),(90.597602,28.200376),(90.567973,28.1905),(90.54822,28.157579),(90.515299,28.154287),(90.485669,28.124657),(90.475232,28.072344),(90.492595,28.074412),(90.510061,28.074101),(90.575277,28.065833),(90.597395,28.070587),(90.621889,28.072965),(90.651035,28.086995),(90.667468,28.090328),(90.683901,28.087072),(90.726896,28.061699),(90.755278,28.055173),(90.788701,28.047488),(90.850919,28.044026),(90.90952,28.032657),(90.960577,27.994726),(90.975149,27.982092),(91.008842,27.96677),(91.051941,27.96279),(91.092558,27.971679),(91.11943,27.994726),(91.11943,27.994778),(91.119637,27.994881),(91.133796,28.014105),(91.175861,28.057487),(91.194671,28.070587),(91.220612,28.074877),(91.246141,28.071466),(91.269705,28.072861),(91.290169,28.091413),(91.309599,28.056402),(91.341432,28.030564),(91.418843,27.994726),(91.436483,27.989375),(91.446438,27.986355),(91.460908,27.984365),(91.497495,27.984081),(91.537492,27.969353),(91.578627,27.964702),(91.600641,27.959276),(91.621725,27.950724),(91.637951,27.939743),(91.652834,27.916747),(91.648907,27.897213),(91.637124,27.87724),(91.628339,27.852694),(91.627306,27.829827),(91.632887,27.759444),(91.626686,27.716423),(91.579867,27.657977),(91.573252,27.619711),(91.59506,27.546382),(91.604465,27.532145),(91.632887,27.511655),(91.641672,27.494964),(91.657382,27.479151),(91.680223,27.472846),(91.704924,27.468764),(91.727041,27.460005),(91.727092,27.459942),(91.743681,27.439153),(91.744818,27.423754),(91.750089,27.416157),(91.779648,27.418844),(91.857369,27.443081),(91.884345,27.447163),(91.920931,27.445148),(91.933747,27.449127),(91.963306,27.468919),(91.975088,27.472433),(91.997309,27.448662),(92.084849,27.304226),(92.088776,27.29234),(92.081852,27.275132),(92.050639,27.251413),(92.03679,27.236478),(92.033173,27.227435),(92.029969,27.20847),(92.027075,27.19984),(92.021494,27.19183),(92.008471,27.179479),(92.005788,27.176112),(92.002994,27.172606),(91.995862,27.158033),(91.990798,27.140773),(91.987904,27.122273),(91.987697,27.104031),(91.999893,27.071527),(92.049709,27.026827),(92.066969,26.994943),(92.066969,26.994839),(92.083919,26.937323),(92.080371,26.921571),(92.072757,26.887766),(92.03586,26.854848),(91.975088,26.846631),(91.957415,26.854279),(91.925686,26.878671),(91.908219,26.885182),(91.89313,26.881358),(91.895507,26.868284),(91.895507,26.853504),(91.874009,26.844306),(91.885895,26.83087),(91.886928,26.814437),(91.87866,26.803016),(91.863054,26.804773),(91.852408,26.818519),(91.849515,26.834746),(91.843934,26.84937),(91.825123,26.858465),(91.795254,26.853504),(91.731589,26.816194),(91.702133,26.803481),(91.653764,26.797952),(91.637951,26.798985),(91.593716,26.810768),(91.57563,26.810148),(91.539353,26.79883),(91.520646,26.79759),(91.507417,26.808029),(91.484472,26.852729),(91.475067,26.865545),(91.460598,26.869369),(91.420187,26.871539),(91.406338,26.869524),(91.388457,26.858465),(91.378122,26.842807),(91.370061,26.824669),(91.358382,26.806169),(91.345566,26.794696),(91.330063,26.785498),(91.313217,26.778677),(91.296577,26.774594),(91.27601,26.774077),(91.261954,26.779038),(91.232498,26.795161),(91.198185,26.802344),(91.127078,26.800898),(91.091938,26.804773),(91.062069,26.804567),(91.012781,26.784348),(91.007395,26.782139),(90.944493,26.77887),(90.717077,26.767049),(90.587783,26.780072),(90.475232,26.83242),(90.382627,26.891796),(90.348831,26.896654),(90.328574,26.890659),(90.314208,26.880376),(90.300875,26.868284),(90.284442,26.85707),(90.265994,26.851592),(90.229148,26.852884),(90.210907,26.851489),(90.17742,26.832058),(90.152202,26.771752),(90.127191,26.751392),(90.089157,26.741728),(89.975262,26.731858),(89.912113,26.716717),(89.890409,26.714856),(89.880281,26.716252),(89.85992,26.721884),(89.858701,26.722057),(89.850774,26.723176),(89.847001,26.72483),(89.839043,26.731238),(89.834961,26.731548),(89.829741,26.72762),(89.827674,26.722453),(89.827261,26.717905),(89.826744,26.715683),(89.826796,26.713513),(89.825245,26.707673),(89.822093,26.701007),(89.817287,26.696201),(89.81367,26.696149),(89.804058,26.699767),(89.800079,26.70049),(89.760288,26.70018),(89.75467,26.700989),(89.738739,26.703281),(89.685151,26.724571),(89.66324,26.725502),(89.628307,26.712531),(89.609806,26.712221),(89.597507,26.720954),(89.613475,26.748549),(89.611357,26.765964),(89.586087,26.784051),(89.546503,26.797539),(89.50542,26.803688),(89.442891,26.797022),(89.407338,26.813403),(89.368895,26.837359),(89.341657,26.854331),(89.300161,26.844409),(89.286364,26.844978),(89.273599,26.843892),(89.262954,26.836348),(89.252619,26.826787),(89.240837,26.819759),(89.212828,26.813041),(89.184613,26.810561),(89.128079,26.813455),(89.096504,26.821413),(89.082448,26.836037),(89.074335,26.856398),(89.060693,26.881461),(89.04488,26.897119),(89.021574,26.912674),(88.996614,26.922751),(88.975323,26.921717),(88.965815,26.915464),(88.954549,26.912622),(88.942767,26.913707),(88.932328,26.919237),(88.9253,26.929365),(88.925404,26.939029),(88.926954,26.949416),(88.924474,26.961663),(88.906645,26.981093),(88.88644,26.978975),(88.867113,26.964247),(88.851713,26.945437),(88.845615,26.994839),(88.845615,26.994943),(88.845615,27.049565),(88.840809,27.075248),(88.827632,27.097882),(88.805256,27.113023),(88.742572,27.142737),(88.733082,27.148972),(88.730067,27.150954),(88.738438,27.179789),(88.754355,27.212604),(88.775852,27.240871),(88.801174,27.256425),(88.861428,27.270378),(88.876116,27.280486),(88.884631,27.286346),(88.892331,27.315543),(88.91516,27.330869),(88.950808,27.328229),(88.971933,27.312385),(88.997019,27.330869),(88.981175,27.354635),(88.964011,27.392924),(88.95106,27.433144),(88.957549,27.456939),(88.966202,27.47803),(88.982966,27.492632),(88.980046,27.49798),(88.97521,27.506839),(88.972955,27.517659),(88.978366,27.530283),(88.992793,27.537497),(89.004966,27.54967),(89.002712,27.560491),(89.016238,27.57582),(89.03337,27.578976),(89.039682,27.594305),(89.050954,27.608282),(89.064029,27.615946),(89.091531,27.625865),(89.102351,27.623611),(89.105865,27.622952),(89.109565,27.622258),(89.119484,27.618201),(89.124655,27.614852),(89.127359,27.62729),(89.156021,27.665686),(89.198203,27.730582),(89.21659,27.771142),(89.22492,27.807813),(89.258717,27.827553),(89.299489,27.844245),(89.336025,27.869075),(89.370131,27.909357),(89.417364,27.988654),(89.420981,27.994726),(89.421187,27.994726),(89.444545,28.031184),(89.458808,28.047798),(89.475344,28.061337),(89.495343,28.068004),(89.515032,28.081905),(89.561489,28.13464),(89.579421,28.14464),(89.597817,28.149807),(89.71781,28.169083),(89.755844,28.184379),(89.773621,28.212775),(89.780855,28.228769),(89.796048,28.24019),(89.829741,28.259155),(89.83863,28.267914),(89.854029,28.287267),(89.862918,28.295793),(89.873615,28.300599),(89.881314,28.297525),(89.91613,28.315601),(89.952524,28.308247),(89.971593,28.31804),(89.990455,28.320624),(90.07086,28.34523),(90.123535,28.335354),(90.153164,28.322185),(90.176209,28.325478),(90.199254,28.348523),(90.225591,28.358399),(90.261804,28.335354)] +Botswana [(25.259781,-17.794107),(25.21937,-17.879786),(25.21937,-17.908001),(25.226088,-17.931876),(25.255026,-18.001122),(25.296368,-18.068612),(25.323446,-18.09662),(25.357449,-18.115844),(25.387525,-18.138995),(25.408816,-18.175995),(25.440855,-18.2532),(25.473204,-18.303429),(25.481163,-18.323377),(25.490516,-18.365545),(25.49558,-18.378877),(25.508499,-18.399134),(25.574439,-18.465693),(25.608442,-18.487708),(25.622084,-18.501143),(25.669523,-18.566049),(25.698255,-18.590234),(25.736909,-18.608734),(25.761921,-18.630335),(25.773393,-18.665578),(25.779491,-18.738752),(25.815251,-18.813993),(25.940721,-18.921273),(25.967449,-18.999925),(25.9678,-19.000958),(25.964389,-19.021629),(25.948059,-19.058732),(25.944855,-19.079196),(25.948576,-19.103277),(25.956534,-19.122088),(25.981132,-19.161775),(26.011414,-19.199809),(26.034359,-19.243734),(26.13027,-19.501082),(26.155488,-19.537153),(26.194452,-19.5602),(26.239101,-19.571466),(26.292638,-19.572499),(26.30349,-19.577254),(26.313205,-19.584178),(26.32106,-19.592033),(26.330981,-19.604952),(26.333462,-19.613014),(26.326331,-19.633891),(26.319096,-19.646293),(26.312481,-19.649601),(26.312171,-19.651358),(26.324367,-19.659109),(26.332325,-19.662416),(26.362711,-19.667584),(26.385242,-19.679056),(26.412837,-19.71957),(26.431854,-19.73652),(26.450251,-19.743342),(26.489731,-19.75192),(26.508852,-19.759258),(26.549263,-19.784063),(26.566316,-19.800806),(26.574791,-19.819513),(26.581922,-19.842147),(26.595565,-19.855583),(26.614065,-19.863438),(26.659437,-19.875737),(26.673803,-19.883385),(26.67717,-19.886815),(26.684758,-19.894547),(26.698608,-19.91253),(26.713904,-19.927413),(26.730957,-19.935888),(26.750801,-19.939609),(26.774469,-19.939815),(26.811882,-19.94643),(26.925054,-20.000897),(26.961072,-20.007201),(26.9943,-20.006788),(27.02665,-20.010095),(27.060136,-20.027562),(27.069231,-20.03738),(27.086491,-20.060532),(27.097343,-20.068903),(27.109642,-20.073244),(27.119771,-20.073864),(27.129692,-20.072934),(27.141888,-20.073347),(27.16292,-20.076551),(27.183746,-20.082339),(27.201781,-20.092984),(27.214907,-20.110451),(27.266015,-20.234164),(27.283998,-20.35147),(27.268392,-20.49575),(27.306012,-20.477354),(27.340739,-20.473013),(27.45391,-20.473323),(27.534112,-20.483038),(27.590853,-20.473323),(27.625786,-20.488619),(27.66599,-20.489136),(27.683767,-20.49606),(27.698133,-20.509083),(27.705575,-20.526653),(27.702629,-20.566134),(27.690382,-20.60148),(27.682475,-20.637344),(27.707332,-20.716719),(27.709605,-20.756716),(27.694412,-20.837745),(27.689038,-20.849011),(27.681803,-20.857589),(27.676016,-20.866684),(27.674775,-20.879913),(27.675085,-20.891282),(27.672605,-20.913709),(27.672657,-20.923528),(27.680356,-20.979649),(27.678961,-21.000733),(27.666817,-21.053753),(27.666611,-21.071219),(27.674775,-21.090133),(27.709192,-21.134471),(27.724385,-21.149664),(27.793838,-21.197413),(27.823604,-21.231726),(27.849132,-21.269657),(27.884995,-21.310171),(27.8944,-21.32433),(27.896674,-21.332392),(27.896157,-21.347895),(27.897811,-21.35544),(27.904219,-21.364741),(27.920549,-21.381174),(27.950211,-21.438329),(27.953001,-21.448664),(27.949642,-21.456519),(27.941943,-21.468508),(27.939876,-21.478016),(27.943338,-21.479876),(27.950418,-21.482047),(27.954448,-21.487835),(27.949281,-21.500754),(27.953208,-21.510469),(27.958066,-21.511502),(27.963698,-21.510469),(27.970571,-21.514396),(27.975739,-21.522561),(27.984731,-21.542922),(27.990415,-21.551913),(28.002559,-21.564212),(28.016563,-21.572894),(28.032893,-21.577855),(28.090771,-21.581266),(28.165702,-21.595218),(28.284867,-21.596872),(28.321919,-21.603486),(28.361762,-21.616302),(28.443101,-21.655783),(28.464598,-21.660331),(28.481393,-21.657437),(28.497309,-21.651546),(28.532501,-21.643071),(28.542939,-21.638316),(28.553998,-21.636559),(28.585934,-21.644414),(28.6157,-21.647101),(28.629704,-21.651339),(28.66841,-21.679968),(28.714195,-21.693507),(28.860853,-21.757379),(28.891032,-21.764924),(28.951907,-21.768334),(28.980846,-21.774845),(28.998726,-21.786008),(29.038723,-21.797893),(29.05526,-21.809985),(29.057637,-21.829209),(29.045441,-21.852567),(29.028905,-21.876648),(29.017949,-21.898145),(29.013815,-21.940417),(29.021567,-21.982791),(29.040532,-22.020929),(29.070763,-22.051004),(29.10797,-22.069194),(29.144867,-22.075292),(29.239331,-22.072605),(29.244395,-22.075706),(29.254111,-22.087074),(29.259588,-22.096066),(29.26734,-22.115807),(29.273644,-22.125108),(29.350074,-22.186707),(29.331522,-22.192804),(29.302893,-22.190221),(29.248219,-22.179265),(29.222071,-22.182159),(29.202796,-22.194458),(29.186621,-22.207687),(29.168844,-22.213992),(29.047818,-22.220296),(29.038723,-22.223914),(29.017846,-22.250372),(29.018053,-22.255023),(29.002756,-22.263394),(28.983739,-22.281998),(28.960227,-22.310213),(28.967926,-22.38039),(28.963379,-22.392172),(28.953457,-22.40075),(28.930409,-22.440851),(28.912529,-22.453667),(28.86938,-22.448913),(28.84659,-22.449946),(28.836772,-22.463176),(28.831191,-22.482296),(28.816825,-22.492941),(28.796774,-22.498212),(28.77476,-22.501416),(28.731352,-22.513922),(28.659005,-22.551956),(28.623865,-22.562808),(28.5972,-22.562704),(28.577563,-22.560017),(28.559838,-22.563014),(28.538495,-22.580274),(28.522476,-22.584822),(28.459379,-22.569629),(28.376851,-22.575003),(28.338559,-22.584615),(28.301817,-22.603839),(28.286831,-22.615828),(28.250554,-22.655619),(28.240684,-22.66089),(28.216344,-22.663163),(28.205492,-22.665954),(28.196191,-22.671638),(28.164668,-22.708639),(28.159707,-22.718147),(28.157743,-22.731066),(28.159707,-22.743262),(28.162704,-22.751013),(28.162498,-22.758971),(28.154953,-22.771994),(28.145858,-22.779745),(28.135626,-22.783363),(28.125601,-22.785533),(28.117436,-22.789461),(28.113198,-22.795352),(28.107721,-22.810648),(28.10369,-22.816746),(28.088807,-22.822637),(28.065759,-22.828838),(28.047156,-22.8369),(28.045399,-22.847752),(28.053977,-22.869146),(28.04974,-22.891366),(28.037441,-22.911417),(28.021834,-22.92661),(28.008295,-22.934775),(27.989382,-22.943766),(27.968401,-22.951001),(27.949177,-22.953895),(27.937498,-22.963817),(27.937912,-22.986658),(27.946077,-23.029032),(27.930057,-23.057041),(27.895537,-23.079469),(27.853783,-23.095592),(27.815749,-23.104687),(27.82226,-23.12298),(27.806447,-23.128355),(27.78495,-23.127011),(27.774201,-23.125151),(27.77172,-23.133005),(27.774614,-23.140757),(27.779058,-23.147682),(27.781022,-23.152539),(27.783038,-23.155433),(27.787378,-23.159774),(27.78929,-23.163805),(27.784588,-23.165562),(27.783296,-23.166905),(27.775751,-23.172486),(27.774201,-23.173003),(27.759421,-23.21145),(27.753634,-23.220752),(27.739164,-23.227573),(27.725728,-23.221682),(27.698443,-23.193467),(27.658756,-23.223439),(27.647129,-23.227573),(27.633434,-23.223439),(27.619172,-23.217031),(27.608009,-23.216721),(27.599224,-23.244627),(27.580414,-23.26385),(27.576073,-23.279146),(27.575247,-23.284831),(27.573076,-23.290515),(27.569614,-23.294856),(27.565893,-23.29651),(27.563309,-23.299197),(27.564911,-23.305811),(27.567754,-23.31377),(27.569356,-23.320384),(27.563671,-23.342812),(27.548892,-23.360795),(27.528841,-23.373094),(27.50724,-23.379089),(27.465693,-23.380432),(27.45267,-23.38529),(27.443162,-23.395108),(27.434997,-23.406581),(27.425178,-23.412678),(27.411122,-23.405754),(27.41846,-23.391284),(27.410502,-23.389321),(27.395826,-23.394075),(27.383734,-23.399553),(27.38084,-23.40534),(27.371331,-23.417019),(27.361203,-23.422497),(27.349989,-23.391491),(27.335571,-23.402446),(27.312007,-23.43707),(27.295574,-23.451746),(27.278107,-23.463631),(27.239712,-23.481408),(27.202505,-23.492053),(27.191497,-23.503836),(27.205657,-23.523059),(27.195632,-23.52709),(27.18664,-23.527297),(27.178682,-23.523576),(27.171447,-23.515618),(27.168967,-23.521612),(27.161525,-23.52988),(27.157184,-23.536702),(27.149123,-23.527503),(27.137651,-23.523369),(27.127419,-23.525023),(27.123078,-23.532981),(27.127419,-23.54528),(27.135687,-23.551895),(27.141165,-23.558303),(27.13672,-23.570188),(27.124421,-23.56316),(27.113363,-23.564297),(27.103751,-23.571738),(27.095793,-23.583831),(27.102511,-23.583831),(27.084114,-23.596026),(27.078326,-23.602021),(27.075225,-23.611219),(27.068404,-23.607292),(27.061531,-23.604398),(27.063133,-23.624242),(27.069438,-23.641708),(27.070058,-23.656074),(27.054762,-23.66641),(27.037605,-23.665686),(27.029854,-23.654731),(27.024273,-23.642535),(27.013834,-23.638504),(27.00417,-23.645842),(26.986549,-23.686977),(26.96717,-23.718706),(26.962054,-23.737413),(26.964542,-23.74714),(26.966602,-23.75519),(26.938128,-23.802887),(26.945001,-23.823248),(26.941177,-23.850223),(26.870897,-24.11584),(26.868933,-24.160385),(26.84971,-24.248131),(26.839168,-24.265598),(26.823251,-24.278827),(26.802271,-24.289679),(26.714007,-24.315931),(26.692923,-24.326576),(26.684087,-24.341459),(26.62347,-24.39944),(26.558358,-24.438197),(26.531176,-24.458661),(26.506061,-24.48884),(26.476812,-24.559947),(26.469474,-24.571419),(26.404362,-24.632811),(26.404001,-24.632758),(26.381624,-24.629503),(26.363538,-24.628056),(26.344521,-24.624026),(26.32571,-24.622372),(26.278788,-24.62847),(26.165911,-24.660846),(26.013585,-24.704537),(25.981132,-24.726345),(25.966043,-24.73358),(25.914676,-24.731823),(25.881707,-24.742158),(25.874058,-24.743398),(25.868374,-24.748152),(25.866927,-24.772647),(25.877262,-24.845717),(25.876746,-24.886025),(25.866204,-24.918168),(25.837058,-24.979146),(25.835198,-25.016353),(25.804915,-25.064826),(25.782901,-25.131385),(25.695465,-25.309979),(25.663529,-25.439996),(25.652838,-25.463319),(25.608855,-25.559266),(25.587254,-25.61952),(25.458425,-25.711194),(25.386491,-25.743544),(25.177822,-25.763284),(25.135964,-25.756566),(25.090282,-25.743647),(25.051731,-25.737859),(25.013284,-25.743027),(24.967912,-25.762871),(24.908381,-25.804109),(24.888537,-25.811653),(24.828903,-25.826019),(24.79862,-25.829223),(24.770715,-25.822609),(24.737952,-25.815891),(24.664985,-25.823332),(24.629638,-25.816098),(24.576722,-25.783335),(24.500851,-25.757848),(24.456729,-25.743027),(24.436782,-25.745301),(24.416731,-25.753052),(24.38924,-25.75946),(24.338907,-25.751812),(24.296739,-25.723493),(24.227699,-25.648976),(24.183464,-25.625928),(24.130961,-25.626238),(24.027091,-25.651766),(24.005697,-25.65466),(24.00425,-25.649906),(24.009624,-25.641328),(24.008694,-25.633163),(23.998256,-25.625308),(23.988024,-25.61952),(23.976448,-25.617557),(23.924772,-25.629236),(23.905755,-25.618487),(23.890665,-25.59885),(23.845397,-25.569084),(23.807466,-25.523609),(23.798578,-25.518545),(23.778321,-25.51255),(23.769019,-25.507383),(23.762301,-25.498494),(23.752069,-25.477617),(23.742664,-25.469969),(23.68675,-25.454362),(23.674244,-25.44258),(23.6667,-25.432658),(23.561073,-25.357314),(23.535855,-25.343258),(23.506606,-25.330959),(23.496581,-25.324241),(23.483455,-25.311529),(23.468159,-25.290238),(23.45927,-25.282177),(23.444904,-25.278146),(23.431985,-25.280316),(23.399222,-25.291375),(23.381446,-25.292615),(23.365943,-25.289308),(23.320364,-25.273392),(23.265691,-25.263987),(23.216081,-25.26719),(23.168539,-25.280006),(23.093401,-25.312459),(23.083893,-25.319694),(23.071697,-25.325998),(23.065496,-25.320831),(23.061155,-25.310702),(23.054541,-25.302537),(23.030666,-25.299437),(23.006998,-25.310805),(22.968034,-25.346876),(22.962557,-25.355764),(22.960283,-25.364342),(22.956149,-25.372094),(22.94478,-25.378708),(22.930931,-25.384289),(22.920492,-25.39049),(22.911914,-25.399069),(22.903645,-25.411368),(22.887626,-25.450228),(22.876774,-25.462011),(22.851349,-25.471312),(22.844631,-25.481131),(22.824684,-25.543039),(22.816829,-25.558439),(22.814039,-25.566604),(22.813418,-25.575079),(22.819206,-25.584897),(22.828715,-25.595542),(22.833366,-25.606084),(22.824374,-25.6158),(22.810835,-25.625308),(22.809594,-25.633266),(22.813418,-25.641948),(22.814969,-25.6528),(22.812798,-25.667063),(22.810214,-25.677398),(22.804427,-25.687216),(22.759778,-25.734862),(22.746446,-25.755326),(22.740451,-25.77703),(22.741175,-25.790879),(22.744999,-25.794083),(22.75089,-25.796047),(22.757918,-25.805969),(22.764119,-25.820335),(22.765463,-25.826536),(22.754714,-25.843383),(22.739521,-25.858472),(22.719471,-25.874285),(22.708825,-25.891028),(22.721641,-25.909012),(22.726809,-25.921621),(22.727222,-25.943945),(22.724225,-25.967509),(22.719367,-25.984253),(22.710479,-25.996862),(22.70066,-26.00327),(22.672238,-26.012881),(22.661593,-26.020943),(22.66211,-26.029831),(22.665831,-26.039856),(22.665004,-26.051432),(22.623249,-26.10931),(22.620863,-26.111532),(22.611157,-26.120575),(22.59152,-26.133184),(22.580254,-26.146517),(22.563821,-26.18114),(22.545114,-26.207391),(22.527958,-26.213696),(22.482586,-26.204808),(22.450857,-26.210079),(22.428842,-26.226512),(22.395046,-26.271884),(22.342853,-26.317359),(22.318772,-26.328831),(22.303165,-26.333585),(22.257277,-26.340923),(22.248285,-26.346918),(22.237743,-26.366762),(22.197435,-26.404072),(22.178315,-26.439935),(22.146172,-26.519207),(22.108138,-26.571917),(22.057702,-26.617599),(21.998998,-26.650258),(21.935849,-26.663901),(21.838801,-26.664521),(21.807278,-26.669585),(21.780613,-26.678164),(21.768728,-26.688706),(21.767487,-26.704312),(21.776479,-26.749167),(21.777513,-26.768494),(21.773379,-26.786788),(21.76232,-26.804461),(21.74382,-26.820481),(21.687182,-26.855207),(21.664548,-26.863062),(21.643361,-26.862752),(21.583933,-26.848386),(21.498667,-26.846422),(21.449471,-26.826372),(21.42663,-26.822651),(21.380844,-26.823995),(21.296922,-26.844459),(21.282866,-26.844975),(21.254857,-26.841771),(21.240595,-26.841978),(21.153468,-26.864509),(21.122462,-26.865336),(20.990377,-26.838567),(20.950173,-26.816036),(20.907695,-26.800017),(20.851884,-26.806528),(20.826046,-26.818827),(20.779434,-26.848076),(20.714942,-26.875051),(20.693548,-26.889004),(20.690757,-26.891794),(20.685693,-26.881769),(20.675461,-26.85004),(20.665643,-26.839084),(20.650553,-26.829679),(20.644869,-26.824511),(20.638667,-26.816967),(20.624818,-26.789371),(20.61469,-26.753198),(20.609212,-26.716198),(20.608902,-26.686122),(20.630709,-26.618322),(20.632363,-26.595275),(20.627712,-26.580805),(20.611486,-26.559928),(20.605284,-26.547732),(20.602287,-26.522204),(20.605284,-26.493265),(20.618204,-26.439729),(20.622544,-26.427533),(20.652103,-26.407793),(20.665953,-26.391773),(20.695512,-26.341957),(20.753286,-26.276224),(20.77623,-26.240568),(20.79473,-26.201914),(20.837932,-26.146827),(20.841446,-26.131324),(20.803929,-26.071276),(20.800518,-26.052466),(20.802792,-25.980532),(20.79411,-25.893922),(20.767135,-25.834391),(20.766928,-25.83067),(20.755766,-25.818991),(20.749978,-25.818475),(20.740057,-25.823126),(20.726517,-25.827363),(20.727137,-25.818165),(20.737783,-25.798941),(20.716699,-25.732588),(20.70688,-25.714812),(20.696545,-25.70706),(20.671017,-25.695485),(20.662852,-25.685253),(20.662749,-25.674918),(20.67143,-25.653317),(20.67081,-25.642258),(20.663059,-25.636264),(20.65138,-25.63461),(20.641045,-25.631199),(20.637944,-25.620347),(20.643318,-25.613216),(20.665229,-25.60102),(20.67143,-25.591202),(20.663369,-25.564743),(20.618514,-25.528466),(20.620374,-25.500561),(20.626885,-25.484748),(20.656547,-25.467798),(20.643525,-25.45736),(20.63443,-25.45767),(20.625645,-25.462734),(20.61655,-25.466145),(20.606628,-25.462011),(20.605905,-25.451779),(20.611382,-25.439376),(20.612002,-25.431005),(20.596913,-25.432865),(20.593606,-25.413228),(20.588025,-25.40403),(20.558776,-25.392041),(20.542239,-25.382222),(20.535831,-25.371163),(20.529217,-25.340054),(20.525083,-25.332199),(20.514644,-25.31928),(20.51051,-25.312252),(20.510407,-25.304708),(20.514851,-25.299126),(20.518571,-25.293029),(20.516401,-25.283624),(20.50989,-25.277526),(20.491803,-25.269051),(20.485498,-25.26316),(20.483535,-25.256648),(20.481674,-25.2305),(20.462451,-25.223679),(20.443847,-25.213344),(20.434442,-25.199804),(20.443227,-25.183061),(20.444777,-25.168385),(20.433925,-25.146784),(20.406847,-25.10782),(20.375531,-25.046119),(20.364886,-25.0332),(20.235695,-24.936048),(20.159317,-24.893673),(20.149085,-24.890986),(20.128414,-24.889746),(20.118906,-24.887369),(20.107847,-24.880341),(20.081079,-24.852642),(20.029299,-24.815228),(20.010489,-24.788047),(19.992919,-24.775851),(19.986408,-24.768823),(19.981447,-24.752493),(19.981343,-24.580411),(19.981137,-24.408431),(19.980826,-24.236556),(19.980723,-24.064473),(19.980516,-23.892494),(19.980483,-23.864489),(19.98031,-23.720567),(19.980103,-23.548587),(19.979896,-23.376505),(19.979855,-23.308551),(19.979793,-23.204526),(19.979586,-23.032546),(19.979276,-22.860671),(19.979173,-22.688588),(19.978966,-22.538106),(19.978863,-22.387625),(19.978656,-22.237246),(19.978449,-22.086764),(19.978346,-22.000671),(20.21244,-22.000671),(20.446534,-22.000671),(20.680629,-22.000671),(20.914723,-22.000671),(20.97198,-22.000671),(20.984796,-21.963981),(20.984693,-21.922847),(20.984486,-21.865176),(20.984279,-21.807608),(20.984073,-21.750041),(20.983866,-21.69237),(20.983659,-21.634699),(20.983453,-21.577028),(20.983143,-21.519357),(20.983039,-21.46179),(20.982832,-21.404119),(20.982626,-21.346448),(20.982419,-21.28888),(20.982212,-21.231209),(20.982109,-21.173642),(20.981902,-21.116074),(20.981592,-21.058403),(20.981489,-21.000733),(20.981486,-20.999958),(20.981075,-20.875779),(20.980662,-20.750722),(20.980249,-20.625768),(20.979835,-20.500711),(20.979422,-20.375758),(20.97936,-20.351028),(20.979112,-20.250804),(20.978698,-20.125851),(20.978285,-20.000794),(20.977975,-19.87584),(20.977561,-19.750783),(20.977045,-19.625829),(20.976735,-19.500876),(20.976321,-19.375819),(20.975804,-19.250865),(20.975609,-19.172106),(20.975494,-19.125912),(20.975081,-19.000958),(20.975081,-18.96003),(20.975081,-18.919206),(20.975081,-18.878381),(20.975081,-18.83766),(20.975081,-18.796836),(20.975081,-18.756012),(20.975081,-18.715187),(20.975081,-18.674363),(20.975081,-18.633539),(20.975081,-18.592714),(20.975081,-18.551993),(20.975081,-18.511065),(20.975081,-18.470138),(20.975081,-18.429313),(20.975081,-18.388592),(20.975081,-18.347768),(20.975081,-18.319346),(20.993436,-18.318612),(21.024174,-18.317382),(21.080604,-18.315212),(21.136932,-18.312938),(21.193466,-18.310768),(21.249896,-18.308494),(21.296818,-18.306633),(21.343947,-18.304773),(21.39087,-18.302913),(21.437895,-18.301052),(21.456809,-18.300226),(21.475722,-18.299502),(21.492879,-18.296401),(21.509829,-18.293198),(21.526985,-18.289994),(21.544039,-18.28679),(21.628478,-18.271183),(21.71271,-18.255577),(21.79715,-18.239867),(21.881486,-18.224158),(21.966028,-18.208552),(22.050261,-18.192842),(22.134597,-18.177236),(22.219036,-18.161526),(22.303475,-18.145816),(22.387811,-18.13021),(22.472147,-18.1145),(22.556483,-18.098791),(22.640922,-18.083185),(22.725258,-18.067475),(22.809698,-18.051869),(22.894034,-18.036159),(22.981367,-18.020036),(23.099602,-18.010217),(23.185799,-18.003086),(23.254942,-17.997402),(23.292769,-17.998952),(23.305688,-18.005463),(23.311476,-18.009804),(23.312819,-18.016522),(23.312716,-18.029958),(23.31592,-18.037089),(23.323258,-18.039156),(23.330596,-18.039983),(23.3338,-18.04329),(23.33256,-18.067061),(23.3338,-18.073986),(23.336591,-18.07936),(23.348063,-18.09445),(23.359535,-18.119151),(23.389714,-18.153258),(23.395812,-18.163386),(23.396329,-18.169381),(23.394468,-18.186227),(23.395812,-18.191395),(23.40129,-18.194289),(23.410281,-18.197389),(23.418859,-18.198423),(23.429401,-18.188501),(23.444284,-18.200697),(23.458754,-18.217647),(23.464128,-18.225501),(23.477771,-18.230876),(23.49131,-18.23315),(23.501542,-18.23749),(23.505676,-18.249376),(23.511257,-18.260331),(23.521696,-18.268186),(23.527277,-18.277695),(23.518802,-18.293714),(23.551461,-18.327511),(23.560763,-18.348491),(23.546604,-18.369472),(23.555492,-18.383115),(23.571305,-18.426006),(23.57916,-18.467864),(23.592182,-18.478199),(23.609856,-18.477682),(23.645409,-18.466004),(23.649853,-18.46342),(23.656468,-18.458252),(23.680136,-18.431484),(23.700909,-18.42797),(23.715792,-18.419081),(23.809843,-18.321723),(23.825553,-18.317072),(23.837232,-18.305807),(23.855215,-18.280072),(23.867514,-18.269426),(23.89697,-18.250203),(23.912886,-18.235733),(23.915987,-18.201213),(23.950817,-18.177649),(23.956604,-18.176615),(23.961979,-18.177856),(23.966733,-18.180646),(23.971177,-18.18385),(23.974898,-18.177029),(23.979652,-18.171861),(23.991744,-18.163386),(24.02027,-18.151604),(24.028125,-18.145816),(24.05696,-18.119048),(24.065125,-18.115224),(24.101609,-18.108816),(24.135095,-18.085458),(24.183051,-18.029441),(24.218294,-18.012595),(24.238241,-18.009907),(24.259222,-18.012595),(24.270074,-18.015798),(24.287437,-18.02448),(24.296429,-18.026237),(24.305834,-18.019416),(24.334256,-17.971563),(24.350586,-17.95606),(24.365262,-17.950789),(24.399471,-17.95234),(24.421589,-17.956474),(24.433888,-17.967223),(24.451045,-17.998952),(24.458486,-18.005773),(24.465101,-18.008667),(24.469751,-18.014455),(24.471508,-18.029958),(24.505615,-18.060344),(24.518431,-18.057346),(24.564423,-18.052799),(24.574551,-18.050422),(24.577755,-18.044427),(24.591811,-18.028407),(24.595015,-18.022826),(24.598632,-18.020759),(24.649172,-17.962778),(24.664055,-17.949859),(24.698471,-17.928879),(24.725343,-17.895909),(24.730717,-17.891878),(24.738159,-17.887641),(24.74684,-17.88423),(24.756039,-17.882783),(24.764514,-17.879683),(24.770715,-17.865523),(24.776916,-17.862319),(24.79738,-17.858082),(24.820841,-17.839272),(24.838101,-17.835034),(24.857428,-17.833587),(24.931119,-17.81054),(24.93763,-17.807129),(24.945175,-17.799998),(24.948585,-17.79328),(24.953339,-17.788422),(24.964295,-17.786665),(24.958094,-17.800928),(24.968636,-17.807646),(24.975147,-17.816327),(24.983312,-17.820462),(24.998505,-17.81395),(25.007083,-17.825733),(25.019692,-17.823769),(25.047494,-17.807129),(25.057002,-17.827696),(25.087905,-17.826766),(25.120874,-17.813537),(25.153947,-17.781808),(25.194152,-17.782324),(25.259781,-17.794107)] +Central African Republic [(22.55576,10.978969),(22.57705,10.985119),(22.600822,10.987806),(22.60909,10.985222),(22.62821,10.976127),(22.638339,10.974137),(22.673169,10.975068),(22.682677,10.974137),(22.719884,10.964655),(22.745102,10.943803),(22.805977,10.924502),(22.861064,10.919154),(22.863234,10.891817),(23.005551,10.686817),(23.109421,10.614495),(23.291219,10.439726),(23.457617,10.173747),(23.624015,9.907768),(23.644789,9.863068),(23.674038,9.69034),(23.669077,9.652022),(23.655538,9.622463),(23.618537,9.566084),(23.606135,9.537171),(23.606755,9.526241),(23.61647,9.501463),(23.618537,9.488311),(23.617194,9.457176),(23.619984,9.447719),(23.627529,9.435084),(23.63497,9.435394),(23.640861,9.43312),(23.646339,9.425033),(23.646856,9.418393),(23.621845,9.34062),(23.620501,9.322869),(23.630733,9.292173),(23.63218,9.277574),(23.623291,9.265637),(23.610062,9.255457),(23.571408,9.207294),(23.549498,9.185254),(23.537922,9.178149),(23.521799,9.175358),(23.48945,9.176702),(23.474257,9.170682),(23.462821,9.153725),(23.45772,9.146161),(23.435706,9.018934),(23.43829,8.994543),(23.451416,8.974182),(23.478081,8.958912),(23.505469,8.961082),(23.542573,8.997281),(23.560143,8.996455),(23.567481,8.974828),(23.565931,8.940024),(23.553632,8.883154),(23.536682,8.85561),(23.495444,8.809438),(23.482318,8.783393),(23.481801,8.759363),(23.49007,8.732595),(23.505262,8.710736),(23.525726,8.701485),(23.540506,8.704793),(23.56407,8.722699),(23.578023,8.730476),(23.59642,8.734145),(23.61337,8.732233),(23.629079,8.725593),(23.644065,8.715154),(23.657088,8.710012),(23.689127,8.710684),(23.72127,8.702002),(23.737496,8.70686),(23.768916,8.721252),(23.803436,8.72213),(23.866687,8.70779),(23.922291,8.713449),(23.962082,8.697015),(23.981306,8.694173),(24.009624,8.698876),(24.114011,8.681642),(24.170328,8.689327),(24.180467,8.690711),(24.217674,8.691512),(24.235761,8.682003),(24.233487,8.667767),(24.21509,8.64136),(24.211266,8.627071),(24.218397,8.613041),(24.245579,8.591802),(24.25054,8.579632),(24.243719,8.570176),(24.203204,8.543459),(24.193179,8.532426),(24.137162,8.438866),(24.125173,8.404889),(24.121556,8.372307),(24.131374,8.343058),(24.152872,8.317891),(24.17995,8.297712),(24.206615,8.283268),(24.222428,8.277196),(24.257051,8.269186),(24.263186,8.268505),(24.281029,8.266525),(24.295498,8.266525),(24.302733,8.26544),(24.310278,8.261564),(24.326814,8.248567),(24.332085,8.245725),(24.396578,8.267817),(24.431097,8.271408),(24.454869,8.248671),(24.458899,8.239757),(24.464274,8.233194),(24.471508,8.22893),(24.481327,8.226657),(24.51285,8.207149),(24.544682,8.206115),(24.614859,8.217148),(24.670876,8.206839),(24.69041,8.206632),(24.710564,8.204307),(24.742293,8.18684),(24.800171,8.180277),(24.832107,8.16573),(24.917993,8.087027),(24.927811,8.070956),(24.930085,8.035454),(24.950549,8.014396),(24.952616,7.996567),(24.958094,7.989178),(24.964812,7.982615),(24.972666,7.976982),(24.981245,7.972331),(25.029304,7.918846),(25.059173,7.896108),(25.089559,7.884895),(25.103408,7.885773),(25.134414,7.892543),(25.148573,7.892594),(25.173171,7.888564),(25.180509,7.884016),(25.18547,7.877918),(25.191568,7.872389),(25.216889,7.864069),(25.229705,7.851615),(25.23942,7.835957),(25.249652,7.804331),(25.264535,7.777718),(25.269909,7.760768),(25.270633,7.746143),(25.266809,7.703097),(25.270633,7.688162),(25.276421,7.674261),(25.279418,7.659482),(25.274974,7.641964),(25.252546,7.62243),(25.186504,7.600106),(25.165213,7.5799),(25.164593,7.567343),(25.169037,7.551168),(25.190431,7.501197),(25.249962,7.469984),(25.263295,7.461044),(25.269599,7.454223),(25.279211,7.438358),(25.285102,7.431589),(25.292957,7.427196),(25.3097,7.422029),(25.316211,7.417223),(25.32417,7.402908),(25.330577,7.374125),(25.335952,7.359604),(25.346804,7.345031),(25.360033,7.335574),(25.416154,7.307772),(25.455118,7.278213),(25.481163,7.266173),(25.500335,7.272787),(25.516768,7.269945),(25.53165,7.260695),(25.576609,7.219819),(25.592422,7.211241),(25.65402,7.195376),(25.672727,7.187831),(25.697015,7.168607),(25.705077,7.166385),(25.724507,7.166695),(25.734429,7.162406),(25.750242,7.146542),(25.7613,7.143751),(25.786209,7.142666),(25.791583,7.134398),(25.791686,7.121117),(25.800781,7.104942),(25.815767,7.099774),(25.860726,7.095537),(25.877469,7.087734),(25.881707,7.079827),(25.884084,7.061069),(25.888735,7.05187),(25.920257,7.034145),(25.930386,7.03151),(25.950436,7.028564),(25.960461,7.024482),(25.966249,7.017454),(25.966766,7.009857),(25.969453,7.003553),(25.981132,7.000297),(26.026091,6.99668),(26.032292,6.974097),(26.035806,6.922266),(26.045418,6.899683),(26.050585,6.896686),(26.05689,6.89741),(26.063401,6.899063),(26.069189,6.899063),(26.073633,6.895136),(26.073116,6.88971),(26.071152,6.88356),(26.071566,6.877462),(26.0757,6.864647),(26.077354,6.85333),(26.080971,6.842348),(26.091203,6.830334),(26.113734,6.816458),(26.131821,6.81173),(26.147634,6.804702),(26.178743,6.765919),(26.219464,6.737523),(26.236207,6.72003),(26.270623,6.702486),(26.329741,6.680575),(26.378007,6.65329),(26.379224,6.631362),(26.379867,6.619778),(26.372323,6.609804),(26.356096,6.579496),(26.324367,6.537199),(26.30504,6.496917),(26.296462,6.489527),(26.286436,6.484179),(26.277031,6.477358),(26.27021,6.465653),(26.289124,6.459426),(26.290674,6.444672),(26.285093,6.425888),(26.282819,6.407853),(26.28964,6.387208),(26.300699,6.377829),(26.315789,6.371576),(26.335219,6.360595),(26.351755,6.344368),(26.375837,6.312587),(26.394647,6.300547),(26.436195,6.29171),(26.452008,6.28029),(26.455315,6.254451),(26.455625,6.230474),(26.464927,6.224402),(26.4795,6.225073),(26.495829,6.221146),(26.508955,6.205462),(26.509472,6.186394),(26.500067,6.167971),(26.48353,6.154457),(26.46534,6.144303),(26.4456,6.130221),(26.42927,6.113091),(26.421312,6.09366),(26.424826,6.072447),(26.440639,6.076995),(26.48105,6.104951),(26.498827,6.099836),(26.509885,6.082679),(26.51805,6.061156),(26.527972,6.043172),(26.543578,6.030847),(26.602179,6.010616),(26.634322,6.006482),(26.705016,6.009789),(26.776329,5.981884),(26.794364,5.970489),(26.805061,5.957183),(26.810849,5.912379),(26.81891,5.894628),(26.842165,5.884267),(26.865316,5.885973),(26.882059,5.891941),(26.894255,5.889667),(26.903763,5.866982),(26.916475,5.849644),(26.937456,5.848507),(26.981071,5.859204),(26.99182,5.847706),(27.003499,5.819284),(27.021999,5.805099),(27.029543,5.78988),(27.036055,5.785126),(27.045356,5.784919),(27.063547,5.790862),(27.072745,5.791224),(27.11481,5.775282),(27.123801,5.768745),(27.130933,5.752131),(27.131449,5.741459),(27.136307,5.734018),(27.156254,5.727481),(27.170413,5.72035),(27.182351,5.707456),(27.190774,5.691824),(27.193823,5.676321),(27.194288,5.667304),(27.196407,5.661464),(27.201109,5.656968),(27.218369,5.645315),(27.219196,5.639993),(27.216716,5.633456),(27.215165,5.616144),(27.210669,5.601623),(27.211341,5.594879),(27.217336,5.585397),(27.222607,5.584363),(27.227309,5.586714),(27.231082,5.587593),(27.234596,5.588833),(27.240073,5.591985),(27.247515,5.592605),(27.257127,5.586068),(27.261054,5.577593),(27.258884,5.559972),(27.260744,5.550257),(27.220126,5.440883),(27.218059,5.42551),(27.220126,5.413082),(27.228239,5.387605),(27.233665,5.33828),(27.2378,5.32319),(27.264465,5.260145),(27.280898,5.23056),(27.30131,5.205187),(27.358516,5.166766),(27.385801,5.143847),(27.402131,5.104496),(27.431173,5.083618),(27.441301,5.070725),(27.414843,5.080725),(27.405335,5.082843),(27.391382,5.092223),(27.380323,5.094393),(27.361203,5.095478),(27.351384,5.097339),(27.342754,5.100594),(27.328647,5.1108),(27.315728,5.122402),(27.301878,5.131988),(27.284412,5.135967),(27.262811,5.138447),(27.239712,5.144881),(27.157494,5.185421),(27.11636,5.200304),(27.073675,5.203327),(27.027476,5.189969),(26.991716,5.171288),(26.961641,5.151185),(26.933684,5.126587),(26.90397,5.094393),(26.899216,5.085996),(26.889604,5.062121),(26.884126,5.053388),(26.872654,5.041786),(26.867073,5.037549),(26.849296,5.039099),(26.848366,5.041373),(26.844955,5.046282),(26.839478,5.051166),(26.832656,5.053388),(26.826145,5.050752),(26.815706,5.040184),(26.808368,5.039099),(26.801857,5.044525),(26.760619,5.088114),(26.753695,5.092274),(26.739432,5.094393),(26.691683,5.094393),(26.681244,5.089277),(26.667602,5.078347),(26.657577,5.073257),(26.644037,5.078347),(26.635666,5.077624),(26.629671,5.067056),(26.62347,5.067056),(26.615512,5.078244),(26.598355,5.080621),(26.579855,5.074343),(26.568176,5.059641),(26.561355,5.067056),(26.554224,5.059847),(26.541511,5.053129),(26.528282,5.048091),(26.519807,5.045972),(26.502547,5.047471),(26.475159,5.057263),(26.462653,5.059641),(26.460689,5.066023),(26.441879,5.104289),(26.429373,5.113798),(26.414284,5.122712),(26.400125,5.133641),(26.390616,5.149015),(26.369429,5.140566),(26.362711,5.135967),(26.353306,5.147775),(26.336356,5.148602),(26.317339,5.146431),(26.291811,5.150979),(26.272484,5.159066),(26.253984,5.172321),(26.246646,5.189969),(26.242098,5.188057),(26.230729,5.185163),(26.226182,5.183147),(26.225665,5.199038),(26.226182,5.204257),(26.213573,5.199141),(26.207165,5.207694),(26.198276,5.238389),(26.195176,5.234772),(26.18453,5.225341),(26.18174,5.229579),(26.175332,5.233687),(26.170888,5.238389),(26.157349,5.232472),(26.150837,5.239966),(26.144223,5.251799),(26.12996,5.258879),(26.125103,5.248595),(26.119625,5.241542),(26.112494,5.238389),(26.104535,5.238596),(26.098438,5.239578),(26.093373,5.241438),(26.088412,5.244591),(26.09172,5.219062),(26.095234,5.211053),(26.086035,5.215238),(26.077147,5.216324),(26.070532,5.212241),(26.067845,5.200846),(26.062677,5.200123),(26.050999,5.200226),(26.037356,5.197953),(26.026917,5.189969),(26.013895,5.199244),(25.996635,5.219243),(25.98599,5.225341),(25.971934,5.227667),(25.962839,5.224514),(25.958394,5.214825),(25.958601,5.197384),(25.943202,5.204102),(25.925632,5.201777),(25.912506,5.190382),(25.910852,5.170099),(25.892972,5.185214),(25.883567,5.203534),(25.872405,5.217099),(25.849357,5.217874),(25.84605,5.211673),(25.836231,5.20002),(25.826103,5.194697),(25.818971,5.214567),(25.814217,5.22162),(25.811427,5.230922),(25.814631,5.244591),(25.810186,5.242679),(25.799438,5.240095),(25.794683,5.238389),(25.792306,5.262832),(25.778354,5.269137),(25.769259,5.265158),(25.781144,5.258879),(25.771739,5.245469),(25.757993,5.244436),(25.743731,5.250611),(25.732775,5.258879),(25.705077,5.289601),(25.691124,5.299807),(25.668903,5.306137),(25.667559,5.307248),(25.663115,5.30916),(25.655777,5.317764),(25.650093,5.320297),(25.637897,5.317971),(25.631076,5.311822),(25.623428,5.309935),(25.609165,5.320297),(25.609165,5.326524),(25.614229,5.329934),(25.617227,5.333552),(25.61981,5.337221),(25.622911,5.34076),(25.600483,5.34045),(25.592319,5.349184),(25.589011,5.362284),(25.58126,5.374919),(25.575059,5.374919),(25.561829,5.373006),(25.543743,5.37528),(25.532787,5.372231),(25.540849,5.354429),(25.528963,5.351897),(25.504469,5.342285),(25.49558,5.344533),(25.484935,5.355307),(25.481989,5.356858),(25.479922,5.353189),(25.435067,5.328694),(25.413363,5.323552),(25.39569,5.333965),(25.385354,5.321485),(25.370678,5.316834),(25.36365,5.310556),(25.376466,5.293011),(25.355899,5.286448),(25.343393,5.271927),(25.337192,5.251748),(25.335538,5.228442),(25.328924,5.216013),(25.316211,5.202242),(25.307736,5.185292),(25.314454,5.163252),(25.321482,5.159169),(25.341223,5.155604),(25.348561,5.149015),(25.349284,5.141677),(25.343807,5.121885),(25.34236,5.111472),(25.339156,5.105168),(25.324996,5.088114),(25.321896,5.077004),(25.320966,5.052251),(25.316832,5.042251),(25.307633,5.032278),(25.292337,5.028273),(25.248515,5.024139),(25.239317,5.015535),(25.227535,5.009566),(25.163663,5.005639),(25.154568,5.009308),(25.147643,5.01414),(25.140201,5.017964),(25.129453,5.018635),(25.121701,5.008636),(25.11426,5.001841),(25.105268,4.998766),(25.100927,4.994554),(25.090489,4.974478),(25.084804,4.954221),(25.076123,4.951844),(25.040569,4.962101),(25.006463,4.980937),(24.969359,4.991402),(24.958094,4.99135),(24.950859,4.987681),(24.932359,4.974426),(24.927088,4.971481),(24.90435,4.966804),(24.868177,4.944376),(24.848333,4.936728),(24.836861,4.93771),(24.827662,4.941922),(24.819498,4.94448),(24.811023,4.940449),(24.800067,4.928899),(24.789422,4.919856),(24.77826,4.918538),(24.766374,4.929881),(24.749838,4.918745),(24.730614,4.917505),(24.664365,4.924403),(24.654236,4.929416),(24.65744,4.939777),(24.670773,4.957218),(24.656923,4.967269),(24.627468,4.976907),(24.615479,4.985097),(24.610001,4.996725),(24.610105,5.016723),(24.601216,5.026103),(24.588607,5.031064),(24.563389,5.034888),(24.553467,5.039099),(24.547369,5.046489),(24.538688,5.065558),(24.533003,5.073257),(24.513676,5.087236),(24.487218,5.100801),(24.480844,5.102335),(24.459623,5.107441),(24.436679,5.100594),(24.433061,5.089329),(24.433475,5.075531),(24.430684,5.067418),(24.416938,5.073257),(24.41146,5.081861),(24.401642,5.111472),(24.396371,5.122298),(24.382522,5.107855),(24.367846,5.084549),(24.361231,5.062948),(24.37198,5.053388),(24.396888,5.048194),(24.398645,5.036024),(24.386139,5.022356),(24.368466,5.012434),(24.296635,5.003262),(24.286507,4.995071),(24.284646,4.992435),(24.272968,4.964013),(24.26966,4.952464),(24.269557,4.943188),(24.267697,4.935721),(24.259222,4.929881),(24.25302,4.929881),(24.246199,4.954066),(24.229766,4.961171),(24.209612,4.956184),(24.190905,4.94417),(24.162897,4.907789),(24.152768,4.902596),(24.139229,4.905438),(24.119902,4.9189),(24.10843,4.92306),(24.08962,4.920218),(24.072463,4.91027),(24.046935,4.888928),(23.995775,4.865053),(23.977998,4.854149),(23.963116,4.868696),(23.957121,4.870815),(23.950817,4.867792),(23.946476,4.861642),(23.943169,4.851695),(23.942755,4.840507),(23.947406,4.830585),(23.948336,4.817692),(23.924358,4.817795),(23.88188,4.82689),(23.874749,4.824978),(23.864414,4.81609),(23.855215,4.813222),(23.847877,4.813997),(23.82824,4.819345),(23.816665,4.820611),(23.798475,4.814746),(23.760027,4.787435),(23.73791,4.779063),(23.692848,4.773405),(23.672694,4.767204),(23.63404,4.745138),(23.588048,4.73395),(23.566551,4.724441),(23.506089,4.676434),(23.488416,4.669845),(23.465058,4.66721),(23.448315,4.659407),(23.437153,4.646565),(23.430022,4.62884),(23.428265,4.617342),(23.428368,4.608609),(23.427438,4.601348),(23.42258,4.594062),(23.414519,4.590832),(23.396019,4.591607),(23.38837,4.587266),(23.371214,4.597266),(23.353954,4.60357),(23.335867,4.6068),(23.316437,4.60773),(23.313026,4.610211),(23.301967,4.621709),(23.29959,4.625119),(23.295146,4.6276),(23.273132,4.632018),(23.264864,4.635067),(23.251841,4.662972),(23.224246,4.680051),(23.220835,4.683514),(23.20864,4.690542),(23.183732,4.725268),(23.168746,4.73811),(23.12389,4.715631),(23.099396,4.711652),(23.077382,4.721057),(23.066633,4.730178),(23.055161,4.7378),(23.042758,4.742967),(23.029323,4.744931),(23.017334,4.750512),(23.011132,4.763638),(23.007205,4.778443),(22.99625,4.799501),(22.985708,4.826425),(22.977439,4.834306),(22.965037,4.835287),(22.953048,4.830792),(22.941473,4.82472),(22.92969,4.820611),(22.915221,4.821154),(22.905919,4.824203),(22.898374,4.823583),(22.888763,4.813222),(22.882872,4.800742),(22.882355,4.788494),(22.886799,4.776686),(22.895584,4.765395),(22.887316,4.755499),(22.865302,4.738678),(22.853829,4.711264),(22.837293,4.714235),(22.818069,4.724596),(22.802876,4.730643),(22.78603,4.724648),(22.776418,4.710101),(22.765153,4.676021),(22.757401,4.660802),(22.74872,4.64827),(22.737867,4.637754),(22.723605,4.62884),(22.723811,4.617032),(22.729806,4.596749),(22.73115,4.587266),(22.728669,4.58029),(22.718954,4.562772),(22.716783,4.556519),(22.713683,4.551222),(22.700144,4.541068),(22.697043,4.535745),(22.697146,4.512025),(22.695079,4.501483),(22.689498,4.491665),(22.675649,4.48474),(22.654358,4.482828),(22.61033,4.484224),(22.59245,4.473707),(22.586972,4.449394),(22.589039,4.421953),(22.594,4.402316),(22.61126,4.381853),(22.613741,4.374359),(22.609297,4.363352),(22.599891,4.352552),(22.588006,4.34418),(22.576534,4.340847),(22.568575,4.331546),(22.539327,4.278164),(22.53974,4.266924),(22.545734,4.245944),(22.546148,4.237184),(22.540464,4.227262),(22.52217,4.211346),(22.518243,4.206799),(22.510491,4.19127),(22.492714,4.174036),(22.457368,4.149076),(22.451532,4.146672),(22.43184,4.13856),(22.422641,4.134787),(22.303269,4.128716),(22.207254,4.150316),(22.184723,4.164605),(22.161882,4.173183),(22.15165,4.179462),(22.133047,4.19866),(22.127879,4.203078),(22.108449,4.209848),(22.057806,4.219537),(22.036613,4.229439),(22.00892,4.242378),(22.001478,4.244652),(21.989593,4.244238),(21.984528,4.242946),(21.980291,4.240621),(21.970783,4.237184),(21.949905,4.233464),(21.891614,4.237184),(21.86774,4.241551),(21.851927,4.25168),(21.838077,4.263255),(21.819887,4.271937),(21.810999,4.273177),(21.78206,4.271937),(21.771001,4.273487),(21.76604,4.277208),(21.76325,4.281678),(21.758496,4.285605),(21.737308,4.293382),(21.722942,4.295139),(21.688939,4.292452),(21.651112,4.295656),(21.634162,4.294209),(21.538147,4.244652),(21.527812,4.249251),(21.508072,4.249406),(21.49722,4.251473),(21.489882,4.256253),(21.48244,4.263126),(21.473138,4.269301),(21.460219,4.271937),(21.416915,4.270076),(21.397691,4.271627),(21.37485,4.278164),(21.358313,4.285553),(21.310358,4.316094),(21.3055,4.323148),(21.298886,4.330228),(21.288344,4.33338),(21.275321,4.332527),(21.265916,4.330073),(21.258371,4.32599),(21.250723,4.320358),(21.244625,4.313769),(21.239148,4.305604),(21.23243,4.297827),(21.223438,4.292452),(21.210932,4.291574),(21.202974,4.296638),(21.195739,4.302917),(21.185611,4.306069),(21.16556,4.307154),(21.158119,4.310203),(21.150057,4.326714),(21.137965,4.332682),(21.113574,4.340847),(21.103445,4.353275),(21.084222,4.388235),(21.076057,4.395469),(21.059624,4.398596),(20.963505,4.433736),(20.871521,4.453373),(20.832351,4.450686),(20.818708,4.443528),(20.807029,4.434252),(20.791836,4.426191),(20.767859,4.42278),(20.68838,4.42278),(20.603114,4.409732),(20.580273,4.415003),(20.559809,4.428361),(20.456713,4.524816),(20.452322,4.528924),(20.44209,4.550499),(20.447051,4.569671),(20.45718,4.58644),(20.463071,4.600935),(20.456456,4.621502),(20.44023,4.64411),(20.420593,4.662352),(20.403746,4.669845),(20.395478,4.677106),(20.373671,4.724441),(20.354034,4.755396),(20.338944,4.771906),(20.322511,4.779063),(20.301737,4.781647),(20.254815,4.797124),(20.236625,4.806349),(20.217194,4.822446),(20.171719,4.87836),(20.152599,4.890685),(20.08635,4.916264),(20.05462,4.937813),(20.031056,4.957993),(20.003977,4.974478),(19.915404,4.993107),(19.890909,5.002125),(19.880367,5.015535),(19.87551,5.031064),(19.858163,5.060305),(19.850188,5.073748),(19.838613,5.087546),(19.82466,5.096977),(19.779185,5.118164),(19.748799,5.124417),(19.728749,5.133848),(19.71955,5.135967),(19.605552,5.138292),(19.568759,5.15519),(19.548605,5.151366),(19.517082,5.135967),(19.496515,5.133796),(19.431506,5.135967),(19.408975,5.130386),(19.394196,5.116976),(19.373112,5.087546),(19.283815,5.032278),(19.236996,5.010781),(19.229761,5.002176),(19.214672,4.976131),(19.195655,4.950345),(19.179015,4.946418),(19.133023,4.946934),(19.116176,4.940449),(19.106741,4.931518),(19.08331,4.90934),(19.069047,4.891253),(19.057782,4.867792),(19.048997,4.836528),(19.044139,4.82689),(19.035768,4.818002),(19.02688,4.811516),(19.019748,4.8033),(19.011583,4.765033),(18.998044,4.750641),(18.980474,4.739402),(18.962284,4.724441),(18.928178,4.666435),(18.923837,4.662869),(18.90451,4.655867),(18.900169,4.652146),(18.897895,4.650647),(18.886526,4.621399),(18.85242,4.594062),(18.828235,4.559981),(18.776972,4.433451),(18.753304,4.400611),(18.721058,4.377357),(18.674343,4.361311),(18.654086,4.357229),(18.633932,4.355963),(18.614295,4.359813),(18.595795,4.371259),(18.576468,4.372757),(18.556831,4.354154),(18.541948,4.327851),(18.53709,4.306069),(18.545048,4.289016),(18.57254,4.265684),(18.578638,4.254858),(18.583909,4.235789),(18.619669,4.169566),(18.632692,4.130421),(18.646541,4.045982),(18.645301,3.982445),(18.64158,3.958261),(18.634552,3.93573),(18.613675,3.901468),(18.611711,3.879093),(18.612024,3.866611),(18.612848,3.833746),(18.593004,3.709775),(18.626387,3.476869),(18.582462,3.477386),(18.570267,3.489607),(18.55435,3.526375),(18.513422,3.592237),(18.497093,3.61146),(18.472081,3.632053),(18.459059,3.631382),(18.448,3.618023),(18.429707,3.600221),(18.420612,3.596371),(18.403662,3.597353),(18.392293,3.595854),(18.387849,3.591668),(18.383715,3.578),(18.379891,3.574382),(18.372863,3.574537),(18.361597,3.58017),(18.355603,3.581462),(18.275918,3.574382),(18.264859,3.574744),(18.255867,3.577225),(18.248529,3.574899),(18.242535,3.561127),(18.235403,3.530923),(18.231579,3.521156),(18.220004,3.503947),(18.202537,3.487333),(18.181556,3.477386),(18.159852,3.480305),(18.146727,3.494904),(18.134014,3.534824),(18.116444,3.552007),(18.082028,3.563453),(18.047094,3.563143),(18.013091,3.55397),(17.981879,3.538803),(17.969476,3.537511),(17.959865,3.541077),(17.924518,3.563453),(17.919247,3.565597),(17.913562,3.561334),(17.875322,3.542731),(17.856408,3.537305),(17.842146,3.540147),(17.835324,3.555831),(17.83057,3.575674),(17.821165,3.593994),(17.808349,3.608592),(17.793156,3.617506),(17.784475,3.61823),(17.765148,3.614354),(17.755949,3.614509),(17.749645,3.618075),(17.73993,3.629159),(17.733212,3.632208),(17.72608,3.631847),(17.714505,3.627506),(17.70913,3.626421),(17.627275,3.626317),(17.586761,3.632234),(17.550484,3.648151),(17.513484,3.679182),(17.508936,3.681766),(17.494983,3.683213),(17.490126,3.68714),(17.486198,3.700292),(17.481858,3.704762),(17.458913,3.708276),(17.442687,3.701274),(17.427494,3.690112),(17.414489,3.683415),(17.375714,3.663447),(17.355767,3.638435),(17.334373,3.618514),(17.298096,3.615904),(17.272258,3.62456),(17.259442,3.625904),(17.244973,3.620607),(17.231123,3.609109),(17.222959,3.598515),(17.213967,3.589291),(17.197224,3.58172),(17.182858,3.579602),(17.142757,3.580842),(17.129011,3.57707),(17.102139,3.566605),(17.088393,3.564435),(17.061418,3.56614),(17.052426,3.56397),(17.035787,3.556141),(17.028862,3.551541),(17.017596,3.5418),(17.009225,3.538131),(17.003127,3.537718),(16.989691,3.539475),(16.98194,3.537976),(16.968607,3.533481),(16.960546,3.538441),(16.953208,3.546891),(16.942252,3.553092),(16.932434,3.553919),(16.904735,3.550637),(16.895537,3.552368),(16.877243,3.559164),(16.867838,3.561541),(16.853162,3.560094),(16.851818,3.551903),(16.854609,3.541335),(16.852645,3.532809),(16.833008,3.522861),(16.811924,3.521672),(16.729552,3.542214),(16.709398,3.543712),(16.686351,3.542214),(16.639428,3.528597),(16.598501,3.501674),(16.567701,3.464389),(16.551682,3.419767),(16.542793,3.336154),(16.517782,3.273238),(16.517162,3.248692),(16.511477,3.227246),(16.477061,3.179394),(16.465485,3.156501),(16.464762,3.1318),(16.47272,3.110612),(16.483159,3.090148),(16.490807,3.067824),(16.484192,3.031909),(16.445538,2.95765),(16.448329,2.913467),(16.460525,2.894605),(16.474994,2.878378),(16.483779,2.860395),(16.479128,2.836314),(16.450603,2.775594),(16.427492,2.726493),(16.413706,2.697201),(16.371124,2.606922),(16.325649,2.510494),(16.293506,2.442074),(16.248031,2.345594),(16.196665,2.236454),(16.192841,2.239503),(16.179715,2.246996),(16.181265,2.256556),(16.18695,2.26932),(16.186536,2.277692),(16.182919,2.281154),(16.169069,2.289887),(16.165969,2.294796),(16.164729,2.314795),(16.162868,2.323839),(16.159251,2.332934),(16.152326,2.343269),(16.133413,2.364818),(16.120907,2.389571),(16.112949,2.410448),(16.111502,2.418562),(16.111502,2.455872),(16.107058,2.474165),(16.094345,2.497523),(16.090315,2.510494),(16.091245,2.532766),(16.106851,2.567028),(16.111502,2.5862),(16.108505,2.606612),(16.093105,2.641494),(16.090315,2.661906),(16.093725,2.67312),(16.101373,2.687847),(16.110468,2.701438),(16.0991,2.70397),(16.086284,2.704952),(16.072848,2.702834),(16.062616,2.703195),(16.059309,2.711825),(16.060032,2.72583),(16.056208,2.759833),(16.059929,2.786188),(16.086904,2.813163),(16.095172,2.836779),(16.092382,2.863289),(16.08246,2.885665),(16.070161,2.906594),(16.055381,2.93977),(16.034194,2.970621),(16.026236,2.978992),(16.015797,2.983488),(16.006082,2.983953),(15.995437,2.981473),(15.982001,2.976719),(15.977763,2.980956),(15.974249,2.985762),(15.971562,2.991188),(15.95823,3.041521),(15.950065,3.061003),(15.933425,3.081777),(15.913995,3.097952),(15.897768,3.103533),(15.854773,3.098985),(15.850949,3.100432),(15.840201,3.107408),(15.834206,3.108545),(15.829142,3.106633),(15.817566,3.100122),(15.813536,3.098985),(15.80103,3.100897),(15.793175,3.103274),(15.78563,3.107977),(15.7107,3.187455),(15.616855,3.286777),(15.517946,3.391603),(15.413973,3.50188),(15.329741,3.590996),(15.262306,3.662589),(15.25264,3.672852),(15.171301,3.758971),(15.084898,3.885836),(15.025987,4.026086),(15.043143,4.026138),(15.075183,4.017973),(15.091719,4.015854),(15.111253,4.019937),(15.150424,4.038514),(15.172438,4.043811),(15.192075,4.052234),(15.189801,4.063112),(15.177709,4.071458),(15.162413,4.073938),(15.14846,4.073938),(15.142569,4.08045),(15.139262,4.094583),(15.132854,4.108536),(15.117764,4.114324),(15.102571,4.112412),(15.091202,4.121791),(15.084484,4.148611),(15.082934,4.205507),(15.072806,4.265942),(15.063814,4.293434),(15.048518,4.321649),(15.013894,4.364257),(15.007383,4.37777),(15.000562,4.403195),(14.993947,4.413298),(14.982062,4.420481),(14.938344,4.435932),(14.779697,4.545047),(14.74373,4.57998),(14.717272,4.622019),(14.704249,4.669354),(14.697325,4.745215),(14.69071,4.762139),(14.691847,4.768702),(14.696084,4.779735),(14.700632,4.804282),(14.701459,4.814384),(14.686989,4.908875),(14.681615,4.920941),(14.675827,4.93076),(14.672107,4.940811),(14.674484,4.967579),(14.669833,4.977113),(14.663425,4.985717),(14.659498,4.997035),(14.660132,5.01144),(14.660324,5.015793),(14.667456,5.052768),(14.663012,5.091447),(14.663218,5.141832),(14.658877,5.164544),(14.651539,5.187514),(14.640481,5.208236),(14.624461,5.224049),(14.603584,5.234255),(14.560485,5.248595),(14.539712,5.261799),(14.523899,5.279679),(14.519868,5.290583),(14.528033,5.293011),(14.539608,5.303579),(14.548393,5.320503),(14.553974,5.338228),(14.555938,5.351328),(14.560796,5.355462),(14.570821,5.370939),(14.579296,5.387605),(14.579606,5.395382),(14.592835,5.400033),(14.597279,5.41148),(14.596246,5.440108),(14.599553,5.456645),(14.614126,5.48486),(14.617433,5.495299),(14.61888,5.525452),(14.617226,5.53788),(14.610612,5.553667),(14.596556,5.577232),(14.591491,5.590952),(14.590148,5.608289),(14.592835,5.62387),(14.610612,5.669138),(14.624358,5.723605),(14.631075,5.738049),(14.624047,5.758306),(14.617433,5.864966),(14.602964,5.883389),(14.598003,5.903491),(14.584773,5.923412),(14.572474,5.924187),(14.545396,5.907573),(14.530616,5.90592),(14.499197,5.909537),(14.482144,5.90964),(14.465711,5.920673),(14.458166,5.936409),(14.453825,5.953875),(14.446901,5.970024),(14.432328,5.98545),(14.417548,5.997258),(14.406076,6.01103),(14.397705,6.019169),(14.389436,6.031054),(14.387266,6.039038),(14.390263,6.045782),(14.397705,6.053947),(14.402459,6.054877),(14.412898,6.047022),(14.418169,6.047126),(14.422509,6.051363),(14.426023,6.059864),(14.429124,6.064179),(14.433568,6.073868),(14.432709,6.079123),(14.431811,6.084617),(14.430571,6.088079),(14.443903,6.100249),(14.467054,6.122599),(14.482144,6.127069),(14.510979,6.155336),(14.525966,6.174069),(14.534957,6.190088),(14.576402,6.189778),(14.719029,6.257862),(14.734842,6.270445),(14.772255,6.318323),(14.782384,6.336772),(14.784658,6.347805),(14.784348,6.358683),(14.780007,6.382221),(14.782177,6.393616),(14.807292,6.4278),(14.921874,6.686414),(14.932452,6.710289),(14.946095,6.72574),(14.962321,6.736696),(15.022369,6.766539),(15.034565,6.776771),(15.042213,6.790775),(15.05906,6.836276),(15.080247,6.878083),(15.113217,6.964692),(15.128926,7.026497),(15.136161,7.045308),(15.147013,7.061844),(15.156108,7.067787),(15.179052,7.07838),(15.187527,7.088612),(15.190214,7.098793),(15.185357,7.156877),(15.186597,7.166334),(15.191248,7.177341),(15.205097,7.200233),(15.223908,7.247517),(15.246564,7.266731),(15.261321,7.279247),(15.338216,7.32219),(15.385345,7.358363),(15.389169,7.364151),(15.397437,7.380739),(15.403225,7.386372),(15.409633,7.387664),(15.428443,7.388801),(15.432784,7.389731),(15.434954,7.402908),(15.415524,7.42084),(15.419451,7.43655),(15.473298,7.509103),(15.481049,7.523263),(15.515569,7.512204),(15.55195,7.509879),(15.624813,7.519749),(15.668532,7.516287),(15.720001,7.468641),(15.758345,7.455567),(15.793899,7.457996),(15.92526,7.488175),(15.94314,7.495306),(15.975696,7.515201),(15.990372,7.529412),(16.012283,7.560315),(16.026339,7.574888),(16.042979,7.583931),(16.0652,7.591217),(16.128762,7.599486),(16.162662,7.611113),(16.185606,7.610751),(16.207207,7.613542),(16.227257,7.625582),(16.26188,7.651885),(16.282758,7.660102),(16.370814,7.672504),(16.38301,7.680669),(16.387144,7.694674),(16.387041,7.762628),(16.392208,7.783609),(16.407401,7.796063),(16.41815,7.795856),(16.427245,7.791464),(16.437373,7.788363),(16.450913,7.792084),(16.457217,7.799628),(16.469413,7.825828),(16.475717,7.835802),(16.491737,7.849238),(16.509204,7.858281),(16.548685,7.870012),(16.550131,7.861692),(16.550752,7.8527),(16.550235,7.843502),(16.54486,7.813013),(16.549305,7.794719),(16.560157,7.779733),(16.576383,7.767796),(16.586822,7.763558),(16.596434,7.761129),(16.605219,7.757202),(16.613073,7.74821),(16.618138,7.734309),(16.616174,7.723871),(16.611833,7.713897),(16.609869,7.701598),(16.61421,7.679584),(16.624546,7.66868),(16.6632,7.657415),(16.686867,7.645788),(16.709812,7.627753),(16.746709,7.586566),(16.768619,7.550238),(16.782365,7.541143),(16.805516,7.543675),(16.812854,7.547706),(16.815071,7.549544),(16.836729,7.567498),(16.839623,7.567446),(16.850372,7.565896),(16.853886,7.567498),(16.855849,7.575404),(16.852439,7.580262),(16.848098,7.584706),(16.847168,7.591579),(16.854816,7.611475),(16.865461,7.624445),(16.880654,7.632869),(16.919618,7.644082),(16.962716,7.650697),(16.98194,7.648733),(16.988968,7.660774),(16.997546,7.666717),(17.008295,7.667647),(17.038991,7.662479),(17.042091,7.667027),(17.041058,7.675502),(17.045605,7.6847),(17.059351,7.696534),(17.079091,7.689919),(17.090254,7.683822),(17.095525,7.67824),(17.101932,7.677724),(17.116298,7.68687),(17.135522,7.705112),(17.170559,7.747539),(17.188645,7.764127),(17.196397,7.76516),(17.204562,7.763817),(17.211073,7.768312),(17.214484,7.786813),(17.220685,7.798181),(17.23379,7.810801),(17.234637,7.811617),(17.250864,7.822831),(17.385739,7.870477),(17.405997,7.883034),(17.419122,7.898227),(17.466355,7.884119),(17.478344,7.891819),(17.487232,7.914453),(17.503665,7.926236),(17.523819,7.93099),(17.559786,7.934711),(17.580766,7.940602),(17.59999,7.950369),(17.62066,7.978739),(17.639884,7.985043),(17.661795,7.986284),(17.679778,7.985198),(17.817238,7.962099),(17.858785,7.960445),(17.897853,7.967473),(17.977228,7.997187),(18.070452,8.019202),(18.508255,8.030674),(18.589283,8.047882),(18.617912,8.090127),(18.618636,8.138652),(18.638583,8.177642),(18.672586,8.20751),(18.715064,8.228672),(18.773768,8.248619),(18.791235,8.257378),(18.813042,8.276421),(18.8549,8.339802),(18.887457,8.370963),(18.901306,8.388636),(18.910401,8.412976),(18.920529,8.432122),(19.020472,8.545578),(19.061296,8.625624),(19.072261,8.631872),(19.081657,8.637226),(19.091475,8.652858),(19.124135,8.675079),(19.103877,8.698049),(19.073492,8.720528),(19.057782,8.729701),(19.048687,8.745669),(18.929108,8.796544),(18.917325,8.805148),(18.912468,8.818403),(18.909677,8.835327),(18.902959,8.84481),(18.886526,8.835844),(18.869783,8.849409),(18.86968,8.864111),(18.892727,8.897933),(18.901409,8.89398),(18.910608,8.894239),(18.917739,8.898812),(18.920736,8.907855),(18.922907,8.918216),(18.928591,8.921679),(18.936446,8.923358),(18.952052,8.931988),(18.971896,8.938215),(18.975927,8.941988),(18.97851,8.949455),(18.984815,8.956431),(18.999491,8.969635),(19.021919,8.985215),(19.060676,9.00418),(19.10057,9.015265),(19.126718,9.007177),(19.133643,9.007177),(19.142118,9.008676),(19.168783,9.002216),(19.174571,9.003767),(19.179635,9.015265),(19.192037,9.020174),(19.232862,9.022293),(19.253429,9.027951),(19.263248,9.028261),(19.275236,9.021983),(19.285778,9.01281),(19.295494,9.009503),(19.304795,9.020846),(19.316268,9.01312),(19.333321,9.006557),(19.352234,9.002061),(19.369391,9.000382),(19.38262,9.003198),(19.420964,9.017435),(19.430162,9.012862),(19.506644,9.013999),(19.511811,9.012293),(19.515842,9.009451),(19.52132,9.008831),(19.530828,9.013999),(19.553772,9.013327),(19.583125,9.025342),(19.613614,9.031672),(19.640072,9.013999),(19.656402,9.021259),(19.700017,9.020587),(19.709008,9.024567),(19.713969,9.02914),(19.738154,9.039372),(19.746836,9.04131),(19.758411,9.041982),(19.784663,9.048751),(19.80554,9.051128),(19.889463,9.046374),(19.902175,9.0518),(19.914474,9.069267),(19.928737,9.062575),(19.932091,9.063331),(19.943413,9.065882),(19.969044,9.082883),(19.976486,9.084175),(19.985477,9.083193),(19.993022,9.084589),(19.996329,9.092831),(19.997156,9.098619),(19.999533,9.104303),(20.002944,9.108515),(20.006871,9.11022),(20.014416,9.106345),(20.01793,9.091048),(20.024338,9.089756),(20.030332,9.093865),(20.029919,9.098981),(20.028369,9.104562),(20.031159,9.11022),(20.060512,9.134353),(20.068676,9.138126),(20.076945,9.13673),(20.090587,9.131123),(20.099372,9.13071),(20.100509,9.134146),(20.099579,9.141174),(20.101026,9.148073),(20.109604,9.151174),(20.117149,9.145748),(20.125727,9.133785),(20.137613,9.121822),(20.154563,9.116421),(20.169549,9.120891),(20.197971,9.140503),(20.212647,9.144973),(20.222982,9.14195),(20.234454,9.13456),(20.256985,9.116421),(20.276829,9.120736),(20.359408,9.116421),(20.378322,9.120065),(20.384419,9.123579),(20.40292,9.136989),(20.412428,9.142053),(20.423073,9.143241),(20.435166,9.138126),(20.455423,9.159313),(20.467618,9.184143),(20.481778,9.204659),(20.507203,9.213263),(20.51299,9.223883),(20.502655,9.247421),(20.496144,9.270882),(20.514231,9.281502),(20.526426,9.283621),(20.533661,9.289641),(20.537278,9.299201),(20.538208,9.311939),(20.541826,9.321629),(20.550921,9.320259),(20.572315,9.308218),(20.573555,9.309149),(20.592262,9.308063),(20.592882,9.308218),(20.609729,9.302792),(20.616653,9.302017),(20.667916,9.302017),(20.654894,9.342971),(20.695822,9.363461),(20.740883,9.377129),(20.750495,9.384545),(20.757937,9.377129),(20.766618,9.38656),(20.771062,9.398058),(20.77654,9.407799),(20.788322,9.411881),(20.792353,9.414),(20.798244,9.423379),(20.801965,9.42555),(20.806719,9.423328),(20.81323,9.419116),(20.813884,9.418847),(20.820258,9.416222),(20.82615,9.418083),(20.832661,9.437255),(20.834314,9.462473),(20.841446,9.484409),(20.86377,9.493789),(20.874209,9.502496),(20.912656,9.544328),(20.921234,9.558978),(20.925058,9.569598),(20.934257,9.577065),(20.955961,9.589416),(20.960508,9.598123),(20.962265,9.606934),(20.96764,9.610603),(20.983143,9.603678),(20.981799,9.616778),(20.980145,9.619931),(20.975804,9.624168),(20.975804,9.630964),(20.989964,9.635615),(20.996062,9.648301),(20.996888,9.682175),(21.000092,9.697394),(21.014252,9.724472),(21.017352,9.743592),(21.019936,9.747933),(21.025621,9.753256),(21.032339,9.75801),(21.037816,9.760671),(21.039056,9.76217),(21.04009,9.764754),(21.042674,9.767079),(21.048358,9.768165),(21.052906,9.765891),(21.062207,9.756201),(21.065825,9.754496),(21.073163,9.757648),(21.080294,9.762609),(21.09311,9.77434),(21.097037,9.775373),(21.101585,9.774237),(21.105202,9.77403),(21.106753,9.778061),(21.105926,9.791884),(21.106753,9.79545),(21.121739,9.831907),(21.131971,9.849426),(21.187264,9.885134),(21.195429,9.887305),(21.198427,9.902988),(21.205661,9.916838),(21.256924,9.975749),(21.27129,9.987247),(21.28514,9.978591),(21.326067,9.962752),(21.339503,9.95991),(21.374333,9.973113),(21.406889,10.005566),(21.433348,10.046055),(21.485437,10.164316),(21.513239,10.200515),(21.544969,10.219997),(21.554477,10.218654),(21.566673,10.214494),(21.579282,10.212272),(21.589721,10.216613),(21.593441,10.214546),(21.625274,10.224493),(21.630648,10.227439),(21.65628,10.233666),(21.668889,10.249195),(21.67695,10.269168),(21.688939,10.288908),(21.697414,10.292422),(21.708886,10.293533),(21.718808,10.296634),(21.723046,10.305987),(21.722116,10.314178),(21.717775,10.328983),(21.716845,10.339809),(21.720462,10.360816),(21.751054,10.41182),(21.743613,10.418978),(21.742786,10.425773),(21.74444,10.432439),(21.744233,10.439106),(21.738032,10.44802),(21.720462,10.468018),(21.716845,10.47732),(21.714674,10.493702),(21.705476,10.53202),(21.703305,10.552406),(21.705476,10.571811),(21.714674,10.601395),(21.716845,10.621007),(21.722632,10.636716),(21.736482,10.646173),(21.753431,10.650721),(21.768418,10.651987),(21.774205,10.655165),(21.778753,10.66227),(21.784851,10.669324),(21.795393,10.672476),(21.803558,10.673665),(21.822575,10.678755),(21.83291,10.679944),(21.852754,10.670151),(21.863606,10.667929),(21.86836,10.676223),(21.872081,10.677592),(21.895025,10.699193),(21.925617,10.720122),(21.943084,10.728261),(22.003855,10.743273),(22.014604,10.754564),(22.004889,10.775519),(22.0114,10.789291),(22.018325,10.809884),(22.029487,10.828746),(22.048607,10.836988),(22.132426,10.828539),(22.148239,10.830761),(22.176351,10.816214),(22.189787,10.837298),(22.200639,10.868666),(22.229371,10.891972),(22.24012,10.905899),(22.253039,10.915304),(22.268439,10.908999),(22.2765,10.908534),(22.287249,10.91595),(22.305956,10.932564),(22.318772,10.939359),(22.339442,10.947731),(22.361146,10.953648),(22.36469,10.954209),(22.391842,10.958505),(22.407035,10.963053),(22.419231,10.970727),(22.437627,10.991552),(22.447136,10.99827),(22.460468,11.000828),(22.476281,10.99796),(22.490751,10.993154),(22.502843,10.992173),(22.511938,11.000828),(22.534676,10.98052),(22.55576,10.978969)] +Switzerland [(8.617437,47.757319),(8.62984,47.762796),(8.635007,47.784604),(8.644102,47.791012),(8.657022,47.788118),(8.666633,47.778273),(8.674488,47.766698),(8.68193,47.75874),(8.692265,47.757164),(8.703324,47.758714),(8.713142,47.757422),(8.719757,47.747319),(8.71707,47.743547),(8.703737,47.730033),(8.70043,47.723496),(8.704667,47.715332),(8.712625,47.708691),(8.715106,47.701069),(8.71707,47.694558),(8.769883,47.695074),(8.761718,47.70125),(8.77071,47.720861),(8.797581,47.720034),(8.830241,47.707192),(8.856079,47.690682),(8.837682,47.687788),(8.837786,47.680838),(8.851935,47.671282),(8.852668,47.670786),(8.881711,47.656136),(8.906205,47.651795),(8.945376,47.654302),(8.981756,47.662156),(8.997673,47.673835),(9.016586,47.6789),(9.128104,47.670425),(9.183398,47.670425),(9.196937,47.656136),(9.234351,47.656162),(9.273211,47.65009),(9.547482,47.534547),(9.553059,47.516891),(9.554951,47.5109),(9.58451,47.480721),(9.621717,47.469197),(9.650346,47.452092),(9.649519,47.409717),(9.639804,47.394524),(9.601047,47.36127),(9.596396,47.352305),(9.591228,47.334683),(9.587404,47.32781),(9.553298,47.299853),(9.521155,47.262801),(9.504618,47.243732),(9.487358,47.210014),(9.484981,47.176346),(9.492629,47.15981),(9.503481,47.145392),(9.511853,47.129372),(9.51237,47.10803),(9.502861,47.094698),(9.487565,47.083949),(9.475886,47.073226),(9.477023,47.063898),(9.499554,47.059351),(9.560636,47.0524),(9.581203,47.05687),(9.59991,47.053486),(9.65231,47.05793),(9.669053,47.056199),(9.857982,47.015478),(9.856328,47.004083),(9.860566,47.001602),(9.866767,47.001938),(9.870591,46.998838),(9.870591,46.992947),(9.866457,46.983387),(9.863976,46.959925),(9.860772,46.949151),(9.862426,46.939772),(9.875138,46.927421),(9.899943,46.914398),(10.006913,46.890757),(10.045567,46.865564),(10.068098,46.856624),(10.1113,46.847116),(10.125188,46.846751),(10.13197,46.846573),(10.157808,46.851612),(10.201423,46.86683),(10.211655,46.877036),(10.214342,46.884685),(10.215169,46.893108),(10.219924,46.905769),(10.235116,46.923313),(10.251343,46.92538),(10.270773,46.921892),(10.295681,46.922693),(10.296198,46.941374),(10.313665,46.964318),(10.338883,46.98411),(10.367925,46.995505),(10.373403,46.996254),(10.378984,46.995505),(10.384255,46.993153),(10.384358,46.993153),(10.384358,46.992998),(10.394693,46.985402),(10.415571,46.962406),(10.449574,46.943906),(10.458462,46.936619),(10.463836,46.919747),(10.451434,46.88577),(10.453811,46.864427),(10.44854,46.832233),(10.444923,46.823241),(10.439032,46.816885),(10.417224,46.79885),(10.419085,46.783967),(10.426216,46.76942),(10.428696,46.755648),(10.416604,46.743014),(10.399654,46.735546),(10.395623,46.7264),(10.396554,46.715005),(10.394383,46.70082),(10.384771,46.689012),(10.373919,46.681906),(10.369165,46.672398),(10.377537,46.653277),(10.395623,46.638808),(10.438205,46.635656),(10.459082,46.623564),(10.466627,46.604288),(10.465903,46.578476),(10.457945,46.553697),(10.451833,46.546702),(10.443993,46.537729),(10.425906,46.535326),(10.354282,46.548323),(10.319452,46.546049),(10.306637,46.547496),(10.295371,46.551087),(10.289067,46.555687),(10.283796,46.560725),(10.275941,46.565531),(10.234703,46.575298),(10.230259,46.58615),(10.235737,46.606691),(10.233773,46.617982),(10.217856,46.626974),(10.192122,46.626819),(10.09745,46.608035),(10.087839,46.604392),(10.083498,46.597002),(10.071199,46.564394),(10.062931,46.556746),(10.04133,46.541863),(10.032752,46.532975),(10.031408,46.525792),(10.031201,46.503829),(10.02686,46.493184),(10.028101,46.483934),(10.030478,46.476673),(10.035335,46.471066),(10.044017,46.466984),(10.026344,46.446262),(10.042053,46.432722),(10.071405,46.424816),(10.116157,46.418822),(10.133417,46.414016),(10.140755,46.402905),(10.13321,46.381098),(10.125976,46.37438),(10.104995,46.361357),(10.09745,46.351642),(10.092386,46.338103),(10.091766,46.328956),(10.095797,46.320533),(10.104892,46.309371),(10.14613,46.280277),(10.158945,46.262449),(10.14582,46.243328),(10.117914,46.231133),(10.075746,46.220022),(10.042673,46.220487),(10.041847,46.24307),(10.031718,46.260072),(9.992237,46.284359),(9.977561,46.298105),(9.97105,46.320016),(9.970636,46.339808),(9.964022,46.356086),(9.93901,46.367455),(9.918443,46.37115),(9.899013,46.372158),(9.855398,46.366964),(9.788839,46.343296),(9.768065,46.33862),(9.755249,46.340532),(9.730858,46.350712),(9.720109,46.350893),(9.709257,46.342392),(9.707293,46.330972),(9.708844,46.319629),(9.70843,46.311748),(9.693134,46.297072),(9.674324,46.291801),(9.559705,46.292731),(9.536451,46.298622),(9.515264,46.308596),(9.502551,46.32074),(9.482604,46.35681),(9.473716,46.361874),(9.451598,46.370375),(9.444364,46.375284),(9.4424,46.380891),(9.443847,46.396136),(9.437852,46.492047),(9.434648,46.498326),(9.426794,46.497111),(9.410671,46.488895),(9.403849,46.482513),(9.400335,46.475407),(9.395478,46.469413),(9.384626,46.466416),(9.377081,46.468689),(9.351553,46.485484),(9.350829,46.497861),(9.330986,46.501504),(9.282306,46.49737),(9.263186,46.485122),(9.245823,46.461041),(9.237968,46.436547),(9.24758,46.423033),(9.260912,46.416651),(9.262876,46.406626),(9.260292,46.394017),(9.260396,46.379728),(9.273831,46.344252),(9.275175,46.331385),(9.268974,46.309371),(9.239725,46.266996),(9.224842,46.231184),(9.215747,46.221056),(9.204172,46.213563),(9.192183,46.209635),(9.181331,46.204054),(9.17575,46.194132),(9.171099,46.182609),(9.163788,46.172989),(9.163244,46.172273),(9.090587,46.138167),(9.072087,46.118892),(9.068159,46.105972),(9.07033,46.083441),(9.067126,46.071142),(9.059168,46.061789),(9.049659,46.057913),(9.027748,46.053107),(9.002117,46.03931),(8.997776,46.027941),(9.015553,45.993111),(8.982686,45.971975),(8.980516,45.969495),(8.979793,45.966911),(8.980516,45.964379),(8.982686,45.961847),(8.993435,45.95425),(9.001703,45.93606),(9.010798,45.926655),(9.020514,45.922779),(9.042321,45.919731),(9.051726,45.915545),(9.063095,45.898957),(9.059271,45.881955),(9.034363,45.848107),(9.002427,45.820718),(8.972351,45.824646),(8.939588,45.834826),(8.900004,45.826403),(8.903725,45.841802),(8.909719,45.853688),(8.91375,45.86609),(8.912096,45.883402),(8.906515,45.896476),(8.898144,45.90955),(8.88078,45.931099),(8.870962,45.947067),(8.864451,45.953424),(8.857733,45.957093),(8.800372,45.978538),(8.785076,45.982311),(8.767919,45.983086),(8.769573,45.985773),(8.773397,45.990579),(8.790967,46.018691),(8.819596,46.042927),(8.834375,46.066388),(8.80895,46.089746),(8.793861,46.093415),(8.763165,46.092898),(8.747145,46.094449),(8.739497,46.098066),(8.732159,46.107419),(8.728983,46.108233),(8.723891,46.109538),(8.71769,46.107523),(8.702187,46.097963),(8.695055,46.095172),(8.677485,46.095792),(8.630873,46.114706),(8.611546,46.119357),(8.601831,46.122819),(8.538682,46.187621),(8.51026,46.207878),(8.482665,46.217542),(8.456517,46.224828),(8.43812,46.23537),(8.427165,46.251442),(8.423237,46.275833),(8.426648,46.301568),(8.442874,46.353373),(8.446285,46.382183),(8.445768,46.412362),(8.441634,46.434945),(8.427888,46.44869),(8.399156,46.452179),(8.385907,46.450206),(8.343449,46.443885),(8.316267,46.433653),(8.294976,46.418046),(8.286605,46.40536),(8.290429,46.401122),(8.297043,46.397634),(8.297457,46.387506),(8.291462,46.378359),(8.281541,46.370116),(8.270068,46.364044),(8.24175,46.354123),(8.192554,46.309164),(8.171883,46.299191),(8.128475,46.292473),(8.106874,46.285548),(8.087341,46.271802),(8.077315,46.262035),(8.073078,46.253612),(8.076592,46.249736),(8.09995,46.235629),(8.129509,46.196044),(8.132299,46.159354),(8.110595,46.126953),(8.066877,46.100598),(8.056025,46.098066),(8.035354,46.096516),(8.025329,46.091141),(8.018197,46.080858),(8.016027,46.069385),(8.015924,46.058172),(8.010653,46.029698),(8.008792,46.027683),(7.999077,46.0128),(7.998354,46.010629),(7.985848,45.999312),(7.978717,45.995178),(7.969105,45.993111),(7.898205,45.981949),(7.883782,45.973869),(7.872917,45.959383),(7.870201,45.94037),(7.84962,45.939712),(7.848389,45.938076),(7.845288,45.927792),(7.846115,45.922573),(7.843738,45.919214),(7.831232,45.91446),(7.825444,45.914666),(7.807564,45.91849),(7.780072,45.918129),(7.732013,45.930376),(7.722195,45.929601),(7.71465,45.92712),(7.706279,45.925725),(7.69398,45.928671),(7.692533,45.931203),(7.673722,45.950323),(7.658736,45.960038),(7.643027,45.966343),(7.541121,45.984119),(7.524377,45.978073),(7.514662,45.966704),(7.503707,45.956731),(7.482726,45.954871),(7.452961,45.945879),(7.393843,45.9157),(7.361803,45.907845),(7.286666,45.913426),(7.27354,45.910274),(7.245428,45.89813),(7.183726,45.880456),(7.153547,45.876529),(7.120888,45.876116),(7.090192,45.880508),(7.066938,45.890223),(7.022083,45.92526),(7.015158,45.933321),(7.009784,45.943398),(7.002756,45.961692),(6.991283,45.982466),(6.987666,45.993111),(6.982808,45.995385),(6.915112,46.048612),(6.892375,46.055588),(6.884003,46.053211),(6.876872,46.048095),(6.869224,46.044064),(6.859715,46.044994),(6.85093,46.049645),(6.85031,46.052746),(6.852377,46.056931),(6.851964,46.064683),(6.853411,46.065665),(6.853101,46.076103),(6.851344,46.086025),(6.848553,46.085043),(6.853101,46.090211),(6.861162,46.097032),(6.86819,46.10468),(6.869224,46.112329),(6.853927,46.122612),(6.774346,46.134808),(6.765664,46.151603),(6.774863,46.185864),(6.792226,46.221676),(6.827676,46.269477),(6.804938,46.296607),(6.769488,46.322678),(6.750368,46.345518),(6.755742,46.357068),(6.782097,46.378462),(6.789229,46.395205),(6.788107,46.405008),(6.787058,46.414171),(6.777756,46.424093),(6.777716,46.424106),(6.762667,46.42926),(6.613684,46.455899),(6.547021,46.457372),(6.482942,46.448587),(6.397676,46.408176),(6.365223,46.40244),(6.332357,46.401381),(6.301558,46.394482),(6.269105,46.375026),(6.24058,46.348955),(6.219496,46.329111),(6.214122,46.315469),(6.218256,46.305495),(6.227454,46.288494),(6.227971,46.284463),(6.237583,46.267926),(6.24182,46.263689),(6.252259,46.259916),(6.269002,46.265239),(6.27603,46.26312),(6.281198,46.240073),(6.255359,46.221107),(6.191384,46.191704),(6.140328,46.150207),(6.107875,46.138632),(6.073872,46.149174),(6.028293,46.147934),(5.982921,46.140441),(5.95884,46.130467),(5.972172,46.152171),(5.979821,46.162248),(5.982921,46.170826),(5.965248,46.186226),(5.954809,46.19992),(5.95853,46.211961),(5.982921,46.222709),(6.042866,46.24307),(6.044519,46.243432),(6.046173,46.243535),(6.048033,46.243432),(6.055888,46.241675),(6.061883,46.241158),(6.067671,46.241623),(6.089685,46.246377),(6.094026,46.253044),(6.093095,46.262294),(6.093612,46.273094),(6.100743,46.301413),(6.104051,46.309216),(6.118607,46.331771),(6.1364,46.359342),(6.135057,46.370401),(6.122861,46.385542),(6.108185,46.396497),(6.059019,46.417383),(6.054235,46.419416),(6.065707,46.427012),(6.067567,46.433601),(6.0655,46.440371),(6.0655,46.447993),(6.064777,46.451068),(6.0624,46.455202),(6.060229,46.459904),(6.060229,46.46502),(6.064157,46.471118),(6.075525,46.479593),(6.110355,46.520831),(6.145702,46.55163),(6.121517,46.570285),(6.118417,46.583463),(6.131853,46.595607),(6.266315,46.680356),(6.337938,46.707409),(6.34786,46.71317),(6.374215,46.733609),(6.407391,46.745701),(6.417933,46.751101),(6.429199,46.760816),(6.433023,46.76911),(6.432609,46.785983),(6.425168,46.791615),(6.419897,46.796525),(6.417107,46.802157),(6.418554,46.807015),(6.434263,46.839545),(6.441188,46.848149),(6.443118,46.851455),(6.446769,46.857709),(6.448422,46.871559),(6.445219,46.882617),(6.431886,46.900032),(6.427752,46.909076),(6.442635,46.944164),(6.491107,46.963388),(6.598698,46.986539),(6.665412,47.021291),(6.688253,47.043848),(6.676264,47.0624),(6.6897,47.07829),(6.699105,47.084621),(6.72422,47.09077),(6.72794,47.097126),(6.731661,47.098883),(6.746027,47.103948),(6.744787,47.121053),(6.774759,47.128184),(6.838076,47.168132),(6.840285,47.169525),(6.859302,47.190919),(6.888344,47.211305),(6.956247,47.245231),(6.952216,47.270036),(6.958624,47.290551),(6.977434,47.303729),(6.986529,47.304504),(6.991904,47.305951),(7.006476,47.319361),(7.016915,47.323521),(7.027147,47.325433),(7.036552,47.329515),(7.044303,47.340497),(7.033865,47.350651),(7.018879,47.359901),(7.003996,47.368143),(6.985599,47.362123),(6.86664,47.354165),(6.871601,47.366955),(6.884003,47.382587),(6.898783,47.395713),(6.924517,47.405996),(6.926068,47.424858),(6.952319,47.428837),(6.968546,47.435194),(6.983429,47.443798),(6.990973,47.452221),(6.986116,47.464132),(6.97578,47.477956),(6.9733,47.489092),(6.991904,47.492942),(7.000792,47.49767),(7.009784,47.499247),(7.018879,47.49767),(7.027974,47.492942),(7.053915,47.490384),(7.103731,47.496275),(7.127296,47.492942),(7.140318,47.487852),(7.142169,47.487651),(7.153651,47.486405),(7.180833,47.488265),(7.162642,47.459895),(7.168327,47.443565),(7.190031,47.434728),(7.219383,47.428476),(7.223517,47.426228),(7.226308,47.422636),(7.230339,47.419019),(7.23809,47.416797),(7.244808,47.417727),(7.282635,47.428889),(7.309093,47.432661),(7.33693,47.431854),(7.378547,47.430646),(7.388219,47.433289),(7.406349,47.438242),(7.420563,47.450857),(7.426089,47.455761),(7.429293,47.465114),(7.427639,47.470747),(7.422782,47.475424),(7.419474,47.477852),(7.41441,47.484028),(7.414307,47.490177),(7.425986,47.492503),(7.441488,47.488834),(7.445996,47.486884),(7.454511,47.483201),(7.46743,47.481909),(7.482726,47.491263),(7.484483,47.492942),(7.485827,47.495784),(7.48593,47.498394),(7.485776,47.498768),(7.484897,47.5009),(7.477765,47.507696),(7.475595,47.511726),(7.476939,47.514879),(7.482726,47.516997),(7.493062,47.515499),(7.501123,47.517307),(7.505464,47.523018),(7.505154,47.533017),(7.501743,47.532965),(7.485103,47.541595),(7.482726,47.542267),(7.520867,47.563416),(7.526341,47.566452),(7.550319,47.575495),(7.585483,47.584479),(7.586028,47.584619),(7.637032,47.594977),(7.659666,47.596579),(7.646541,47.571542),(7.635895,47.564591),(7.612337,47.564731),(7.609747,47.564746),(7.646901,47.551445),(7.661423,47.546246),(7.683438,47.544257),(7.72732,47.550423),(7.76674,47.555961),(7.78555,47.563196),(7.801467,47.576089),(7.819657,47.595339),(7.833713,47.590481),(7.898205,47.587846),(7.904303,47.583557),(7.907507,47.574177),(7.90947,47.564798),(7.912157,47.560561),(8.042279,47.560561),(8.087237,47.567382),(8.096952,47.571852),(8.101397,47.576193),(8.105427,47.581257),(8.113902,47.587846),(8.122067,47.592135),(8.143771,47.600067),(8.162065,47.603762),(8.168886,47.608646),(8.173847,47.613529),(8.179015,47.615803),(8.232965,47.621952),(8.251051,47.622004),(8.276993,47.61663),(8.288569,47.615803),(8.293943,47.611462),(8.299317,47.601824),(8.306345,47.592187),(8.316164,47.587846),(8.354094,47.581024),(8.41807,47.580766),(8.4211,47.581112),(8.448869,47.58428),(8.450109,47.589034),(8.461788,47.606139),(8.49238,47.619833),(8.522353,47.621901),(8.537752,47.612134),(8.549638,47.598594),(8.551719,47.596863),(8.560697,47.589396),(8.574133,47.592445),(8.576305,47.595023),(8.580644,47.600171),(8.581781,47.607664),(8.581264,47.614769),(8.582504,47.62159),(8.582091,47.625027),(8.579714,47.628929),(8.57806,47.633476),(8.580334,47.639005),(8.583951,47.641124),(8.589222,47.642468),(8.593563,47.642571),(8.594493,47.640969),(8.595113,47.63482),(8.601624,47.632598),(8.607309,47.656291),(8.598214,47.656885),(8.593589,47.658169),(8.582194,47.66133),(8.568241,47.662932),(8.519666,47.657351),(8.504679,47.65226),(8.49083,47.645568),(8.476051,47.640401),(8.458274,47.639884),(8.437603,47.647842),(8.411972,47.661045),(8.407011,47.661562),(8.391301,47.665464),(8.397709,47.67629),(8.395229,47.684817),(8.390991,47.692129),(8.392128,47.699519),(8.401947,47.707089),(8.427268,47.716468),(8.437913,47.723186),(8.445458,47.743185),(8.450109,47.750471),(8.463648,47.763907),(8.471503,47.76706),(8.482665,47.766853),(8.536512,47.774088),(8.551602,47.779255),(8.5423,47.795017),(8.558216,47.801166),(8.583124,47.800236),(8.601624,47.794603),(8.603175,47.787317),(8.604105,47.774398),(8.607619,47.762254),(8.617437,47.757319)] +Clipperton Island [(-109.212026,10.30268),(-109.210357,10.288723),(-109.218577,10.281562),(-109.228017,10.292141),(-109.234242,10.307929),(-109.225942,10.311021),(-109.212026,10.30268)] +Cameroon [(14.560692,12.766224),(14.569374,12.769403),(14.569374,12.75961),(14.570717,12.750386),(14.575265,12.744908),(14.584877,12.746355),(14.603997,12.760798),(14.610612,12.762349),(14.618363,12.759196),(14.620327,12.754055),(14.62074,12.747853),(14.624254,12.741885),(14.641721,12.730904),(14.648129,12.725116),(14.664458,12.715969),(14.694017,12.723721),(14.709934,12.718243),(14.716755,12.70181),(14.702079,12.668995),(14.713654,12.65251),(14.728847,12.677212),(14.734118,12.680416),(14.743317,12.67716),(14.752102,12.668944),(14.758716,12.658815),(14.761403,12.649358),(14.768845,12.633235),(14.786208,12.63122),(14.819178,12.638816),(14.830753,12.618249),(14.863826,12.495466),(14.860105,12.490091),(14.852044,12.474692),(14.850184,12.468129),(14.849563,12.457019),(14.85101,12.455158),(14.855455,12.454538),(14.863826,12.447045),(14.861862,12.452006),(14.865893,12.452574),(14.872404,12.450404),(14.877469,12.447045),(14.878502,12.443066),(14.876849,12.431594),(14.877469,12.427201),(14.891215,12.402655),(14.908268,12.326897),(14.906304,12.317957),(14.904857,12.248401),(14.9031,12.236257),(14.898036,12.219462),(14.898036,12.207473),(14.90093,12.200032),(14.905891,12.195639),(14.910128,12.190368),(14.911575,12.180136),(14.907441,12.17347),(14.899896,12.171765),(14.894832,12.167372),(14.898036,12.152799),(14.9031,12.145875),(14.928732,12.128615),(14.950746,12.103345),(14.964802,12.092441),(14.976791,12.094147),(14.993844,12.106704),(15.011827,12.108616),(15.030431,12.100916),(15.049448,12.084586),(15.04459,12.078385),(15.04087,12.067585),(15.04056,12.055648),(15.045727,12.046088),(15.053065,12.038026),(15.053685,12.031877),(15.051205,12.024228),(15.049448,12.011929),(15.05968,11.997305),(15.076836,11.982836),(15.081177,11.971673),(15.052548,11.967229),(15.048311,11.962785),(15.050585,11.952863),(15.055546,11.942476),(15.05937,11.936792),(15.063401,11.927283),(15.056579,11.918447),(15.046967,11.910179),(15.042006,11.902375),(15.044177,11.877312),(15.050998,11.861603),(15.06278,11.853489),(15.079834,11.851216),(15.086345,11.840467),(15.110943,11.782899),(15.105362,11.772719),(15.089135,11.75763),(15.083554,11.748173),(15.085311,11.744039),(15.095957,11.734117),(15.097197,11.727657),(15.093063,11.722903),(15.086345,11.72218),(15.079834,11.722593),(15.076113,11.721456),(15.068258,11.700114),(15.066501,11.680632),(15.069395,11.660788),(15.085208,11.615881),(15.09575,11.598156),(15.123862,11.563171),(15.135644,11.530822),(15.122312,11.503227),(15.076113,11.453307),(15.067018,11.435556),(15.06061,11.416126),(15.054305,11.364088),(15.049448,11.348714),(15.049448,11.337268),(15.052548,11.329801),(15.057819,11.325356),(15.062264,11.320034),(15.06309,11.309931),(15.056373,11.29342),(15.033325,11.26027),(15.028261,11.244483),(15.021233,11.182549),(15.02883,11.080218),(15.035185,10.994627),(15.06247,10.930703),(15.072702,10.915769),(15.079007,10.898147),(15.075596,10.873498),(15.06309,10.830761),(15.065881,10.793115),(15.142259,10.647207),(15.149907,10.623125),(15.14846,10.607338),(15.138435,10.589691),(15.132337,10.565403),(15.131717,10.540701),(15.138228,10.521659),(15.144429,10.51631),(15.153628,10.511969),(15.164686,10.509075),(15.176055,10.50799),(15.186597,10.505871),(15.193315,10.501195),(15.198173,10.496492),(15.218326,10.487216),(15.227215,10.470137),(15.241167,10.432904),(15.255637,10.41704),(15.268763,10.406343),(15.278374,10.394276),(15.282199,10.374588),(15.284266,10.349292),(15.29057,10.328983),(15.301422,10.311749),(15.439192,10.185245),(15.476399,10.132742),(15.490661,10.124448),(15.490144,10.120107),(15.536137,10.080523),(15.602799,10.04099),(15.637939,10.029957),(15.681244,9.991278),(15.663777,9.98611),(15.439398,9.931695),(15.382968,9.930196),(15.214916,9.984095),(15.155488,9.986523),(15.109599,9.981537),(15.100711,9.978901),(15.089445,9.972183),(15.071669,9.955957),(15.06123,9.949239),(15.033015,9.942857),(15.002422,9.945053),(14.944131,9.958825),(14.898139,9.960478),(14.772566,9.921747),(14.732465,9.923814),(14.440493,9.995308),(14.196341,9.979147),(14.181697,9.978178),(14.173532,9.975025),(14.171155,9.96761),(14.170638,9.957843),(14.168365,9.94774),(14.119789,9.85201),(14.088473,9.809635),(14.006721,9.739277),(13.945949,9.652642),(13.947603,9.637759),(14.036486,9.568771),(14.321327,9.243158),(14.331145,9.200215),(14.349542,9.168356),(14.571699,8.99099),(14.793856,8.813623),(14.809876,8.808611),(14.819178,8.811608),(14.827963,8.813158),(14.836748,8.813003),(14.846049,8.810988),(14.859899,8.803314),(14.89938,8.774323),(14.908268,8.764841),(14.913332,8.752438),(14.919947,8.74771),(14.927285,8.745075),(14.934416,8.739003),(14.940101,8.729649),(14.949092,8.704276),(14.951469,8.692106),(14.951469,8.68283),(14.955087,8.676216),(14.968523,8.672159),(15.005833,8.66663),(15.031258,8.658749),(15.051928,8.643789),(15.068568,8.623867),(15.110736,8.555138),(15.16851,8.498604),(15.183703,8.479148),(15.210706,8.421822),(15.345347,8.13599),(15.406532,7.921585),(15.440742,7.839419),(15.487871,7.804951),(15.509368,7.804021),(15.540787,7.796838),(15.562905,7.792445),(15.562181,7.690178),(15.548952,7.630801),(15.521977,7.576076),(15.481049,7.523263),(15.473298,7.509103),(15.419451,7.43655),(15.415524,7.42084),(15.434954,7.402908),(15.432784,7.389731),(15.428443,7.388801),(15.409633,7.387664),(15.403225,7.386372),(15.397437,7.380739),(15.389169,7.364151),(15.385345,7.358363),(15.338216,7.32219),(15.261321,7.279247),(15.246564,7.266731),(15.223908,7.247517),(15.205097,7.200233),(15.191248,7.177341),(15.186597,7.166334),(15.185357,7.156877),(15.190214,7.098793),(15.187527,7.088612),(15.179052,7.07838),(15.156108,7.067787),(15.147013,7.061844),(15.136161,7.045308),(15.128926,7.026497),(15.113217,6.964692),(15.080247,6.878083),(15.05906,6.836276),(15.042213,6.790775),(15.034565,6.776771),(15.022369,6.766539),(14.962321,6.736696),(14.946095,6.72574),(14.932452,6.710289),(14.921874,6.686414),(14.807292,6.4278),(14.782177,6.393616),(14.780007,6.382221),(14.784348,6.358683),(14.784658,6.347805),(14.782384,6.336772),(14.772255,6.318323),(14.734842,6.270445),(14.719029,6.257862),(14.576402,6.189778),(14.534957,6.190088),(14.525966,6.174069),(14.510979,6.155336),(14.482144,6.127069),(14.467054,6.122599),(14.443903,6.100249),(14.430571,6.088079),(14.431811,6.084617),(14.432709,6.079123),(14.433568,6.073868),(14.429124,6.064179),(14.426023,6.059864),(14.422509,6.051363),(14.418169,6.047126),(14.412898,6.047022),(14.402459,6.054877),(14.397705,6.053947),(14.390263,6.045782),(14.387266,6.039038),(14.389436,6.031054),(14.397705,6.019169),(14.406076,6.01103),(14.417548,5.997258),(14.432328,5.98545),(14.446901,5.970024),(14.453825,5.953875),(14.458166,5.936409),(14.465711,5.920673),(14.482144,5.90964),(14.499197,5.909537),(14.530616,5.90592),(14.545396,5.907573),(14.572474,5.924187),(14.584773,5.923412),(14.598003,5.903491),(14.602964,5.883389),(14.617433,5.864966),(14.624047,5.758306),(14.631075,5.738049),(14.624358,5.723605),(14.610612,5.669138),(14.592835,5.62387),(14.590148,5.608289),(14.591491,5.590952),(14.596556,5.577232),(14.610612,5.553667),(14.617226,5.53788),(14.61888,5.525452),(14.617433,5.495299),(14.614126,5.48486),(14.599553,5.456645),(14.596246,5.440108),(14.597279,5.41148),(14.592835,5.400033),(14.579606,5.395382),(14.579296,5.387605),(14.570821,5.370939),(14.560796,5.355462),(14.555938,5.351328),(14.553974,5.338228),(14.548393,5.320503),(14.539608,5.303579),(14.528033,5.293011),(14.519868,5.290583),(14.523899,5.279679),(14.539712,5.261799),(14.560485,5.248595),(14.603584,5.234255),(14.624461,5.224049),(14.640481,5.208236),(14.651539,5.187514),(14.658877,5.164544),(14.663218,5.141832),(14.663012,5.091447),(14.667456,5.052768),(14.660324,5.015793),(14.660132,5.01144),(14.659498,4.997035),(14.663425,4.985717),(14.669833,4.977113),(14.674484,4.967579),(14.672107,4.940811),(14.675827,4.93076),(14.681615,4.920941),(14.686989,4.908875),(14.701459,4.814384),(14.700632,4.804282),(14.696084,4.779735),(14.691847,4.768702),(14.69071,4.762139),(14.697325,4.745215),(14.704249,4.669354),(14.717272,4.622019),(14.74373,4.57998),(14.779697,4.545047),(14.938344,4.435932),(14.982062,4.420481),(14.993947,4.413298),(15.000562,4.403195),(15.007383,4.37777),(15.013894,4.364257),(15.048518,4.321649),(15.063814,4.293434),(15.072806,4.265942),(15.082934,4.205507),(15.084484,4.148611),(15.091202,4.121791),(15.102571,4.112412),(15.117764,4.114324),(15.132854,4.108536),(15.139262,4.094583),(15.142569,4.08045),(15.14846,4.073938),(15.162413,4.073938),(15.177709,4.071458),(15.189801,4.063112),(15.192075,4.052234),(15.172438,4.043811),(15.150424,4.038514),(15.111253,4.019937),(15.091719,4.015854),(15.075183,4.017973),(15.043143,4.026138),(15.025987,4.026086),(15.084898,3.885836),(15.171301,3.758971),(15.25264,3.672852),(15.262306,3.662589),(15.329741,3.590996),(15.413973,3.50188),(15.517946,3.391603),(15.616855,3.286777),(15.7107,3.187455),(15.78563,3.107977),(15.793175,3.103274),(15.80103,3.100897),(15.813536,3.098985),(15.817566,3.100122),(15.829142,3.106633),(15.834206,3.108545),(15.840201,3.107408),(15.850949,3.100432),(15.854773,3.098985),(15.897768,3.103533),(15.913995,3.097952),(15.933425,3.081777),(15.950065,3.061003),(15.95823,3.041521),(15.971562,2.991188),(15.974249,2.985762),(15.977763,2.980956),(15.982001,2.976719),(15.995437,2.981473),(16.006082,2.983953),(16.015797,2.983488),(16.026236,2.978992),(16.034194,2.970621),(16.055381,2.93977),(16.070161,2.906594),(16.08246,2.885665),(16.092382,2.863289),(16.095172,2.836779),(16.086904,2.813163),(16.059929,2.786188),(16.056208,2.759833),(16.060032,2.72583),(16.059309,2.711825),(16.062616,2.703195),(16.072848,2.702834),(16.086284,2.704952),(16.0991,2.70397),(16.110468,2.701438),(16.101373,2.687847),(16.093725,2.67312),(16.090315,2.661906),(16.093105,2.641494),(16.108505,2.606612),(16.111502,2.5862),(16.106851,2.567028),(16.091245,2.532766),(16.090315,2.510494),(16.094345,2.497523),(16.107058,2.474165),(16.111502,2.455872),(16.111502,2.418562),(16.112949,2.410448),(16.120907,2.389571),(16.133413,2.364818),(16.152326,2.343269),(16.159251,2.332934),(16.162868,2.323839),(16.164729,2.314795),(16.165969,2.294796),(16.169069,2.289887),(16.182919,2.281154),(16.186536,2.277692),(16.18695,2.26932),(16.181265,2.256556),(16.179715,2.246996),(16.192841,2.239503),(16.196665,2.236454),(16.202349,2.23201),(16.207723,2.22307),(16.199455,2.212166),(16.159251,2.18209),(16.140647,2.199815),(16.12039,2.203329),(16.104371,2.193562),(16.097756,2.171548),(16.085767,2.149172),(16.083493,2.137752),(16.08556,2.12491),(16.089798,2.116151),(16.092485,2.106901),(16.090315,2.092742),(16.088144,2.09176),(16.084113,2.091605),(16.079669,2.090261),(16.076672,2.08592),(16.075535,2.079952),(16.075535,2.075456),(16.076155,2.07282),(16.076672,2.072252),(16.078119,2.063441),(16.08153,2.055638),(16.081736,2.046827),(16.06644,2.025485),(16.063753,2.015873),(16.06489,1.97895),(16.068714,1.973602),(16.074915,1.970604),(16.083493,1.963008),(16.101373,1.932803),(16.135066,1.845315),(16.159044,1.734805),(16.15584,1.719069),(16.145092,1.714315),(16.123594,1.721601),(16.114809,1.719069),(16.069851,1.654551),(16.030473,1.705401),(16.021998,1.72279),(16.021998,1.733048),(16.024892,1.742479),(16.026339,1.752297),(16.021998,1.763795),(16.013833,1.771314),(16.002775,1.775913),(15.990786,1.776172),(15.98045,1.770591),(15.963191,1.77736),(15.94376,1.781624),(15.928981,1.788962),(15.92588,1.804749),(15.915235,1.798961),(15.901799,1.793742),(15.889913,1.793277),(15.884952,1.801648),(15.882369,1.816712),(15.875651,1.823766),(15.865936,1.828468),(15.842061,1.844152),(15.815396,1.853428),(15.80289,1.859965),(15.76465,1.908722),(15.757415,1.912985),(15.734057,1.916706),(15.721552,1.921615),(15.711113,1.927377),(15.706772,1.931976),(15.611791,1.942544),(15.526628,1.967814),(15.48291,1.97585),(15.439192,1.969829),(15.388135,1.939547),(15.367981,1.932855),(15.349171,1.923295),(15.337389,1.92146),(15.337802,1.92376),(15.314341,1.93425),(15.309484,1.935077),(15.301629,1.943578),(15.300182,1.94766),(15.301939,1.953319),(15.303283,1.966419),(15.301112,1.973757),(15.295428,1.981534),(15.287573,1.987787),(15.25357,2.000318),(15.248092,2.003341),(15.244165,2.010059),(15.238687,2.025304),(15.233726,2.031298),(15.212642,2.039618),(15.197036,2.034967),(15.1836,2.029335),(15.151664,2.040988),(15.138538,2.011506),(15.123862,2.01701),(15.117764,2.01701),(15.107636,2.000835),(15.091616,1.984428),(15.074873,1.979364),(15.06309,1.997166),(15.04366,1.990862),(15.028261,1.995306),(14.980718,2.033107),(14.971003,2.034451),(14.963045,2.010421),(14.953846,2.005822),(14.932142,2.003341),(14.892455,2.00639),(14.896589,2.030937),(14.907338,2.058894),(14.887804,2.072252),(14.8846,2.082096),(14.871474,2.101656),(14.857005,2.115944),(14.850184,2.109795),(14.850184,2.097367),(14.84822,2.085197),(14.841192,2.075921),(14.826309,2.072252),(14.764814,2.065456),(14.76161,2.070185),(14.76254,2.092535),(14.761403,2.099589),(14.756339,2.099589),(14.747554,2.097186),(14.737116,2.096075),(14.727297,2.099589),(14.733498,2.102018),(14.747864,2.113205),(14.720889,2.127597),(14.713654,2.12398),(14.720476,2.099589),(14.705696,2.105532),(14.685956,2.125866),(14.672003,2.134341),(14.646062,2.133359),(14.636346,2.13832),(14.644821,2.154185),(14.620947,2.16483),(14.587874,2.201727),(14.562139,2.208807),(14.557075,2.202399),(14.547773,2.193666),(14.54798,2.184364),(14.550254,2.175166),(14.54705,2.166536),(14.538058,2.163383),(14.4592,2.146537),(14.438736,2.133979),(14.432948,2.132119),(14.418685,2.135271),(14.399358,2.153151),(14.383649,2.162091),(14.320293,2.17067),(14.276265,2.153565),(14.266963,2.152428),(14.16175,2.15341),(14.002793,2.154805),(13.823993,2.156407),(13.662266,2.157761),(13.620336,2.158112),(13.466547,2.159508),(13.294568,2.161058),(13.294258,2.185759),(13.298392,2.215835),(13.294155,2.230511),(13.284646,2.242242),(13.26966,2.255729),(13.254157,2.266891),(13.242891,2.27149),(13.235967,2.269888),(13.221601,2.263946),(13.212299,2.264049),(13.205684,2.266891),(13.191732,2.277692),(13.163827,2.283169),(13.133337,2.284513),(13.124656,2.281051),(13.11308,2.272731),(13.09303,2.253455),(13.083521,2.249528),(13.04094,2.244205),(13.012931,2.256298),(12.996912,2.260018),(12.983166,2.253455),(12.97221,2.250355),(12.954847,2.253249),(12.924771,2.264049),(12.914539,2.254541),(12.903171,2.250355),(12.890458,2.251388),(12.876402,2.257176),(12.867824,2.24498),(12.848084,2.249321),(12.825243,2.259243),(12.808189,2.264049),(12.79558,2.258778),(12.784108,2.249528),(12.770155,2.240691),(12.749898,2.236712),(12.614609,2.256918),(12.590735,2.265703),(12.574819,2.277692),(12.551461,2.272266),(12.534201,2.277692),(12.47839,2.295882),(12.439943,2.298517),(12.384856,2.285908),(12.366769,2.289577),(12.334006,2.309576),(12.321604,2.314072),(12.312096,2.312935),(12.291218,2.301773),(12.28078,2.299034),(12.261039,2.296192),(12.222592,2.283324),(12.202645,2.279552),(12.159237,2.281412),(12.118826,2.28782),(12.100739,2.288492),(12.041931,2.283996),(11.966174,2.28875),(11.889796,2.282084),(11.802153,2.284823),(11.768149,2.280172),(11.75275,2.281877),(11.701384,2.298724),(11.681023,2.315415),(11.671204,2.320996),(11.657252,2.322495),(11.644643,2.319653),(11.618598,2.310403),(11.351637,2.300584),(11.349777,2.291489),(11.354325,2.278467),(11.355978,2.265186),(11.349984,2.25113),(11.342232,2.240588),(11.335928,2.229167),(11.334171,2.212786),(11.334171,2.20028),(11.332414,2.188033),(11.328486,2.176302),(11.322078,2.16576),(11.022975,2.165709),(10.723769,2.165657),(10.424666,2.165657),(10.409686,2.165654),(10.189983,2.165616),(10.125562,2.165605),(9.990997,2.165605),(9.97074,2.168913),(9.907488,2.200487),(9.890125,2.204569),(9.872141,2.211236),(9.84682,2.228547),(9.823669,2.249011),(9.810853,2.264876),(9.808682,2.285495),(9.811886,2.306165),(9.81106,2.324872),(9.799571,2.341742),(9.812185,2.353583),(9.812185,2.359809),(9.819184,2.376939),(9.822927,2.562934),(9.853201,2.696967),(9.870453,2.738105),(9.874278,2.754543),(9.877778,2.881415),(9.88795,2.926907),(9.903331,2.968329),(9.922048,2.99726),(9.94337,3.023139),(9.95574,3.050482),(9.958018,3.082221),(9.919688,3.228095),(9.90211,3.251695),(9.90211,3.257961),(9.911632,3.257717),(9.917979,3.259467),(9.929454,3.264797),(9.929454,3.271552),(9.91391,3.270331),(9.903087,3.272895),(9.89503,3.278306),(9.88795,3.285224),(9.881521,3.294338),(9.855317,3.343573),(9.780935,3.436754),(9.739024,3.47309),(9.6421,3.539049),(9.664236,3.543931),(9.68865,3.556098),(9.770763,3.61872),(9.792817,3.627183),(9.819591,3.627875),(9.787608,3.637112),(9.759613,3.626166),(9.733653,3.60932),(9.706879,3.600531),(9.638438,3.594387),(9.626231,3.600002),(9.621349,3.612779),(9.625987,3.626451),(9.6421,3.63467),(9.612559,3.704983),(9.565115,3.770901),(9.551524,3.79621),(9.545909,3.819648),(9.570974,3.795478),(9.576671,3.792304),(9.581554,3.787828),(9.58961,3.766099),(9.594249,3.758205),(9.606944,3.752265),(9.624278,3.75019),(9.662608,3.750718),(9.652517,3.756049),(9.621104,3.76496),(9.611013,3.770575),(9.607107,3.774726),(9.604259,3.779975),(9.597423,3.788886),(9.589203,3.809638),(9.592133,3.83515),(9.60377,3.859036),(9.621104,3.874823),(9.659028,3.84101),(9.679698,3.836086),(9.689789,3.860582),(9.723481,3.843817),(9.736339,3.834174),(9.744477,3.819648),(9.750336,3.830268),(9.750499,3.840766),(9.74586,3.850898),(9.738292,3.860582),(9.741466,3.861029),(9.751964,3.860582),(9.704926,3.877509),(9.682872,3.890448),(9.67628,3.909003),(9.68922,3.922431),(9.715017,3.931342),(9.743337,3.93594),(9.764415,3.936347),(9.764334,3.940741),(9.76295,3.943793),(9.758149,3.950019),(9.760753,3.951361),(9.76295,3.951239),(9.764415,3.952338),(9.764415,3.957465),(9.664806,3.940375),(9.634613,3.943183),(9.618907,3.960354),(9.623709,3.985785),(9.639903,4.008775),(9.65919,4.018866),(9.675629,4.03384),(9.718923,4.099555),(9.748302,4.114447),(9.752452,4.119818),(9.756847,4.129828),(9.754568,4.135688),(9.738292,4.12873),(9.719493,4.114936),(9.710948,4.105699),(9.703461,4.09394),(9.696625,4.09394),(9.696625,4.114447),(9.678884,4.10102),(9.646332,4.051459),(9.628429,4.031928),(9.606619,4.020657),(9.579356,4.013007),(9.559337,4.016791),(9.559581,4.039374),(9.545909,4.025702),(9.526622,4.035793),(9.508556,4.054185),(9.498546,4.077216),(9.504242,4.100775),(9.490082,4.115871),(9.478526,4.111396),(9.450369,4.080308),(9.452891,4.076972),(9.457286,4.071112),(9.46518,4.068101),(9.474294,4.066148),(9.484386,4.059882),(9.485362,4.055325),(9.495616,4.03148),(9.507009,4.019477),(9.523611,4.00609),(9.532481,3.989447),(9.518565,3.970445),(9.504242,3.976142),(9.497081,3.977688),(9.490082,3.980658),(9.476899,3.990912),(9.464041,4.01203),(9.458344,4.016181),(9.453868,4.018622),(9.451182,4.022773),(9.450369,4.031928),(9.437999,4.030463),(9.42921,4.026557),(9.424083,4.019477),(9.422374,4.008368),(9.449392,3.992133),(9.456554,3.984076),(9.458832,3.972357),(9.456391,3.963528),(9.452403,3.953925),(9.450369,3.939765),(9.453298,3.932115),(9.469086,3.923407),(9.476899,3.915839),(9.464041,3.90998),(9.448253,3.905748),(9.41212,3.902167),(9.393403,3.904283),(9.359223,3.913723),(9.343516,3.915839),(9.313731,3.930854),(9.302582,3.964993),(9.307628,4.001939),(9.326182,4.025702),(9.326182,4.031928),(9.301443,4.026353),(9.290294,4.009711),(9.284353,3.992255),(9.250336,3.960842),(9.220714,3.96601),(9.210704,3.96426),(9.211111,3.982571),(9.213227,3.996568),(9.210623,4.008124),(9.196462,4.018866),(9.184744,4.020901),(9.166515,4.020901),(9.148774,4.019029),(9.138682,4.015448),(9.123383,4.01789),(9.07016,4.051418),(8.983409,4.092434),(8.971202,4.100775),(8.969412,4.128974),(8.988455,4.18891),(8.990977,4.217475),(8.960297,4.245917),(8.93629,4.279527),(8.918956,4.318061),(8.894786,4.460517),(8.900076,4.485093),(8.926036,4.529608),(8.93572,4.55329),(8.913585,4.528632),(8.900564,4.521633),(8.894786,4.535875),(8.897227,4.548),(8.901541,4.560248),(8.904307,4.573188),(8.901622,4.587388),(8.893809,4.594631),(8.871918,4.602484),(8.864106,4.61872),(8.856293,4.62995),(8.847016,4.639716),(8.83961,4.642646),(8.835704,4.629625),(8.86671,4.582709),(8.873709,4.560045),(8.867849,4.544582),(8.858735,4.540839),(8.850597,4.547431),(8.847016,4.563218),(8.798595,4.601142),(8.798025,4.588284),(8.79949,4.577786),(8.80421,4.570136),(8.812836,4.566352),(8.799571,4.542182),(8.795177,4.539008),(8.788422,4.541449),(8.768565,4.553127),(8.764415,4.556627),(8.757009,4.56509),(8.740571,4.571234),(8.724132,4.580471),(8.716563,4.597724),(8.705903,4.63467),(8.661306,4.698798),(8.655121,4.738267),(8.638682,4.71308),(8.645356,4.684068),(8.660492,4.653998),(8.68572,4.561225),(8.694835,4.55329),(8.706309,4.547675),(8.716563,4.539008),(8.722667,4.513129),(8.701671,4.501288),(8.576671,4.491889),(8.56544,4.49726),(8.570323,4.50967),(8.582693,4.523342),(8.593761,4.532782),(8.581716,4.538479),(8.570567,4.53856),(8.562673,4.533189),(8.556407,4.511705),(8.54835,4.507799),(8.537364,4.508531),(8.525564,4.511705),(8.510265,4.527045),(8.505056,4.55093),(8.509939,4.568834),(8.525564,4.566352),(8.530772,4.57925),(8.552094,4.614732),(8.538341,4.604641),(8.525727,4.604438),(8.516124,4.612982),(8.511241,4.629055),(8.513682,4.64232),(8.521169,4.655951),(8.538585,4.676215),(8.567638,4.69599),(8.573253,4.704088),(8.573578,4.716376),(8.569672,4.728339),(8.567638,4.74022),(8.573253,4.752509),(8.580089,4.745063),(8.576508,4.784654),(8.57838,4.804674),(8.590017,4.813381),(8.594168,4.815294),(8.594179,4.815299),(8.594186,4.815299),(8.595113,4.815314),(8.612166,4.831877),(8.608446,4.846217),(8.605448,4.86004),(8.602245,4.881331),(8.61103,4.896653),(8.638315,4.916781),(8.644412,4.934868),(8.683687,4.99688),(8.683687,4.997035),(8.698569,5.017809),(8.707871,5.037549),(8.722651,5.08119),(8.728852,5.094548),(8.748282,5.12421),(8.758307,5.134881),(8.769469,5.139946),(8.781252,5.141987),(8.79169,5.146741),(8.798925,5.159635),(8.825693,5.295492),(8.82466,5.306137),(8.816392,5.330296),(8.815255,5.343499),(8.821663,5.367684),(8.84316,5.409981),(8.849775,5.432357),(8.849258,5.453467),(8.845744,5.472794),(8.844297,5.492353),(8.850498,5.514006),(8.865484,5.533462),(8.884294,5.551445),(8.899487,5.570953),(8.903932,5.595086),(8.8937,5.621751),(8.874889,5.64144),(8.852565,5.658674),(8.832411,5.678156),(8.819286,5.703451),(8.826934,5.717817),(8.844607,5.730866),(8.862177,5.752337),(8.866621,5.777452),(8.857836,5.794893),(8.847087,5.810758),(8.845227,5.831041),(8.855872,5.847499),(8.891219,5.871116),(8.904655,5.888117),(8.921708,5.904473),(8.943206,5.901424),(8.965013,5.893595),(8.982686,5.895765),(8.986304,5.908814),(8.988474,5.937287),(8.993849,5.944083),(9.009868,5.952351),(9.022477,5.965813),(9.043871,5.996689),(9.043871,5.996844),(9.136165,6.092523),(9.273315,6.202775),(9.298843,6.238432),(9.327368,6.298506),(9.341011,6.313983),(9.354757,6.321502),(9.366539,6.32269),(9.379148,6.321605),(9.394961,6.322535),(9.422866,6.339356),(9.453149,6.397673),(9.482604,6.415992),(9.48859,6.418208),(9.528596,6.433019),(9.548957,6.443174),(9.56477,6.458599),(9.588127,6.502731),(9.60301,6.515185),(9.632673,6.521153),(9.644806,6.521226),(9.680525,6.521438),(9.693031,6.531308),(9.69398,6.534305),(9.769822,6.773722),(9.788529,6.794754),(9.8123,6.793049),(9.83173,6.783566),(9.851161,6.777882),(9.874622,6.787701),(10.119465,6.994406),(10.142926,7.007687),(10.156878,7.004742),(10.165043,6.988515),(10.179409,6.914928),(10.189848,6.895446),(10.210828,6.879168),(10.238424,6.871003),(10.495979,6.874672),(10.496599,6.897151),(10.500733,6.912809),(10.508898,6.926348),(10.521197,6.942781),(10.527502,6.947484),(10.533186,6.948828),(10.537424,6.952135),(10.543315,7.028719),(10.55179,7.06634),(10.564192,7.102668),(10.578661,7.130832),(10.597161,7.107268),(10.602536,7.058072),(10.620623,7.043757),(10.646978,7.035076),(10.716947,6.998127),(10.799113,6.967328),(10.831876,6.94521),(10.848206,6.905316),(10.857404,6.859789),(10.877454,6.816097),(10.909391,6.784264),(11.002615,6.767262),(11.036721,6.740546),(11.055945,6.700367),(11.059045,6.652722),(11.057392,6.613008),(11.060596,6.573967),(11.077442,6.496736),(11.097079,6.449117),(11.113512,6.434001),(11.140384,6.43028),(11.202276,6.436739),(11.231748,6.439815),(11.237122,6.438058),(11.248285,6.431004),(11.255519,6.42997),(11.261514,6.432554),(11.272159,6.442037),(11.27588,6.444207),(11.286835,6.443225),(11.308539,6.437903),(11.319495,6.437283),(11.344196,6.443122),(11.369828,6.455757),(11.389361,6.473921),(11.395666,6.496736),(11.401764,6.538181),(11.41675,6.572003),(11.443105,6.593268),(11.482585,6.597169),(11.509767,6.612311),(11.533435,6.645099),(11.562374,6.712485),(11.568885,6.739099),(11.571469,6.766229),(11.566611,6.784187),(11.544597,6.80894),(11.538086,6.8239),(11.543667,6.850694),(11.561754,6.876067),(11.623249,6.932291),(11.681126,6.96862),(11.684847,6.973839),(11.688464,6.986913),(11.692495,6.991616),(11.697249,6.992856),(11.707481,6.991822),(11.718643,6.994458),(11.73425,6.995078),(11.741071,6.997507),(11.746859,7.005362),(11.748616,7.014973),(11.75151,7.023965),(11.766392,7.033525),(11.80887,7.071921),(11.820343,7.078794),(11.833985,7.08298),(11.845147,7.081946),(11.854139,7.077812),(11.862614,7.075435),(11.872226,7.079362),(11.881321,7.102048),(11.868918,7.127111),(11.829954,7.169383),(11.780242,7.241058),(11.766186,7.252943),(11.742415,7.257439),(11.736627,7.263279),(11.744585,7.272167),(11.762465,7.285551),(11.782722,7.304517),(11.844734,7.396397),(11.903545,7.453557),(11.966174,7.514426),(11.992839,7.55401),(12.008548,7.564862),(12.021054,7.576231),(12.024981,7.596592),(12.010719,7.655244),(12.009065,7.676328),(12.012166,7.698343),(12.018987,7.718858),(12.054954,7.783919),(12.154276,7.921326),(12.192103,7.960652),(12.197787,7.975173),(12.1951,7.99171),(12.188175,8.016256),(12.182698,8.054652),(12.182594,8.093486),(12.188279,8.117774),(12.229103,8.175497),(12.233713,8.188455),(12.236751,8.196994),(12.237682,8.21689),(12.221765,8.29766),(12.219285,8.343161),(12.227036,8.386311),(12.249981,8.418764),(12.271788,8.427781),(12.310235,8.421348),(12.331319,8.424293),(12.343205,8.432742),(12.351163,8.44424),(12.357571,8.456358),(12.365116,8.466564),(12.395191,8.487338),(12.403873,8.496537),(12.403253,8.524235),(12.400462,8.538421),(12.377001,8.59511),(12.368836,8.609579),(12.396328,8.600768),(12.410591,8.598494),(12.42444,8.599786),(12.440253,8.606608),(12.451829,8.614695),(12.464334,8.621154),(12.482524,8.623247),(12.495547,8.619553),(12.527793,8.604851),(12.542572,8.602008),(12.557972,8.605677),(12.660395,8.659318),(12.678171,8.678696),(12.692848,8.710891),(12.701633,8.739158),(12.708867,8.750914),(12.720236,8.756469),(12.734499,8.755901),(12.747211,8.753627),(12.759613,8.75342),(12.772946,8.759053),(12.794547,8.788612),(12.805709,8.831503),(12.82824,9.019967),(12.821005,9.056425),(12.822142,9.09681),(12.842192,9.14443),(12.888391,9.226725),(12.894592,9.243959),(12.898416,9.262433),(12.899347,9.302017),(12.891285,9.33199),(12.88157,9.352221),(12.853148,9.356639),(12.848394,9.359947),(12.855422,9.378111),(12.862036,9.382891),(12.920741,9.410486),(12.929009,9.416119),(12.940068,9.4271),(12.969006,9.464075),(12.982442,9.474591),(13.051689,9.504511),(13.13034,9.516526),(13.195453,9.542209),(13.223461,9.613135),(13.228422,9.677912),(13.241341,9.745324),(13.251056,9.76925),(13.260461,9.785709),(13.262942,9.801728),(13.251987,9.824234),(13.222944,9.854128),(13.212712,9.870148),(13.211059,9.892756),(13.218707,9.913039),(13.242271,9.949756),(13.246405,9.973475),(13.242478,9.992673),(13.230489,10.025358),(13.230179,10.045331),(13.247956,10.079412),(13.281339,10.092098),(13.359784,10.100547),(13.378387,10.108609),(13.392672,10.116957),(13.401952,10.122381),(13.423242,10.138478),(13.434921,10.153412),(13.450837,10.187157),(13.453008,10.200515),(13.451354,10.212117),(13.444533,10.232477),(13.444843,10.245474),(13.467167,10.307589),(13.501274,10.496337),(13.538791,10.62142),(13.566283,10.679013),(13.744411,10.930497),(13.749839,10.942442),(13.75702,10.958247),(13.750406,10.996203),(13.75485,11.016719),(13.765909,11.033901),(13.782032,11.047518),(13.820066,11.069274),(13.832054,11.084803),(13.849211,11.124568),(13.873189,11.166503),(13.906262,11.208025),(13.943882,11.245723),(13.98233,11.276264),(14.013129,11.276367),(14.052506,11.265153),(14.122579,11.235724),(14.14325,11.232726),(14.165471,11.238333),(14.186762,11.249237),(14.204642,11.26213),(14.232133,11.290294),(14.244329,11.295436),(14.271304,11.29864),(14.279159,11.301844),(14.368249,11.383001),(14.387059,11.393388),(14.446281,11.411682),(14.467261,11.423852),(14.503951,11.456304),(14.524932,11.468836),(14.576609,11.487336),(14.593765,11.496431),(14.605754,11.514725),(14.616193,11.538677),(14.623841,11.563481),(14.627561,11.584359),(14.627148,11.60968),(14.62136,11.629782),(14.610198,11.646835),(14.593868,11.66301),(14.588597,11.669676),(14.585083,11.676808),(14.580949,11.683267),(14.573508,11.687711),(14.556455,11.687505),(14.552424,11.689003),(14.543329,11.701096),(14.541882,11.709829),(14.546533,11.718614),(14.583223,11.766363),(14.590665,11.783158),(14.612059,11.88496),(14.623427,11.916535),(14.627148,11.950073),(14.626941,11.957204),(14.625184,11.968108),(14.606271,12.011258),(14.604307,12.03043),(14.622187,12.042005),(14.619913,12.052495),(14.637173,12.124222),(14.643168,12.13585),(14.648129,12.141844),(14.650609,12.148097),(14.669936,12.167424),(14.668283,12.178069),(14.663425,12.187578),(14.651539,12.193779),(14.643168,12.190627),(14.629318,12.183495),(14.616296,12.178948),(14.610612,12.183547),(14.6041,12.204321),(14.588287,12.217188),(14.568134,12.22773),(14.548497,12.241579),(14.558315,12.246902),(14.562139,12.248401),(14.562139,12.255842),(14.551184,12.260441),(14.521521,12.282352),(14.51439,12.28938),(14.512426,12.29863),(14.517594,12.313358),(14.51439,12.323538),(14.487105,12.337801),(14.42313,12.353149),(14.217561,12.359298),(14.202161,12.362502),(14.188932,12.370409),(14.179837,12.385602),(14.179113,12.397281),(14.185108,12.427873),(14.185418,12.447045),(14.180216,12.46353),(14.1787,12.468336),(14.177356,12.545592),(14.121132,12.81179),(14.064908,13.077988),(14.418169,13.081141),(14.435429,13.070289),(14.481041,13.000508),(14.482144,12.99882),(14.496303,12.983808),(14.504675,12.969003),(14.507672,12.95244),(14.506122,12.93208),(14.490619,12.886346),(14.490102,12.873608),(14.500437,12.859113),(14.53103,12.836246),(14.549013,12.818211),(14.549013,12.780461),(14.55108,12.771573),(14.554801,12.766896),(14.560692,12.766224)] +Republic of Congo [(17.627275,3.626317),(17.70913,3.626421),(17.714505,3.627506),(17.72608,3.631847),(17.733212,3.632208),(17.73993,3.629159),(17.749645,3.618075),(17.755949,3.614509),(17.765148,3.614354),(17.784475,3.61823),(17.793156,3.617506),(17.808349,3.608592),(17.821165,3.593994),(17.83057,3.575674),(17.835324,3.555831),(17.842146,3.540147),(17.856408,3.537305),(17.875322,3.542731),(17.913562,3.561334),(17.919247,3.565597),(17.924518,3.563453),(17.959865,3.541077),(17.969476,3.537511),(17.981879,3.538803),(18.013091,3.55397),(18.047094,3.563143),(18.082028,3.563453),(18.116444,3.552007),(18.134014,3.534824),(18.146727,3.494904),(18.159852,3.480305),(18.181556,3.477386),(18.202537,3.487333),(18.220004,3.503947),(18.231579,3.521156),(18.235403,3.530923),(18.242535,3.561127),(18.248529,3.574899),(18.255867,3.577225),(18.264859,3.574744),(18.275918,3.574382),(18.355603,3.581462),(18.361597,3.58017),(18.372863,3.574537),(18.379891,3.574382),(18.383715,3.578),(18.387849,3.591668),(18.392293,3.595854),(18.403662,3.597353),(18.420612,3.596371),(18.429707,3.600221),(18.448,3.618023),(18.459059,3.631382),(18.472081,3.632053),(18.497093,3.61146),(18.513422,3.592237),(18.55435,3.526375),(18.570267,3.489607),(18.582462,3.477386),(18.626387,3.476869),(18.634552,3.449222),(18.642407,3.323829),(18.631141,3.17898),(18.62184,3.156656),(18.619669,3.14477),(18.613055,3.128182),(18.597345,3.114643),(18.562102,3.096815),(18.541431,3.08281),(18.528409,3.064775),(18.495336,2.966073),(18.479626,2.941372),(18.475802,2.931192),(18.471771,2.909229),(18.467327,2.898894),(18.44924,2.873004),(18.425159,2.822154),(18.421852,2.808822),(18.418338,2.781743),(18.393223,2.713686),(18.316742,2.584339),(18.313745,2.575968),(18.303513,2.572557),(18.246152,2.518917),(18.233026,2.502587),(18.225171,2.486464),(18.214113,2.427657),(18.207808,2.407968),(18.199126,2.389106),(18.187964,2.370916),(18.174012,2.336138),(18.16378,2.321048),(18.146727,2.315932),(18.142696,2.3057),(18.118615,2.276968),(18.111173,2.265289),(18.072416,2.160024),(18.072416,2.145193),(18.078307,2.114807),(18.080787,2.084163),(18.076033,1.988484),(18.081718,1.942415),(18.081511,1.92655),(18.078307,1.90929),(18.068178,1.876217),(18.066111,1.858983),(18.073656,1.572334),(18.071382,1.551457),(18.012264,1.421956),(18.006683,1.402396),(18.002033,1.365783),(17.966996,1.253723),(17.963379,1.191453),(17.956247,1.171661),(17.914803,1.102001),(17.892478,1.077403),(17.873255,1.039628),(17.86664,1.016632),(17.878216,0.947178),(17.877906,0.867907),(17.907671,0.740473),(17.907568,0.713084),(17.892582,0.63588),(17.893202,0.607664),(17.8993,0.583273),(17.91842,0.535214),(17.933096,0.527049),(17.943638,0.510823),(17.949943,0.491496),(17.95201,0.474339),(17.945498,0.377291),(17.939917,0.361271),(17.854031,0.241072),(17.77538,0.026408),(17.757086,-0.009456),(17.716365,-0.195801),(17.713678,-0.220916),(17.716262,-0.246237),(17.740756,-0.346179),(17.749541,-0.523429),(17.741997,-0.533351),(17.728044,-0.553092),(17.664172,-0.612726),(17.658694,-0.619754),(17.654457,-0.627506),(17.652493,-0.642182),(17.650943,-0.646316),(17.647636,-0.649933),(17.635853,-0.658512),(17.623038,-0.673291),(17.60216,-0.688691),(17.545863,-0.756491),(17.411474,-0.918341),(17.385429,-0.942422),(17.364965,-0.967227),(17.357317,-0.973531),(17.330446,-0.986554),(17.327655,-0.991721),(17.308018,-1.014976),(17.297683,-1.021074),(17.245386,-1.035853),(17.194847,-1.042984),(17.175416,-1.048255),(17.10865,-1.075644),(17.060488,-1.089183),(17.028655,-1.094454),(17.022557,-1.097038),(17.012015,-1.104273),(17.005918,-1.106753),(17.003127,-1.112851),(16.979563,-1.140239),(16.940495,-1.174759),(16.909179,-1.211139),(16.862567,-1.248863),(16.839726,-1.262506),(16.833215,-1.269017),(16.828667,-1.276252),(16.817815,-1.304157),(16.794664,-1.345498),(16.779265,-1.382395),(16.762728,-1.405856),(16.725521,-1.47996),(16.692552,-1.522955),(16.669504,-1.56936),(16.655971,-1.59029),(16.636224,-1.62083),(16.628886,-1.637263),(16.623822,-1.6538),(16.622478,-1.665169),(16.623099,-1.699172),(16.617207,-1.728731),(16.604185,-1.754052),(16.524971,-1.858535),(16.522536,-1.861746),(16.517162,-1.873735),(16.513958,-1.887377),(16.507757,-1.890271),(16.49029,-1.903604),(16.474787,-1.910115),(16.470033,-1.912699),(16.460938,-1.920864),(16.445642,-1.940501),(16.382596,-2.002202),(16.340222,-2.034138),(16.284411,-2.087572),(16.256093,-2.106795),(16.231288,-2.129016),(16.206793,-2.160952),(16.194598,-2.182036),(16.187363,-2.204567),(16.188603,-2.227718),(16.19005,-2.23547),(16.189947,-2.241878),(16.176924,-2.286836),(16.174857,-2.303062),(16.178268,-2.318462),(16.187466,-2.332311),(16.189843,-2.337479),(16.191704,-2.346884),(16.192324,-2.39515),(16.225603,-2.635239),(16.204519,-2.782723),(16.180852,-2.85414),(16.178165,-2.868093),(16.177028,-2.882459),(16.183981,-2.940449),(16.188293,-2.976406),(16.184469,-3.026119),(16.189843,-3.082343),(16.185709,-3.136397),(16.189947,-3.153036),(16.199248,-3.171847),(16.199455,-3.194791),(16.193357,-3.238406),(16.198628,-3.25949),(16.210411,-3.271065),(16.222089,-3.279127),(16.227464,-3.289876),(16.225603,-3.313233),(16.220746,-3.331733),(16.207723,-3.361913),(16.158424,-3.447282),(16.137857,-3.500715),(16.115533,-3.544227),(16.053314,-3.619985),(16.012697,-3.702254),(16.005255,-3.724784),(15.991096,-3.738944),(15.974249,-3.786486),(15.94314,-3.840746),(15.936112,-3.848498),(15.930324,-3.858626),(15.912134,-3.917434),(15.888019,-3.940523),(15.882989,-3.945339),(15.844231,-3.965597),(15.799996,-3.978826),(15.755141,-3.985647),(15.711216,-3.992158),(15.566832,-4.038047),(15.549056,-4.046212),(15.533759,-4.057994),(15.52115,-4.076804),(15.490351,-4.175196),(15.484977,-4.183878),(15.462859,-4.207132),(15.458932,-4.21385),(15.45025,-4.217261),(15.425446,-4.23018),(15.386585,-4.244339),(15.275274,-4.300357),(15.25574,-4.313069),(15.228352,-4.324851),(15.20396,-4.339011),(15.193418,-4.358751),(15.188044,-4.372187),(15.150678,-4.425151),(15.09792,-4.499931),(15.076113,-4.520085),(15.022783,-4.54706),(15.014618,-4.558015),(15.00821,-4.571038),(14.931005,-4.646899),(14.849047,-4.783738),(14.841399,-4.800171),(14.831167,-4.815054),(14.815457,-4.827973),(14.768431,-4.84823),(14.702182,-4.889571),(14.672727,-4.899907),(14.634486,-4.903627),(14.623324,-4.899493),(14.592111,-4.88058),(14.579606,-4.876342),(14.575058,-4.873655),(14.566893,-4.860529),(14.562139,-4.855878),(14.553871,-4.855155),(14.532477,-4.856188),(14.528033,-4.852157),(14.519868,-4.841305),(14.501471,-4.840685),(14.481937,-4.845853),(14.470052,-4.852157),(14.449484,-4.873965),(14.437289,-4.880166),(14.418169,-4.883163),(14.400702,-4.886264),(14.396464,-4.855878),(14.412588,-4.778157),(14.408763,-4.767822),(14.403699,-4.75883),(14.399668,-4.749321),(14.399048,-4.737539),(14.401529,-4.728134),(14.409177,-4.710564),(14.410934,-4.701056),(14.406903,-4.676044),(14.395844,-4.660128),(14.380962,-4.646175),(14.365769,-4.627262),(14.3575,-4.589124),(14.349956,-4.566904),(14.350783,-4.559049),(14.358947,-4.544579),(14.37476,-4.530213),(14.412588,-4.514504),(14.424576,-4.502308),(14.435739,-4.486702),(14.452482,-4.467995),(14.466538,-4.448048),(14.469742,-4.429341),(14.46323,-4.422623),(14.428607,-4.400402),(14.409074,-4.377561),(14.392744,-4.352756),(14.386026,-4.338287),(14.385716,-4.332913),(14.389126,-4.327538),(14.393467,-4.313172),(14.395224,-4.300357),(14.395328,-4.289711),(14.392847,-4.281753),(14.387059,-4.277102),(14.368559,-4.278446),(14.325461,-4.301803),(14.279986,-4.312759),(14.259625,-4.326918),(14.222212,-4.359784),(14.184694,-4.377458),(14.146351,-4.38986),(14.058397,-4.400505),(14.021087,-4.415388),(13.991631,-4.455076),(13.989874,-4.45797),(13.987704,-4.46014),(13.971788,-4.471612),(13.954941,-4.491869),(13.944502,-4.498071),(13.934581,-4.498484),(13.905436,-4.4901),(13.904401,-4.489802),(13.87629,-4.491663),(13.867091,-4.489286),(13.856136,-4.479674),(13.84208,-4.453422),(13.832881,-4.441227),(13.810454,-4.426654),(13.78999,-4.424587),(13.726531,-4.446704),(13.714956,-4.453009),(13.711028,-4.464481),(13.721777,-4.561012),(13.71816,-4.580339),(13.702605,-4.62075),(13.699091,-4.642661),(13.712475,-4.685656),(13.705861,-4.694338),(13.698368,-4.693511),(13.690099,-4.691134),(13.681934,-4.695371),(13.6778,-4.706327),(13.680591,-4.724723),(13.67532,-4.731751),(13.666535,-4.732682),(13.643694,-4.726274),(13.633979,-4.725654),(13.613101,-4.739193),(13.591397,-4.779397),(13.57986,-4.783031),(13.570727,-4.785908),(13.558634,-4.780431),(13.538894,-4.759967),(13.526182,-4.754282),(13.51471,-4.755936),(13.482257,-4.77485),(13.492385,-4.783531),(13.496416,-4.792109),(13.493522,-4.799654),(13.482257,-4.805545),(13.430787,-4.843372),(13.403192,-4.876859),(13.39265,-4.885334),(13.371359,-4.841719),(13.364124,-4.806889),(13.35875,-4.794797),(13.349345,-4.785598),(13.334565,-4.777537),(13.274001,-4.755833),(13.255811,-4.743947),(13.208785,-4.703123),(13.18212,-4.686069),(13.172405,-4.676148),(13.160002,-4.643385),(13.142122,-4.61734),(13.134061,-4.602354),(13.112357,-4.576929),(13.087966,-4.579513),(13.071532,-4.60163),(13.073703,-4.635323),(13.027194,-4.612172),(12.961565,-4.533831),(12.921981,-4.502308),(12.902447,-4.480191),(12.884464,-4.432131),(12.869891,-4.411978),(12.854285,-4.403089),(12.842296,-4.40433),(12.830307,-4.409704),(12.814804,-4.412908),(12.801058,-4.410014),(12.782656,-4.400071),(12.775426,-4.396165),(12.761681,-4.391204),(12.737909,-4.40495),(12.726541,-4.427997),(12.718479,-4.451872),(12.70494,-4.467995),(12.686853,-4.47833),(12.670523,-4.491353),(12.656571,-4.507372),(12.634867,-4.54768),(12.623808,-4.559255),(12.608098,-4.565043),(12.497201,-4.5853),(12.429091,-4.607521),(12.414105,-4.608865),(12.387026,-4.605454),(12.377621,-4.619407),(12.378862,-4.662298),(12.374107,-4.683176),(12.332353,-4.765858),(12.321914,-4.778157),(12.307651,-4.783635),(12.273752,-4.787149),(12.258559,-4.790766),(12.244089,-4.796347),(12.235201,-4.803995),(12.222592,-4.780637),(12.213497,-4.769165),(12.204092,-4.763481),(12.192206,-4.763481),(12.187555,-4.768028),(12.15717,-4.870554),(12.130815,-4.912929),(12.018072,-5.0086),(12.009608,-5.019631),(11.994314,-5.005792),(11.980479,-4.989435),(11.957856,-4.951918),(11.920258,-4.906427),(11.895728,-4.882645),(11.886241,-4.855239),(11.830586,-4.797022),(11.82021,-4.7848),(11.819266,-4.77916),(11.824069,-4.77236),(11.829961,-4.773533),(11.843319,-4.788783),(11.848424,-4.786044),(11.853137,-4.773918),(11.850367,-4.752839),(11.824067,-4.718683),(11.781633,-4.680409),(11.776906,-4.667878),(11.777688,-4.657701),(11.801321,-4.657938),(11.820163,-4.637281),(11.824624,-4.614767),(11.806409,-4.577118),(11.692982,-4.463491),(11.589122,-4.374688),(11.497895,-4.294041),(11.450587,-4.26473),(11.401403,-4.221366),(11.382498,-4.191013),(11.377696,-4.184666),(11.364757,-4.162774),(11.362071,-4.15309),(11.363129,-4.131117),(11.362153,-4.119806),(11.358246,-4.111912),(11.270181,-4.041725),(11.172425,-3.977474),(11.139095,-3.9531),(11.114016,-3.936856),(11.129623,-3.907857),(11.196091,-3.728815),(11.212524,-3.697293),(11.238569,-3.675072),(11.272676,-3.652954),(11.302441,-3.62846),(11.334688,-3.608616),(11.375822,-3.600348),(11.413959,-3.587635),(11.436283,-3.559006),(11.45499,-3.528207),(11.482585,-3.509294),(11.532712,-3.516528),(11.569815,-3.54495),(11.64919,-3.673315),(11.665933,-3.691401),(11.687638,-3.69874),(11.742105,-3.691712),(11.762155,-3.693985),(11.819723,-3.710418),(11.838326,-3.710935),(11.840808,-3.709989),(11.858377,-3.703287),(11.879977,-3.687164),(11.897651,-3.66608),(11.905505,-3.643549),(11.898477,-3.622362),(11.879254,-3.612026),(11.855586,-3.604378),(11.834915,-3.592079),(11.824994,-3.571202),(11.827784,-3.548051),(11.884835,-3.413279),(11.898374,-3.389198),(11.941472,-3.356952),(11.954908,-3.335454),(11.944366,-3.303208),(11.905712,-3.285121),(11.858273,-3.272099),(11.821893,-3.254839),(11.781585,-3.221663),(11.760501,-3.209054),(11.703864,-3.185386),(11.696113,-3.179598),(11.687534,-3.17102),(11.685674,-3.167196),(11.687328,-3.161511),(11.688258,-3.092265),(11.693219,-3.074695),(11.706448,-3.04989),(11.716886,-3.043586),(11.730632,-3.044723),(11.75368,-3.042345),(11.778381,-3.027153),(11.778381,-3.005655),(11.763705,-2.982608),(11.687638,-2.901786),(11.653118,-2.851659),(11.636788,-2.833263),(11.616841,-2.826751),(11.588419,-2.835433),(11.547905,-2.863855),(11.530748,-2.866749),(11.52558,-2.843288),(11.535566,-2.804996),(11.537466,-2.797709),(11.61033,-2.678853),(11.619528,-2.653532),(11.624386,-2.632758),(11.624386,-2.611984),(11.619011,-2.586456),(11.609606,-2.564028),(11.584285,-2.523617),(11.576533,-2.502533),(11.57612,-2.485067),(11.583355,-2.42967),(11.579737,-2.407656),(11.55824,-2.349365),(11.566198,-2.329727),(11.568368,-2.329107),(11.605369,-2.330348),(11.655908,-2.345644),(11.669654,-2.352672),(11.675855,-2.360423),(11.679886,-2.368795),(11.687534,-2.377683),(11.721331,-2.404142),(11.739521,-2.413753),(11.756057,-2.415097),(11.772697,-2.405382),(11.806597,-2.374169),(11.828818,-2.365281),(11.864888,-2.35815),(11.907056,-2.34461),(11.938372,-2.329107),(11.948707,-2.335205),(11.966794,-2.348538),(12.000693,-2.390602),(12.031286,-2.411583),(12.062292,-2.414994),(12.45927,-2.329934),(12.447901,-2.30792),(12.455136,-2.275571),(12.468572,-2.241154),(12.475496,-2.212422),(12.468365,-2.171081),(12.470225,-2.156301),(12.477357,-2.141108),(12.49534,-2.11279),(12.499784,-2.09553),(12.46082,-2.077857),(12.440046,-2.045817),(12.431468,-2.005406),(12.423097,-1.897609),(12.426921,-1.88407),(12.438083,-1.886654),(12.450009,-1.899298),(12.468985,-1.919417),(12.486555,-1.924894),(12.499474,-1.917866),(12.503815,-1.907738),(12.504539,-1.896886),(12.506296,-1.888204),(12.512393,-1.875492),(12.517354,-1.86898),(12.523452,-1.863296),(12.572441,-1.83043),(12.58319,-1.826502),(12.632386,-1.825159),(12.674967,-1.842832),(12.741014,-1.890672),(12.745454,-1.893888),(12.787725,-1.907531),(12.804572,-1.919107),(12.816148,-1.943498),(12.838162,-2.016052),(12.847153,-2.037239),(12.852941,-2.044577),(12.868547,-2.059873),(12.872992,-2.065868),(12.876919,-2.088709),(12.875162,-2.089122),(12.875162,-2.093773),(12.874128,-2.099767),(12.876299,-2.104935),(12.895109,-2.109793),(12.894489,-2.11558),(12.890562,-2.122195),(12.888701,-2.126949),(12.884464,-2.134494),(12.882707,-2.140798),(12.885084,-2.147413),(12.89821,-2.160229),(12.902034,-2.167257),(12.902757,-2.177592),(12.907098,-2.195369),(12.921361,-2.194852),(12.945649,-2.18245),(12.95433,-2.190925),(12.973037,-2.221517),(12.982442,-2.232989),(12.987507,-2.259964),(12.990194,-2.268026),(12.997325,-2.275674),(13.003423,-2.275467),(13.008177,-2.276501),(13.010658,-2.287766),(13.002286,-2.296655),(12.996705,-2.304819),(12.994638,-2.314948),(12.993914,-2.323526),(12.991124,-2.332311),(12.987093,-2.340683),(12.982442,-2.347711),(12.97128,-2.357116),(12.966113,-2.366418),(12.969006,-2.372412),(12.982442,-2.371689),(12.994008,-2.360123),(13.012105,-2.342026),(13.025024,-2.338202),(13.049828,-2.342647),(13.114321,-2.371895),(13.135198,-2.37696),(13.146153,-2.374686),(13.165273,-2.363524),(13.176849,-2.361974),(13.186668,-2.364144),(13.361024,-2.428843),(13.3788,-2.43091),(13.398024,-2.426156),(13.419728,-2.42967),(13.424896,-2.429773),(13.438952,-2.425432),(13.44536,-2.427086),(13.453731,-2.439385),(13.458899,-2.441039),(13.469441,-2.435044),(13.473988,-2.426983),(13.476779,-2.417681),(13.482257,-2.408069),(13.492179,-2.398457),(13.524631,-2.37603),(13.533106,-2.367658),(13.547679,-2.349365),(13.557601,-2.340476),(13.569487,-2.334482),(13.593361,-2.326834),(13.603386,-2.320012),(13.60783,-2.311124),(13.610724,-2.289937),(13.617442,-2.279601),(13.69351,-2.205911),(13.701571,-2.194749),(13.705241,-2.18431),(13.706791,-2.16457),(13.709478,-2.153511),(13.72002,-2.133564),(13.740897,-2.102455),(13.743171,-2.09708),(13.746375,-2.09832),(13.756917,-2.105865),(13.770663,-2.119094),(13.782755,-2.138008),(13.791437,-2.159092),(13.800532,-2.200433),(13.823269,-2.246838),(13.835568,-2.265235),(13.853862,-2.283839),(13.86058,-2.293657),(13.863887,-2.321459),(13.871639,-2.328797),(13.882181,-2.333862),(13.892516,-2.3412),(13.906158,-2.359803),(13.901921,-2.366314),(13.890035,-2.373652),(13.875876,-2.403831),(13.855102,-2.41427),(13.847661,-2.423055),(13.846937,-2.461606),(13.8458,-2.466567),(13.86213,-2.480933),(13.884971,-2.488477),(13.909466,-2.489718),(13.930446,-2.485377),(13.947706,-2.474938),(13.957318,-2.470597),(13.967033,-2.470597),(13.976232,-2.477315),(13.979229,-2.495609),(13.985637,-2.5015),(13.993285,-2.501603),(14.039277,-2.487237),(14.045582,-2.4861),(14.055607,-2.486927),(14.071006,-2.495816),(14.080928,-2.49995),(14.090023,-2.498606),(14.096018,-2.491061),(14.100553,-2.478065),(14.106766,-2.460262),(14.115241,-2.451374),(14.124853,-2.443829),(14.131881,-2.435147),(14.131468,-2.408896),(14.136015,-2.398767),(14.14418,-2.390189),(14.1633,-2.373963),(14.172395,-2.367865),(14.182317,-2.363317),(14.230066,-2.352155),(14.234407,-2.354946),(14.226966,-2.323113),(14.151208,-2.259034),(14.148004,-2.224824),(14.161543,-2.214282),(14.195857,-2.201777),(14.209189,-2.187204),(14.209396,-2.179866),(14.203195,-2.161986),(14.204332,-2.152167),(14.209706,-2.147413),(14.226966,-2.141315),(14.233787,-2.134494),(14.238438,-2.120231),(14.244019,-2.067521),(14.250634,-2.047781),(14.251667,-2.037859),(14.24681,-2.029384),(14.238645,-2.02339),(14.233477,-2.018222),(14.232857,-2.012021),(14.238128,-2.002616),(14.237611,-1.991143),(14.240092,-1.982255),(14.245053,-1.974814),(14.252184,-1.967579),(14.368571,-1.92212),(14.37073,-1.921277),(14.397291,-1.906808),(14.404526,-1.893062),(14.396878,-1.849447),(14.397498,-1.840972),(14.403596,-1.815237),(14.406696,-1.735552),(14.413104,-1.713951),(14.425197,-1.700515),(14.448761,-1.686253),(14.441113,-1.679638),(14.420029,-1.676124),(14.402976,-1.670853),(14.390883,-1.630339),(14.371453,-1.619487),(14.364839,-1.612045),(14.37383,-1.604087),(14.394294,-1.596852),(14.403699,-1.592201),(14.413208,-1.585277),(14.419926,-1.575148),(14.423956,-1.563573),(14.430364,-1.554891),(14.463127,-1.54869),(14.462714,-1.5336),(14.451552,-1.515617),(14.438426,-1.502595),(14.451035,-1.473656),(14.452688,-1.449574),(14.456306,-1.440169),(14.467881,-1.429007),(14.480594,-1.420842),(14.487725,-1.40937),(14.482144,-1.388596),(14.447004,-1.365342),(14.432328,-1.350149),(14.426333,-1.331029),(14.429124,-1.31997),(14.436049,-1.312735),(14.444317,-1.306327),(14.451552,-1.298163),(14.457133,-1.287621),(14.46075,-1.278009),(14.464781,-1.255581),(14.465814,-1.224369),(14.464161,-1.215377),(14.456409,-1.202458),(14.439435,-1.185733),(14.435325,-1.181684),(14.428297,-1.169488),(14.427987,-1.16091),(14.433568,-1.14365),(14.434395,-1.135072),(14.430984,-1.123393),(14.420339,-1.101792),(14.391814,-1.023347),(14.39202,-1.008981),(14.402562,-0.987691),(14.407523,-0.944489),(14.412794,-0.921545),(14.428194,-0.896947),(14.445867,-0.877516),(14.457133,-0.856122),(14.452895,-0.825737),(14.446177,-0.800312),(14.44597,-0.775714),(14.451552,-0.751219),(14.492169,-0.663369),(14.498991,-0.630916),(14.489999,-0.600944),(14.466538,-0.552678),(14.454239,-0.539553),(14.414448,-0.512164),(14.39233,-0.482398),(14.358637,-0.461314),(14.320603,-0.444468),(14.292698,-0.436406),(14.275542,-0.439094),(14.260039,-0.446432),(14.244742,-0.451599),(14.228516,-0.447775),(14.210223,-0.440334),(14.193066,-0.440437),(14.17653,-0.446122),(14.159683,-0.455113),(14.157926,-0.417699),(14.150588,-0.376462),(14.138289,-0.336361),(14.121443,-0.302151),(14.095398,-0.276623),(14.058811,-0.258846),(14.01871,-0.252645),(13.98233,-0.262257),(13.975095,-0.252542),(13.967033,-0.245824),(13.957318,-0.242),(13.921558,-0.237865),(13.913807,-0.240553),(13.909983,-0.247167),(13.907295,-0.254402),(13.903058,-0.258846),(13.889829,-0.263704),(13.883421,-0.264944),(13.877426,-0.2605),(13.831228,-0.205413),(13.832158,-0.177094),(13.8427,-0.152289),(13.888054,-0.092088),(13.900474,-0.075602),(13.910706,-0.065886),(13.921145,-0.052967),(13.920111,-0.042425),(13.914943,-0.031263),(13.91298,-0.016587),(13.917217,-0.006665),(13.931377,0.011628),(13.932927,0.022067),(13.925072,0.034366),(13.913083,0.036536),(13.901404,0.036846),(13.894893,0.043668),(13.890656,0.115911),(13.885901,0.140303),(13.876186,0.171308),(13.871225,0.196423),(13.875773,0.220298),(13.909776,0.270941),(13.945226,0.350419),(13.966517,0.373053),(14.040414,0.413774),(14.059121,0.435272),(14.063048,0.455942),(14.056847,0.476406),(14.045582,0.497283),(14.075967,0.539451),(14.125473,0.546169),(14.181594,0.539865),(14.231823,0.542552),(14.245259,0.54772),(14.250944,0.551854),(14.254664,0.557125),(14.328768,0.621204),(14.335383,0.642598),(14.33838,0.693912),(14.367319,0.735512),(14.413414,0.775044),(14.447624,0.81623),(14.44101,0.862791),(14.437599,0.875142),(14.445144,0.883255),(14.457029,0.890334),(14.466228,0.899636),(14.468088,0.913227),(14.46044,0.921237),(14.436565,0.933277),(14.417548,0.950589),(14.400805,0.970329),(14.386749,0.99224),(14.375691,1.015598),(14.360084,1.066758),(14.346442,1.087118),(14.298486,1.109236),(14.28288,1.130113),(14.274715,1.155641),(14.275748,1.231089),(14.273061,1.257237),(14.258178,1.319662),(14.252184,1.330824),(14.241435,1.339196),(14.230066,1.34395),(14.221488,1.349479),(14.219939,1.355018),(14.218387,1.360564),(14.206502,1.362838),(14.198957,1.368316),(14.192549,1.374956),(14.183868,1.380847),(14.14449,1.391622),(14.12444,1.393585),(14.106456,1.388934),(14.070696,1.375111),(14.049509,1.376403),(14.033799,1.387643),(14.01902,1.402138),(14.00083,1.413016),(13.98357,1.41684),(13.794744,1.434436),(13.780585,1.431025),(13.779758,1.426271),(13.770353,1.400432),(13.758157,1.376506),(13.75485,1.374336),(13.744101,1.370279),(13.741104,1.371313),(13.729425,1.37692),(13.724361,1.377953),(13.71754,1.375369),(13.705551,1.36599),(13.699091,1.362786),(13.680694,1.359401),(13.671496,1.358781),(13.662091,1.359195),(13.642247,1.357386),(13.628088,1.348136),(13.615065,1.337439),(13.579202,1.323486),(13.556361,1.29279),(13.543442,1.283489),(13.509955,1.277287),(13.479776,1.277132),(13.448874,1.283075),(13.41394,1.295529),(13.398748,1.296925),(13.37694,1.294444),(13.357406,1.28907),(13.349345,1.281577),(13.342937,1.263852),(13.325987,1.259304),(13.307797,1.25672),(13.289194,1.233983),(13.2709,1.226024),(13.25023,1.221787),(13.215813,1.224371),(13.195453,1.221115),(13.184911,1.22251),(13.184885,1.222623),(13.18181,1.236463),(13.172301,1.242871),(13.160313,1.247729),(13.150184,1.256617),(13.169201,1.258581),(13.176642,1.27088),(13.180363,1.284832),(13.188321,1.291447),(13.202377,1.293411),(13.219327,1.299198),(13.23359,1.30881),(13.242995,1.328861),(13.249093,1.332375),(13.251263,1.337646),(13.242891,1.34979),(13.239584,1.356507),(13.239171,1.364181),(13.239791,1.372346),(13.238447,1.41963),(13.239481,1.427976),(13.223461,1.438001),(13.205478,1.48637),(13.184911,1.496886),(13.190905,1.511072),(13.189665,1.52474),(13.182637,1.536548),(13.171268,1.545256),(13.164447,1.53784),(13.145946,1.56342),(13.129617,1.592462),(13.146773,1.612254),(13.149977,1.636284),(13.143983,1.681811),(13.147807,1.702869),(13.154628,1.721653),(13.157522,1.739146),(13.150184,1.756302),(13.162793,1.76364),(13.173025,1.776947),(13.180673,1.792011),(13.191008,1.828727),(13.192455,1.844746),(13.188321,1.85658),(13.183154,1.864048),(13.175092,1.882108),(13.162173,1.899833),(13.166307,1.904381),(13.178193,1.907792),(13.184911,1.92345),(13.191732,1.935077),(13.19845,1.943112),(13.205064,1.949339),(13.210232,1.956316),(13.212299,1.966419),(13.206615,1.985151),(13.206925,1.993575),(13.21602,1.997166),(13.221291,2.000835),(13.239481,2.02073),(13.245475,2.025304),(13.281132,2.044967),(13.291364,2.068945),(13.294878,2.101087),(13.294568,2.161058),(13.466547,2.159508),(13.620336,2.158112),(13.662266,2.157761),(13.823993,2.156407),(14.002793,2.154805),(14.16175,2.15341),(14.266963,2.152428),(14.276265,2.153565),(14.320293,2.17067),(14.383649,2.162091),(14.399358,2.153151),(14.418685,2.135271),(14.432948,2.132119),(14.438736,2.133979),(14.4592,2.146537),(14.538058,2.163383),(14.54705,2.166536),(14.550254,2.175166),(14.54798,2.184364),(14.547773,2.193666),(14.557075,2.202399),(14.562139,2.208807),(14.587874,2.201727),(14.620947,2.16483),(14.644821,2.154185),(14.636346,2.13832),(14.646062,2.133359),(14.672003,2.134341),(14.685956,2.125866),(14.705696,2.105532),(14.720476,2.099589),(14.713654,2.12398),(14.720889,2.127597),(14.747864,2.113205),(14.733498,2.102018),(14.727297,2.099589),(14.737116,2.096075),(14.747554,2.097186),(14.756339,2.099589),(14.761403,2.099589),(14.76254,2.092535),(14.76161,2.070185),(14.764814,2.065456),(14.826309,2.072252),(14.841192,2.075921),(14.84822,2.085197),(14.850184,2.097367),(14.850184,2.109795),(14.857005,2.115944),(14.871474,2.101656),(14.8846,2.082096),(14.887804,2.072252),(14.907338,2.058894),(14.896589,2.030937),(14.892455,2.00639),(14.932142,2.003341),(14.953846,2.005822),(14.963045,2.010421),(14.971003,2.034451),(14.980718,2.033107),(15.028261,1.995306),(15.04366,1.990862),(15.06309,1.997166),(15.074873,1.979364),(15.091616,1.984428),(15.107636,2.000835),(15.117764,2.01701),(15.123862,2.01701),(15.138538,2.011506),(15.151664,2.040988),(15.1836,2.029335),(15.197036,2.034967),(15.212642,2.039618),(15.233726,2.031298),(15.238687,2.025304),(15.244165,2.010059),(15.248092,2.003341),(15.25357,2.000318),(15.287573,1.987787),(15.295428,1.981534),(15.301112,1.973757),(15.303283,1.966419),(15.301939,1.953319),(15.300182,1.94766),(15.301629,1.943578),(15.309484,1.935077),(15.314341,1.93425),(15.337802,1.92376),(15.337389,1.92146),(15.349171,1.923295),(15.367981,1.932855),(15.388135,1.939547),(15.439192,1.969829),(15.48291,1.97585),(15.526628,1.967814),(15.611791,1.942544),(15.706772,1.931976),(15.711113,1.927377),(15.721552,1.921615),(15.734057,1.916706),(15.757415,1.912985),(15.76465,1.908722),(15.80289,1.859965),(15.815396,1.853428),(15.842061,1.844152),(15.865936,1.828468),(15.875651,1.823766),(15.882369,1.816712),(15.884952,1.801648),(15.889913,1.793277),(15.901799,1.793742),(15.915235,1.798961),(15.92588,1.804749),(15.928981,1.788962),(15.94376,1.781624),(15.963191,1.77736),(15.98045,1.770591),(15.990786,1.776172),(16.002775,1.775913),(16.013833,1.771314),(16.021998,1.763795),(16.026339,1.752297),(16.024892,1.742479),(16.021998,1.733048),(16.021998,1.72279),(16.030473,1.705401),(16.069851,1.654551),(16.114809,1.719069),(16.123594,1.721601),(16.145092,1.714315),(16.15584,1.719069),(16.159044,1.734805),(16.135066,1.845315),(16.101373,1.932803),(16.083493,1.963008),(16.074915,1.970604),(16.068714,1.973602),(16.06489,1.97895),(16.063753,2.015873),(16.06644,2.025485),(16.081736,2.046827),(16.08153,2.055638),(16.078119,2.063441),(16.076672,2.072252),(16.076155,2.07282),(16.075535,2.075456),(16.075535,2.079952),(16.076672,2.08592),(16.079669,2.090261),(16.084113,2.091605),(16.088144,2.09176),(16.090315,2.092742),(16.092485,2.106901),(16.089798,2.116151),(16.08556,2.12491),(16.083493,2.137752),(16.085767,2.149172),(16.097756,2.171548),(16.104371,2.193562),(16.12039,2.203329),(16.140647,2.199815),(16.159251,2.18209),(16.199455,2.212166),(16.207723,2.22307),(16.202349,2.23201),(16.196665,2.236454),(16.248031,2.345594),(16.293506,2.442074),(16.325649,2.510494),(16.371124,2.606922),(16.413706,2.697201),(16.427492,2.726493),(16.450603,2.775594),(16.479128,2.836314),(16.483779,2.860395),(16.474994,2.878378),(16.460525,2.894605),(16.448329,2.913467),(16.445538,2.95765),(16.484192,3.031909),(16.490807,3.067824),(16.483159,3.090148),(16.47272,3.110612),(16.464762,3.1318),(16.465485,3.156501),(16.477061,3.179394),(16.511477,3.227246),(16.517162,3.248692),(16.517782,3.273238),(16.542793,3.336154),(16.551682,3.419767),(16.567701,3.464389),(16.598501,3.501674),(16.639428,3.528597),(16.686351,3.542214),(16.709398,3.543712),(16.729552,3.542214),(16.811924,3.521672),(16.833008,3.522861),(16.852645,3.532809),(16.854609,3.541335),(16.851818,3.551903),(16.853162,3.560094),(16.867838,3.561541),(16.877243,3.559164),(16.895537,3.552368),(16.904735,3.550637),(16.932434,3.553919),(16.942252,3.553092),(16.953208,3.546891),(16.960546,3.538441),(16.968607,3.533481),(16.98194,3.537976),(16.989691,3.539475),(17.003127,3.537718),(17.009225,3.538131),(17.017596,3.5418),(17.028862,3.551541),(17.035787,3.556141),(17.052426,3.56397),(17.061418,3.56614),(17.088393,3.564435),(17.102139,3.566605),(17.129011,3.57707),(17.142757,3.580842),(17.182858,3.579602),(17.197224,3.58172),(17.213967,3.589291),(17.222959,3.598515),(17.231123,3.609109),(17.244973,3.620607),(17.259442,3.625904),(17.272258,3.62456),(17.298096,3.615904),(17.334373,3.618514),(17.355767,3.638435),(17.375714,3.663447),(17.414489,3.683415),(17.427494,3.690112),(17.442687,3.701274),(17.458913,3.708276),(17.481858,3.704762),(17.486198,3.700292),(17.490126,3.68714),(17.494983,3.683213),(17.508936,3.681766),(17.513484,3.679182),(17.550484,3.648151),(17.586761,3.632234),(17.627275,3.626317)] +Coral Sea Islands [(154.391287,-21.030043),(154.38852,-21.029067),(154.391287,-21.028741),(154.391287,-21.030043)] +Curaçao [(-68.780751,12.097805),(-68.745229,12.062242),(-68.739735,12.053046),(-68.748647,12.047024),(-68.769846,12.042914),(-68.794749,12.041327),(-68.814809,12.043158),(-68.841176,12.055487),(-68.893422,12.090522),(-68.944732,12.105618),(-68.977773,12.124579),(-69.007436,12.148179),(-69.020253,12.169745),(-69.027211,12.19009),(-69.043609,12.196682),(-69.062896,12.198432),(-69.078603,12.20425),(-69.091908,12.219875),(-69.12267,12.269029),(-69.134389,12.27733),(-69.148101,12.28441),(-69.159535,12.293362),(-69.164296,12.306952),(-69.161977,12.342841),(-69.163808,12.361884),(-69.171742,12.378892),(-69.166127,12.387844),(-69.161204,12.391506),(-69.156239,12.390611),(-69.150624,12.385728),(-69.107777,12.367825),(-69.089589,12.356879),(-69.071523,12.341376),(-69.060414,12.322577),(-69.049957,12.276109),(-69.040761,12.256049),(-69.004018,12.221666),(-68.961293,12.201361),(-68.835276,12.171047),(-68.82079,12.16234),(-68.814809,12.149604),(-68.811838,12.12934),(-68.804026,12.117011),(-68.780751,12.097805)] +Czech Republic [(14.397808,51.013115),(14.425817,51.020944),(14.462094,51.019652),(14.473462,51.023372),(14.482144,51.037196),(14.487932,51.028721),(14.490102,51.022701),(14.493513,51.016706),(14.502918,51.008516),(14.51532,51.003038),(14.542295,50.998749),(14.554594,50.992651),(14.566687,50.983401),(14.574335,50.975494),(14.577435,50.965727),(14.575575,50.95069),(14.567824,50.938649),(14.555835,50.924283),(14.550357,50.912087),(14.561829,50.906351),(14.617123,50.920872),(14.629215,50.920717),(14.634589,50.9094),(14.628802,50.896119),(14.611852,50.870953),(14.608338,50.853073),(14.613195,50.84558),(14.647922,50.839379),(14.662185,50.834366),(14.700425,50.815969),(14.737529,50.810698),(14.759233,50.810181),(14.775356,50.812972),(14.785071,50.820052),(14.79458,50.831627),(14.810393,50.858447),(14.831683,50.857982),(14.867857,50.86439),(14.982062,50.859067),(14.984129,50.867697),(14.982889,50.902424),(14.981752,50.905266),(14.981132,50.90909),(14.982062,50.914671),(14.984852,50.918082),(14.994671,50.92511),(14.997771,50.930174),(14.996635,50.959216),(14.981442,50.973221),(14.965215,50.981334),(14.960978,50.992651),(14.961081,50.992651),(14.965629,50.996062),(14.970693,50.998697),(14.976377,51.000402),(14.982062,51.001177),(14.996531,51.007844),(15.001182,51.012443),(15.003973,51.020685),(15.02299,51.009652),(15.073632,51.002624),(15.082107,50.992754),(15.09389,50.985416),(15.107946,50.981024),(15.119211,50.982471),(15.122518,50.992651),(15.122518,50.992754),(15.13151,51.005828),(15.144429,51.011564),(15.156108,51.007844),(15.160759,50.992651),(15.170164,50.977975),(15.227111,50.977406),(15.253776,50.969035),(15.269796,50.952653),(15.268763,50.94299),(15.260081,50.932499),(15.253053,50.914103),(15.25605,50.899892),(15.265352,50.88227),(15.277134,50.865734),(15.28778,50.854881),(15.307727,50.844753),(15.325813,50.839689),(15.341006,50.83173),(15.352995,50.812972),(15.353305,50.803257),(15.350515,50.793232),(15.349688,50.783723),(15.356096,50.775455),(15.368579,50.772949),(15.370255,50.772613),(15.381314,50.780002),(15.390822,50.790648),(15.400124,50.797986),(15.441775,50.800208),(15.641866,50.755766),(15.653235,50.75096),(15.666464,50.738093),(15.673803,50.733545),(15.684345,50.731426),(15.76744,50.744191),(15.792245,50.742692),(15.794415,50.735871),(15.797619,50.729773),(15.848159,50.675151),(15.854567,50.673704),(15.882265,50.674221),(15.941486,50.68838),(15.958023,50.686881),(15.971459,50.678613),(15.984481,50.662904),(15.993163,50.649364),(15.998641,50.635567),(15.996367,50.623681),(15.982001,50.61624),(15.980037,50.612984),(15.97921,50.60978),(15.979934,50.606628),(15.982001,50.603631),(16.024479,50.608592),(16.086491,50.64678),(16.128658,50.644042),(16.160284,50.628642),(16.175477,50.624095),(16.192324,50.626575),(16.204519,50.636342),(16.211754,50.649106),(16.219092,50.659131),(16.232011,50.660888),(16.268288,50.660423),(16.300948,50.6551),(16.331644,50.644042),(16.416806,50.586629),(16.425901,50.567561),(16.394482,50.559344),(16.398306,50.551799),(16.398306,50.548492),(16.395516,50.545701),(16.391175,50.539914),(16.389624,50.534849),(16.388281,50.52715),(16.388384,50.521258),(16.391175,50.521827),(16.382596,50.514179),(16.362029,50.501208),(16.352624,50.492785),(16.335468,50.490356),(16.303428,50.49604),(16.287719,50.492785),(16.279967,50.479866),(16.264981,50.471649),(16.247411,50.464983),(16.232011,50.456766),(16.226534,50.455371),(16.217335,50.45165),(16.211237,50.451289),(16.216095,50.440178),(16.217955,50.437129),(16.198008,50.440023),(16.190153,50.424158),(16.199559,50.406278),(16.232011,50.402609),(16.24493,50.376823),(16.249685,50.371035),(16.2625,50.36442),(16.269839,50.365454),(16.27697,50.369433),(16.288649,50.371862),(16.334227,50.371862),(16.343736,50.36995),(16.350764,50.360648),(16.351487,50.351346),(16.35066,50.342251),(16.353244,50.333518),(16.371021,50.318377),(16.415566,50.307938),(16.437787,50.297965),(16.452153,50.284994),(16.477578,50.255332),(16.492047,50.242722),(16.50476,50.227995),(16.535042,50.207738),(16.545894,50.188824),(16.557263,50.154718),(16.566668,50.142212),(16.584238,50.127432),(16.618654,50.10702),(16.660616,50.093016),(16.701233,50.094928),(16.732033,50.121955),(16.754253,50.13229),(16.766449,50.1434),(16.777301,50.15694),(16.795284,50.174406),(16.817712,50.186757),(16.837556,50.188617),(16.857606,50.187739),(16.869762,50.189729),(16.880964,50.191563),(16.890369,50.196937),(16.907009,50.211768),(16.918998,50.217091),(16.927783,50.217298),(16.946283,50.21306),(16.955275,50.213474),(16.957755,50.217143),(16.957548,50.229235),(16.960339,50.231974),(16.975015,50.231819),(16.98101,50.229183),(16.98566,50.223137),(16.996306,50.212905),(17.008398,50.20996),(17.014806,50.218486),(17.012842,50.231664),(16.99982,50.242722),(16.998373,50.26701),(16.987831,50.284942),(16.969641,50.297758),(16.945249,50.306905),(16.926543,50.319255),(16.916724,50.338634),(16.909283,50.359925),(16.897914,50.378218),(16.865874,50.408449),(16.865771,50.422401),(16.892953,50.432943),(16.915794,50.431083),(16.944005,50.420267),(16.958789,50.414598),(16.98194,50.416355),(17.084672,50.397958),(17.095628,50.393669),(17.118882,50.381164),(17.131698,50.376823),(17.145444,50.376719),(17.175933,50.38075),(17.187612,50.378476),(17.185442,50.375686),(17.188852,50.364834),(17.195053,50.351915),(17.201048,50.343233),(17.210866,50.336412),(17.24611,50.322149),(17.269881,50.317757),(17.316803,50.318635),(17.337474,50.313002),(17.319077,50.308248),(17.321867,50.304476),(17.325381,50.301117),(17.329515,50.298223),(17.334063,50.295691),(17.332823,50.282668),(17.334786,50.270008),(17.341711,50.259724),(17.355044,50.253264),(17.365896,50.271558),(17.388013,50.272643),(17.409821,50.261326),(17.419122,50.242722),(17.424187,50.240552),(17.429561,50.239777),(17.434832,50.2405),(17.44,50.242722),(17.469352,50.265563),(17.516998,50.268354),(17.606398,50.258225),(17.629549,50.262101),(17.646705,50.271093),(17.676368,50.297396),(17.681949,50.305561),(17.684533,50.312382),(17.691044,50.315069),(17.707994,50.311039),(17.713575,50.30768),(17.731971,50.291763),(17.734452,50.28949),(17.734969,50.286802),(17.734245,50.283805),(17.731971,50.280653),(17.721119,50.261946),(17.719156,50.252799),(17.721429,50.242722),(17.731971,50.236005),(17.747578,50.217504),(17.738173,50.202363),(17.717915,50.191098),(17.675334,50.174716),(17.648669,50.167998),(17.600403,50.16681),(17.589448,50.163244),(17.58211,50.153167),(17.584177,50.145881),(17.632753,50.106348),(17.648359,50.101801),(17.658488,50.102989),(17.666963,50.106142),(17.677608,50.107744),(17.690734,50.10547),(17.717915,50.096788),(17.731971,50.094876),(17.732385,50.093894),(17.732592,50.092964),(17.732385,50.092189),(17.731971,50.091466),(17.72267,50.08635),(17.719466,50.080872),(17.722566,50.075136),(17.731971,50.06909),(17.74303,50.060563),(17.749852,50.049504),(17.755433,50.037154),(17.763287,50.025216),(17.774553,50.015191),(17.839355,49.973643),(17.875735,49.968682),(17.912116,49.975814),(17.941571,49.992764),(17.959761,49.995812),(17.999862,49.996588),(18.032418,50.00284),(18.037483,50.007233),(18.035726,50.017207),(18.028698,50.024131),(18.020119,50.024286),(18.012161,50.022684),(18.00689,50.024131),(18.002446,50.046765),(18.019074,50.044087),(18.033245,50.041805),(18.091639,50.017207),(18.085128,49.998758),(18.098151,49.989043),(18.162023,49.98124),(18.177216,49.975814),(18.208738,49.958295),(18.22052,49.954885),(18.243982,49.951732),(18.255867,49.946048),(18.260105,49.94057),(18.267029,49.925067),(18.27261,49.918298),(18.292454,49.907808),(18.306923,49.909668),(18.334932,49.925429),(18.333795,49.927135),(18.332452,49.928271),(18.330695,49.92884),(18.328524,49.92884),(18.368832,49.932044),(18.407486,49.923155),(18.481797,49.896645),(18.505051,49.896697),(18.544428,49.912975),(18.559208,49.907187),(18.565409,49.889049),(18.562929,49.873701),(18.567269,49.861454),(18.593831,49.852204),(18.566339,49.831585),(18.566753,49.804765),(18.584116,49.774379),(18.60768,49.74296),(18.617706,49.713866),(18.62401,49.706373),(18.637343,49.700327),(18.668142,49.69857),(18.682404,49.695779),(18.695427,49.688854),(18.715064,49.673817),(18.727673,49.668907),(18.742246,49.669683),(18.757852,49.674075),(18.773458,49.675832),(18.788444,49.668597),(18.792579,49.660794),(18.799297,49.626378),(18.803947,49.616766),(18.81573,49.599299),(18.820174,49.590256),(18.83454,49.547623),(18.837434,49.526952),(18.833196,49.510261),(18.792269,49.509537),(18.773562,49.504886),(18.732531,49.480288),(18.704522,49.479255),(18.675583,49.485043),(18.64282,49.495791),(18.635896,49.496721),(18.628971,49.495791),(18.600446,49.485973),(18.556211,49.490159),(18.535643,49.481684),(18.530476,49.473467),(18.527995,49.454864),(18.522931,49.446079),(18.514663,49.440601),(18.481797,49.429077),(18.439215,49.395074),(18.416788,49.385462),(18.387642,49.389751),(18.385162,49.342261),(18.361586,49.330191),(18.324597,49.311255),(18.190031,49.276942),(18.160576,49.2587),(18.136495,49.233068),(18.117788,49.202579),(18.105075,49.169765),(18.101458,49.142945),(18.10163,49.136928),(18.102905,49.09225),(18.09629,49.070288),(18.075516,49.047188),(18.046061,49.029153),(18.012885,49.019128),(17.959244,49.021867),(17.93506,49.019386),(17.914079,49.010498),(17.90085,48.993031),(17.894649,48.9782),(17.886897,48.947246),(17.878733,48.933552),(17.860336,48.921718),(17.841215,48.920994),(17.820131,48.923371),(17.795533,48.920581),(17.77941,48.911744),(17.744891,48.872574),(17.727217,48.86291),(17.535084,48.812991),(17.498497,48.816763),(17.467905,48.838105),(17.453332,48.842756),(17.429561,48.838157),(17.411225,48.830216),(17.391734,48.821776),(17.374371,48.819605),(17.260269,48.857794),(17.21221,48.866062),(17.167458,48.859758),(17.113715,48.83392),(17.10462,48.824618),(17.098728,48.805756),(17.084362,48.793715),(17.049946,48.774027),(17.025348,48.746328),(16.974808,48.649874),(16.963336,48.635947),(16.947523,48.623157),(16.945043,48.604166),(16.910523,48.63078),(16.896674,48.696977),(16.873006,48.718991),(16.856573,48.719818),(16.818125,48.710775),(16.798902,48.709224),(16.780505,48.713772),(16.744332,48.729637),(16.729035,48.733099),(16.691001,48.732065),(16.675085,48.733926),(16.661959,48.740023),(16.654725,48.751857),(16.651004,48.766223),(16.643149,48.778264),(16.624029,48.78338),(16.605529,48.784827),(16.545791,48.796299),(16.528737,48.803534),(16.519539,48.805601),(16.510341,48.804774),(16.492254,48.79971),(16.481919,48.7994),(16.453083,48.80219),(16.43572,48.794542),(16.384974,48.737078),(16.374018,48.730308),(16.358309,48.727259),(16.352727,48.728448),(16.339498,48.735579),(16.318724,48.733512),(16.317588,48.73284),(16.177751,48.746535),(16.085354,48.742866),(16.032334,48.758059),(15.931771,48.806428),(15.930324,48.811389),(15.930324,48.818313),(15.925053,48.822602),(15.908103,48.819709),(15.90707,48.830251),(15.899629,48.834746),(15.888363,48.835056),(15.875754,48.833093),(15.885986,48.842033),(15.877614,48.841671),(15.870173,48.843893),(15.859218,48.849164),(15.840097,48.850094),(15.833276,48.852006),(15.828315,48.857122),(15.824284,48.869421),(15.818497,48.872315),(15.787904,48.872263),(15.779222,48.870868),(15.743669,48.858466),(15.726823,48.854952),(15.703775,48.854952),(15.681347,48.858466),(15.603729,48.887353),(15.544187,48.902612),(15.521254,48.908489),(15.471851,48.936704),(15.450354,48.944817),(15.405912,48.954687),(15.357853,48.97081),(15.335529,48.974996),(15.28871,48.975358),(15.283749,48.977632),(15.279615,48.982593),(15.27455,48.986727),(15.266902,48.986675),(15.262872,48.982593),(15.260391,48.969157),(15.257084,48.963886),(15.243234,48.95293),(15.238067,48.95076),(15.161792,48.937221),(15.141949,48.937479),(15.148563,48.951742),(15.148977,48.965333),(15.144739,48.978924),(15.137401,48.993031),(15.059576,48.997217),(15.003973,49.009774),(14.982062,49.007914),(14.978858,49.00626),(14.977308,49.002902),(14.977308,48.998251),(14.978238,48.992825),(14.964595,48.971741),(14.964182,48.943267),(14.968316,48.912674),(14.968213,48.885028),(14.947025,48.822396),(14.93979,48.809787),(14.938137,48.80281),(14.940101,48.796506),(14.944441,48.788599),(14.948886,48.78214),(14.951056,48.780331),(14.939584,48.762813),(14.919327,48.761573),(14.86765,48.775577),(14.815457,48.780331),(14.800367,48.776507),(14.794476,48.766999),(14.790446,48.754855),(14.78042,48.743124),(14.775356,48.724004),(14.722749,48.693411),(14.703836,48.673103),(14.700219,48.646102),(14.700735,48.615535),(14.695671,48.589542),(14.69114,48.586535),(14.675621,48.576235),(14.659187,48.576959),(14.651333,48.583496),(14.645442,48.592901),(14.634693,48.602332),(14.628182,48.603288),(14.612885,48.599748),(14.605134,48.600316),(14.60193,48.604528),(14.601827,48.611194),(14.600586,48.617576),(14.594179,48.621323),(14.578779,48.620496),(14.548807,48.610936),(14.53382,48.608714),(14.522038,48.610626),(14.482144,48.624475),(14.458166,48.643182),(14.443593,48.636516),(14.421166,48.597061),(14.405353,48.586286),(14.353366,48.571429),(14.333213,48.560706),(14.325358,48.558639),(14.315746,48.557916),(14.216527,48.58117),(14.07483,48.591712),(14.040827,48.601169),(14.032456,48.60613),(14.015196,48.620393),(14.010855,48.62587),(14.006204,48.639513),(14.008064,48.642407),(14.013749,48.643802),(14.020467,48.653155),(14.023464,48.654602),(14.028322,48.653982),(14.032869,48.654912),(14.034729,48.661165),(14.032146,48.667263),(14.026151,48.670054),(14.019227,48.671914),(14.014162,48.675066),(14.007754,48.683283),(13.991115,48.700181),(13.98233,48.706485),(13.915047,48.73098),(13.893136,48.743021),(13.874946,48.752426),(13.855929,48.759299),(13.815725,48.76643),(13.796191,48.779814),(13.747925,48.843376),(13.724671,48.867303),(13.710615,48.87247),(13.673356,48.876346),(13.654443,48.882237),(13.637389,48.893451),(13.621783,48.909057),(13.611138,48.927247),(13.608657,48.946161),(13.590467,48.944817),(13.573414,48.951018),(13.556464,48.959958),(13.538894,48.967038),(13.522395,48.969342),(13.51595,48.970242),(13.5021,48.966056),(13.492592,48.955049),(13.482257,48.937634),(13.458899,48.945024),(13.427273,48.959958),(13.398541,48.977683),(13.384175,48.993031),(13.383555,49.021092),(13.372393,49.038507),(13.329915,49.066929),(13.299529,49.093645),(13.287333,49.10057),(13.267283,49.105634),(13.206821,49.107495),(13.178503,49.118347),(13.162586,49.135142),(13.14946,49.15483),(13.055823,49.238184),(13.04342,49.242784),(13.043214,49.242887),(13.043214,49.242939),(13.011278,49.267795),(13.00673,49.277097),(13.005387,49.28676),(12.999806,49.294925),(12.982442,49.299628),(12.95433,49.31911),(12.939861,49.326758),(12.922911,49.332701),(12.88467,49.339573),(12.870925,49.336731),(12.875369,49.323864),(12.856662,49.32221),(12.797751,49.327843),(12.777907,49.332545),(12.762094,49.343242),(12.729331,49.391147),(12.709177,49.404737),(12.663082,49.418897),(12.643548,49.42949),(12.632179,49.44396),(12.627218,49.460186),(12.624325,49.493001),(12.622981,49.509847),(12.61554,49.513775),(12.604998,49.512793),(12.593732,49.515015),(12.58288,49.522405),(12.575025,49.529898),(12.568721,49.538838),(12.562313,49.550827),(12.558282,49.562557),(12.553631,49.584726),(12.546603,49.595579),(12.536061,49.603123),(12.512187,49.61165),(12.501955,49.619711),(12.502678,49.62214),(12.507432,49.629995),(12.499474,49.632527),(12.496891,49.633871),(12.505365,49.646118),(12.504642,49.659399),(12.496374,49.669993),(12.482524,49.674695),(12.449245,49.68503),(12.433949,49.6918),(12.419583,49.700223),(12.398912,49.719499),(12.388577,49.732314),(12.383616,49.742856),(12.395398,49.757894),(12.436739,49.769263),(12.452655,49.779702),(12.455859,49.796135),(12.456376,49.817115),(12.462474,49.831223),(12.482524,49.827244),(12.489863,49.842695),(12.51291,49.870239),(12.520972,49.885535),(12.524072,49.904965),(12.517871,49.9122),(12.503608,49.915766),(12.462681,49.931269),(12.463818,49.942121),(12.470742,49.955608),(12.468158,49.970233),(12.451312,49.980568),(12.414518,49.983048),(12.399222,49.992764),(12.398189,49.992764),(12.24688,50.044957),(12.243676,50.051313),(12.243469,50.060408),(12.241402,50.07064),(12.232514,50.08051),(12.218044,50.088572),(12.202025,50.094514),(12.187865,50.102834),(12.179184,50.117976),(12.178564,50.132962),(12.185592,50.155699),(12.182698,50.170737),(12.17505,50.182623),(12.163784,50.193785),(12.13929,50.211045),(12.089887,50.230837),(12.079552,50.242722),(12.092057,50.254815),(12.102393,50.259156),(12.109111,50.263806),(12.110971,50.276622),(12.10725,50.290885),(12.099189,50.299773),(12.076141,50.315173),(12.101344,50.31398),(12.149315,50.311711),(12.168538,50.302977),(12.17443,50.293727),(12.17412,50.276571),(12.178047,50.268767),(12.189209,50.262463),(12.203782,50.259569),(12.232514,50.259104),(12.239645,50.256572),(12.242953,50.252954),(12.242436,50.248355),(12.237992,50.242722),(12.236441,50.242567),(12.235098,50.242257),(12.233754,50.241689),(12.232514,50.240965),(12.229827,50.239053),(12.228897,50.237038),(12.22993,50.234816),(12.232514,50.232491),(12.249981,50.221173),(12.254321,50.217401),(12.258455,50.21089),(12.260212,50.20505),(12.261246,50.199883),(12.273235,50.172339),(12.283363,50.162211),(12.300417,50.160815),(12.314369,50.167327),(12.314369,50.176215),(12.308582,50.186912),(12.305584,50.199314),(12.308685,50.217091),(12.314059,50.226496),(12.3338,50.242722),(12.336487,50.258587),(12.344652,50.26639),(12.355814,50.271403),(12.367183,50.279051),(12.398189,50.315173),(12.408937,50.321994),(12.438289,50.332536),(12.450175,50.339357),(12.453792,50.340701),(12.462784,50.340494),(12.466815,50.34189),(12.468985,50.345559),(12.468365,50.349486),(12.467022,50.352845),(12.466815,50.354912),(12.469502,50.359408),(12.471569,50.364472),(12.475083,50.369433),(12.482524,50.373567),(12.510223,50.38876),(12.550531,50.396357),(12.625358,50.399922),(12.678792,50.393721),(12.691814,50.394651),(12.702976,50.401524),(12.725094,50.423435),(12.737909,50.431548),(12.754239,50.435321),(12.770259,50.435941),(12.788139,50.434339),(12.79434,50.435889),(12.808396,50.441832),(12.817388,50.44302),(12.825759,50.441418),(12.918363,50.4054),(12.952573,50.40416),(12.960631,50.409234),(12.982442,50.42297),(12.996602,50.433667),(13.003113,50.451909),(13.009624,50.492681),(13.017892,50.49635),(13.026264,50.497642),(13.034532,50.496505),(13.042284,50.492785),(13.051069,50.491131),(13.06037,50.490614),(13.069775,50.491079),(13.07887,50.492681),(13.078974,50.492681),(13.079181,50.492785),(13.107396,50.498986),(13.160106,50.497022),(13.184704,50.508753),(13.19907,50.525341),(13.232349,50.58203),(13.25178,50.580893),(13.268006,50.573658),(13.284646,50.568956),(13.305627,50.575777),(13.316272,50.596034),(13.321853,50.60239),(13.35937,50.61934),(13.365365,50.623474),(13.365985,50.627092),(13.368775,50.628332),(13.380971,50.62549),(13.386345,50.621614),(13.400401,50.606576),(13.407016,50.601305),(13.42934,50.594329),(13.447944,50.597274),(13.464893,50.607093),(13.482257,50.620891),(13.492179,50.624456),(13.498173,50.629159),(13.499103,50.635205),(13.493315,50.643215),(13.509955,50.651225),(13.523288,50.66218),(13.527215,50.675668),(13.51564,50.691016),(13.556567,50.706725),(13.601939,50.712151),(13.691753,50.711841),(13.711028,50.71427),(13.749062,50.72321),(13.770663,50.724605),(13.816552,50.72135),(13.834535,50.723675),(13.863474,50.735147),(13.869572,50.735251),(13.875359,50.736542),(13.882181,50.742744),(13.882697,50.748015),(13.88032,50.755043),(13.87908,50.763518),(13.883318,50.773233),(13.892516,50.780416),(13.900991,50.780622),(13.910706,50.778762),(13.923315,50.779951),(13.933547,50.784808),(13.948843,50.797211),(13.959592,50.802068),(13.979126,50.804755),(14.015713,50.801758),(14.034936,50.802585),(14.190792,50.847905),(14.202988,50.85514),(14.221281,50.872607),(14.232133,50.879376),(14.2681,50.88413),(14.346545,50.880203),(14.375897,50.895964),(14.381892,50.920872),(14.355227,50.930639),(14.31833,50.937512),(14.292802,50.95348),(14.293732,50.96397),(14.302207,50.967691),(14.303757,50.969707),(14.28381,50.974822),(14.250013,50.977613),(14.238335,50.982471),(14.249497,50.992651),(14.263553,51.021435),(14.287531,51.036834),(14.319363,51.040012),(14.35657,51.032338),(14.364115,51.027998),(14.369386,51.022442),(14.375897,51.01699),(14.386749,51.01327),(14.397808,51.013115)] +Djibouti [(43.240733,11.48786),(43.188815,11.407764),(42.923715,10.998787),(42.908109,11.004187),(42.898084,10.995687),(42.888059,10.983568),(42.873279,10.978246),(42.860153,10.980416),(42.835452,10.987444),(42.794111,10.991604),(42.771787,10.996462),(42.754837,11.010544),(42.729619,11.06501),(42.710395,11.072116),(42.686521,11.073046),(42.615621,11.08966),(42.608145,11.089088),(42.569732,11.086146),(42.479712,11.059119),(42.413256,11.015944),(42.391758,11.005893),(42.376669,11.006668),(42.361166,11.011887),(42.338532,11.015504),(42.305872,11.004601),(42.297294,11.003774),(42.279414,11.004394),(42.270835,11.003516),(42.235179,10.987703),(42.221639,10.984344),(42.202726,10.98455),(42.151359,10.996203),(42.096272,10.990261),(42.069401,10.981501),(42.038395,10.950444),(42.0108,10.943597),(41.954162,10.941271),(41.947341,10.938532),(41.942793,10.933546),(41.937522,10.929825),(41.928841,10.931065),(41.922846,10.936026),(41.920262,10.941943),(41.916852,10.947059),(41.79872,10.970675),(41.773811,10.980054),(41.766523,10.989466),(41.761306,10.996203),(41.779289,11.024677),(41.785594,11.067388),(41.787971,11.259727),(41.775672,11.368429),(41.749834,11.483383),(41.74911,11.537953),(41.778669,11.628645),(41.792415,11.704455),(41.808228,11.736236),(41.823007,11.746106),(41.862282,11.763056),(41.872203,11.775871),(41.877784,11.790134),(41.886259,11.796025),(41.897525,11.799384),(41.911477,11.805947),(41.925327,11.816437),(41.936386,11.827445),(41.97468,11.88091),(42.057308,11.996271),(42.097719,12.070169),(42.108778,12.082106),(42.132343,12.093475),(42.140301,12.105826),(42.155494,12.142257),(42.288715,12.321006),(42.319205,12.386377),(42.379459,12.465907),(42.430929,12.520322),(42.448499,12.523371),(42.475681,12.516343),(42.521569,12.496241),(42.678252,12.360022),(42.691482,12.378832),(42.696187,12.380126),(42.727758,12.388806),(42.741401,12.408081),(42.749876,12.417073),(42.779745,12.422602),(42.792251,12.429165),(42.798038,12.456088),(42.788737,12.487456),(42.785223,12.517222),(42.828838,12.557633),(42.852092,12.611738),(42.868835,12.626155),(42.877723,12.62507),(42.890126,12.615407),(42.900358,12.616389),(43.117686,12.707913),(43.133962,12.697211),(43.143321,12.679511),(43.151134,12.659735),(43.161794,12.642727),(43.259613,12.533352),(43.283214,12.496527),(43.297374,12.482001),(43.312999,12.477688),(43.329356,12.488756),(43.329356,12.453559),(43.331228,12.436713),(43.336192,12.419908),(43.344086,12.406155),(43.353201,12.395209),(43.360525,12.383002),(43.363536,12.365302),(43.364757,12.327135),(43.367849,12.306871),(43.374034,12.292955),(43.411388,12.241767),(43.414317,12.224921),(43.411388,12.166653),(43.418712,12.091254),(43.413341,12.059272),(43.398774,12.029527),(43.377126,12.004828),(43.350434,11.987942),(43.34254,11.985663),(43.315684,11.981106),(43.288341,11.967434),(43.268403,11.963813),(43.225434,11.962877),(43.206554,11.957831),(43.174001,11.935004),(43.097179,11.84455),(43.09197,11.841295),(43.086029,11.838853),(43.076182,11.834703),(43.069184,11.830268),(43.064708,11.823432),(43.060883,11.809556),(43.055512,11.803616),(43.041515,11.798529),(42.986827,11.796088),(42.972504,11.790839),(42.95753,11.780463),(42.942638,11.77383),(42.915538,11.783596),(42.896495,11.780585),(42.803396,11.747992),(42.777192,11.732245),(42.75408,11.707953),(42.684093,11.582261),(42.677419,11.573676),(42.667979,11.568549),(42.636974,11.559556),(42.627696,11.559068),(42.60377,11.563381),(42.577403,11.562405),(42.569021,11.563381),(42.563487,11.567206),(42.554047,11.580268),(42.548595,11.583808),(42.526866,11.582465),(42.515147,11.574123),(42.514985,11.567206),(42.528087,11.570217),(42.532481,11.548489),(42.532481,11.547471),(42.533051,11.523505),(42.538748,11.502997),(42.571625,11.490465),(42.591563,11.47248),(42.60377,11.46776),(42.617686,11.470282),(42.633556,11.484809),(42.644786,11.488227),(42.653494,11.485907),(42.662852,11.481635),(42.672537,11.479722),(42.681651,11.484524),(42.687511,11.497219),(42.680675,11.504788),(42.670421,11.509955),(42.665294,11.51557),(42.674083,11.532131),(42.694102,11.545966),(42.739757,11.563381),(42.807465,11.571275),(42.829112,11.576972),(42.839529,11.584459),(42.847504,11.592719),(42.855805,11.595771),(42.866954,11.587592),(42.875173,11.583686),(42.900727,11.584052),(43.040538,11.585924),(43.06186,11.590155),(43.081798,11.589545),(43.103363,11.576972),(43.123057,11.581488),(43.133556,11.595282),(43.141124,11.608588),(43.151866,11.611762),(43.157888,11.601304),(43.172211,11.542873),(43.173106,11.541653),(43.183849,11.526557),(43.19516,11.518297),(43.226329,11.501899),(43.240733,11.48786)] +Dominica [(-61.362864,15.201809),(-61.374094,15.20482),(-61.376129,15.212836),(-61.372792,15.237209),(-61.37328,15.266425),(-61.372792,15.270697),(-61.378285,15.28205),(-61.39094,15.296291),(-61.393219,15.308295),(-61.395009,15.333075),(-61.399566,15.351142),(-61.413726,15.380561),(-61.415679,15.387641),(-61.41808,15.405951),(-61.421213,15.41474),(-61.444203,15.436835),(-61.447865,15.445136),(-61.449778,15.454657),(-61.454254,15.46483),(-61.460032,15.472886),(-61.465566,15.476142),(-61.472076,15.481391),(-61.474273,15.493476),(-61.475209,15.517768),(-61.47936,15.525458),(-61.484853,15.530341),(-61.488922,15.535712),(-61.488881,15.545071),(-61.483998,15.551581),(-61.467275,15.562974),(-61.462148,15.572984),(-61.469065,15.574286),(-61.481191,15.578559),(-61.488881,15.57925),(-61.480621,15.59101),(-61.468984,15.633857),(-61.449208,15.633083),(-61.437245,15.632636),(-61.425933,15.628485),(-61.413726,15.619574),(-61.397572,15.596625),(-61.384633,15.588365),(-61.36974,15.595933),(-61.35733,15.598293),(-61.307688,15.57925),(-61.305898,15.572455),(-61.29955,15.557196),(-61.289622,15.540961),(-61.284047,15.531399),(-61.268625,15.509914),(-61.267161,15.507799),(-61.25768,15.472602),(-61.256012,15.43594),(-61.262929,15.407904),(-61.258372,15.406317),(-61.254221,15.402981),(-61.249257,15.401068),(-61.255523,15.364569),(-61.254058,15.332668),(-61.253733,15.324693),(-61.256663,15.285346),(-61.277211,15.25023),(-61.284413,15.244818),(-61.289296,15.243598),(-61.293202,15.243883),(-61.303375,15.24258),(-61.311879,15.244534),(-61.318186,15.243394),(-61.323598,15.238593),(-61.328725,15.225572),(-61.342681,15.219672),(-61.345937,15.212348),(-61.346384,15.211697),(-61.350738,15.205146),(-61.362864,15.201809)] +Algeria [(8.60251,36.939511),(8.605655,36.913045),(8.604828,36.900979),(8.608239,36.890721),(8.642552,36.848501),(8.641725,36.836357),(8.623845,36.826074),(8.554495,36.803646),(8.520079,36.79791),(8.482665,36.799977),(8.444011,36.796205),(8.413109,36.783906),(8.406701,36.767989),(8.441634,36.75321),(8.461788,36.732798),(8.45321,36.697658),(8.430369,36.662621),(8.407941,36.642622),(8.286915,36.583401),(8.222319,36.563764),(8.193484,36.548985),(8.169919,36.525834),(8.16789,36.491995),(8.167852,36.491365),(8.20878,36.477826),(8.295597,36.46868),(8.314924,36.460618),(8.333837,36.456381),(8.349237,36.448784),(8.357712,36.430387),(8.359675,36.411215),(8.358125,36.369926),(8.355423,36.356116),(8.354404,36.350909),(8.307069,36.243629),(8.302314,36.202339),(8.307069,36.182495),(8.31451,36.163944),(8.317094,36.145909),(8.307999,36.126995),(8.296733,36.110407),(8.275649,36.03682),(8.272446,35.981732),(8.268423,35.969864),(8.247227,35.907318),(8.24144,35.827737),(8.24578,35.78531),(8.257666,35.750325),(8.306552,35.684903),(8.323605,35.652192),(8.327225,35.621405),(8.337041,35.537935),(8.336731,35.508376),(8.300868,35.437476),(8.290016,35.402595),(8.287948,35.366059),(8.294356,35.32508),(8.317404,35.289475),(8.355231,35.274334),(8.396882,35.263688),(8.431299,35.241726),(8.421377,35.222089),(8.360916,35.145918),(8.313683,35.103078),(8.300454,35.06768),(8.282884,34.994041),(8.25901,34.940659),(8.248881,34.901953),(8.250741,34.864746),(8.269345,34.763874),(8.266554,34.750283),(8.258714,34.741298),(8.257356,34.739741),(8.225213,34.711681),(8.213431,34.696746),(8.210641,34.681192),(8.236479,34.647654),(8.228831,34.63644),(8.192864,34.617733),(8.186559,34.609568),(8.179531,34.592153),(8.17519,34.58528),(8.167232,34.578562),(8.143668,34.566728),(8.102483,34.536355),(8.094058,34.530142),(7.999077,34.494175),(7.957323,34.469422),(7.87061,34.437899),(7.831542,34.414386),(7.811905,34.379272),(7.774285,34.260959),(7.765293,34.244707),(7.752787,34.232149),(7.733874,34.223778),(7.670312,34.215303),(7.631451,34.199102),(7.604063,34.175486),(7.579568,34.148459),(7.539228,34.113758),(7.517453,34.095026),(7.503707,34.067973),(7.500606,33.994257),(7.479832,33.893901),(7.484897,33.855015),(7.498539,33.799979),(7.505464,33.782849),(7.534196,33.736236),(7.544428,33.68425),(7.553006,33.658748),(7.616568,33.565963),(7.693153,33.454109),(7.708242,33.414861),(7.708286,33.410704),(7.709689,33.278151),(7.724985,33.231409),(7.75072,33.207664),(7.787514,33.198311),(7.83547,33.194538),(7.871953,33.184125),(7.982747,33.116817),(8.002178,33.108368),(8.022642,33.103045),(8.043622,33.101831),(8.0645,33.105784),(8.086824,33.094286),(8.181392,32.969823),(8.282884,32.836369),(8.296423,32.804407),(8.309963,32.663873),(8.319574,32.560598),(8.331253,32.527628),(8.332627,32.526355),(8.359985,32.501015),(8.482665,32.434791),(8.642345,32.336658),(8.851532,32.208242),(9.019893,32.104863),(9.033743,32.090756),(9.045008,32.071842),(9.063304,32.000192),(9.065989,31.989676),(9.094514,31.879606),(9.12273,31.769535),(9.151152,31.659567),(9.17947,31.549497),(9.207789,31.439426),(9.236211,31.329407),(9.264426,31.219336),(9.292952,31.109317),(9.32127,30.999246),(9.349589,30.889175),(9.377908,30.779156),(9.40633,30.669085),(9.434752,30.559066),(9.463071,30.449047),(9.491389,30.338976),(9.519708,30.228905),(9.286544,30.117129),(9.310005,30.084366),(9.369487,30.022794),(9.421729,29.968714),(9.54968,29.802316),(9.667709,29.608323),(9.746929,29.368428),(9.826149,29.128533),(9.848267,28.975726),(9.851264,28.785996),(9.827276,28.618647),(9.776953,28.267578),(9.789872,28.209442),(9.93591,27.866724),(9.934256,27.827398),(9.931274,27.818642),(9.863356,27.619246),(9.846613,27.599298),(9.818501,27.585733),(9.793903,27.569739),(9.797107,27.548914),(9.81168,27.526538),(9.821602,27.505687),(9.813643,27.486489),(9.770545,27.444217),(9.756283,27.42303),(9.743053,27.364119),(9.726517,27.32469),(9.721866,27.308463),(9.721349,27.291875),(9.806099,27.025122),(9.825529,26.92058),(9.835141,26.900995),(9.846096,26.891951),(9.890848,26.869576),(9.906661,26.857483),(9.910588,26.843117),(9.885474,26.736612),(9.88258,26.701782),(9.894052,26.67398),(9.896326,26.652793),(9.854571,26.524377),(9.835761,26.504223),(9.482604,26.352553),(9.481364,26.332606),(9.477643,26.315552),(9.468858,26.301031),(9.434752,26.271989),(9.416458,26.23225),(9.402506,26.216179),(9.377804,26.168946),(9.401162,26.113394),(9.541309,25.936351),(9.693961,25.743494),(9.816744,25.588465),(9.9695,25.395402),(10.007947,25.331426),(10.021383,25.26802),(10.025517,25.1364),(10.029961,24.995065),(10.032028,24.856339),(10.044534,24.829622),(10.193362,24.749937),(10.212172,24.722859),(10.229742,24.629945),(10.242248,24.595115),(10.260335,24.576641),(10.391799,24.47998),(10.410506,24.473288),(10.450194,24.476931),(10.566776,24.516463),(10.677363,24.553851),(10.699067,24.556125),(10.720668,24.552301),(10.911354,24.494501),(11.149996,24.422335),(11.46724,24.326339),(11.50863,24.313814),(11.541393,24.29751),(11.567128,24.26684),(11.636478,24.137649),(11.708618,24.00298),(11.71014,24.000137),(11.822306,23.790642),(11.89238,23.660056),(11.968861,23.517351),(11.900855,23.477173),(11.832745,23.437046),(11.764739,23.396945),(11.696733,23.356844),(11.628623,23.316717),(11.560514,23.276591),(11.492611,23.236516),(11.424501,23.196415),(11.356392,23.156262),(11.288489,23.116161),(11.220379,23.07606),(11.15227,23.035882),(11.084367,22.995755),(11.016257,22.955654),(10.948148,22.915527),(10.880038,22.875375),(10.812032,22.835326),(10.743923,22.795199),(10.675813,22.755046),(10.607807,22.714945),(10.539801,22.674896),(10.471691,22.634744),(10.403788,22.594643),(10.335679,22.554542),(10.267569,22.514337),(10.199563,22.474237),(10.131557,22.434136),(10.063447,22.394035),(9.995441,22.353882),(9.927435,22.313781),(9.859325,22.27368),(9.791319,22.233579),(9.723313,22.193427),(9.655203,22.153326),(9.587197,22.113225),(9.519088,22.073072),(9.451082,22.03292),(9.383075,21.992819),(9.314966,21.952718),(9.24696,21.912565),(9.178953,21.872516),(9.110844,21.832364),(9.042838,21.792263),(8.974832,21.75211),(8.906722,21.712061),(8.838613,21.671908),(8.770606,21.631807),(8.702497,21.591655),(8.634491,21.551502),(8.566381,21.51135),(8.498375,21.4713),(8.430265,21.431148),(8.362259,21.391047),(8.294253,21.350946),(8.226143,21.310845),(8.158034,21.270744),(8.090131,21.230592),(8.022022,21.190491),(7.953912,21.15039),(7.886009,21.110237),(7.8179,21.070085),(7.74979,21.029984),(7.681887,20.989831),(7.613778,20.94973),(7.482726,20.872577),(7.383611,20.791652),(7.312297,20.733464),(7.240881,20.675173),(7.169464,20.616986),(7.098047,20.558746),(7.020532,20.495443),(6.982808,20.46361),(6.925138,20.414001),(6.862092,20.35974),(6.799047,20.305532),(6.736105,20.251323),(6.672957,20.197115),(6.609963,20.142854),(6.546918,20.088646),(6.483769,20.034385),(6.420931,19.980177),(6.357782,19.925917),(6.294737,19.871682),(6.231692,19.817474),(6.168646,19.763213),(6.105601,19.709005),(6.042556,19.654745),(5.979407,19.600536),(5.916362,19.546276),(5.837607,19.478631),(5.794302,19.449796),(5.749344,19.433699),(5.620463,19.408997),(5.520831,19.389903),(5.301826,19.347993),(5.082821,19.306006),(4.983189,19.286963),(4.794467,19.250764),(4.605848,19.214616),(4.417229,19.178417),(4.22861,19.142244),(4.057561,19.110437),(3.886512,19.07863),(3.790291,19.06077),(3.715566,19.046901),(3.54462,19.015068),(3.439821,18.995638),(3.439717,18.995638),(3.358689,18.976853),(3.333057,18.975561),(3.318381,18.977706),(3.308356,18.981685),(3.284895,18.995741),(3.225984,19.05106),(3.179785,19.07),(3.158597,19.08155),(3.138754,19.096045),(3.120874,19.112814),(3.10413,19.135526),(3.102684,19.153561),(3.111779,19.171337),(3.126558,19.193352),(3.134206,19.212859),(3.13927,19.221929),(3.152706,19.230197),(3.17441,19.251643),(3.178855,19.268722),(3.183816,19.307505),(3.192911,19.325798),(3.211514,19.340862),(3.232701,19.351843),(3.250995,19.36546),(3.260813,19.388327),(3.25823,19.410393),(3.247481,19.426464),(3.234769,19.441347),(3.225984,19.459692),(3.22619,19.4692),(3.231668,19.489044),(3.232288,19.495478),(3.228051,19.504159),(3.222883,19.508061),(3.217509,19.511162),(3.212238,19.517156),(3.199422,19.553769),(3.198285,19.592397),(3.216785,19.794064),(3.212754,19.807758),(3.198802,19.820523),(3.183195,19.827731),(3.147022,19.837938),(3.130485,19.845224),(3.072608,19.88889),(2.946001,19.941652),(2.671805,19.996222),(2.616925,19.998367),(2.525665,20.015162),(2.514812,20.015937),(2.495382,20.020097),(2.459312,20.038778),(2.439882,20.04609),(2.415697,20.051284),(2.400401,20.056555),(2.388722,20.067407),(2.348208,20.137635),(2.316478,20.180165),(2.279581,20.21794),(2.21819,20.264087),(2.200826,20.273906),(2.18243,20.278505),(2.161346,20.274939),(2.138195,20.260728),(2.097474,20.224193),(2.071222,20.213263),(2.056339,20.215046),(1.993397,20.235949),(1.983372,20.241918),(1.975621,20.248429),(1.967146,20.253416),(1.95526,20.254915),(1.941204,20.251116),(1.924254,20.23613),(1.913402,20.231092),(1.891388,20.231789),(1.883843,20.24414),(1.880329,20.263054),(1.870614,20.283543),(1.855008,20.294835),(1.838885,20.29592),(1.820901,20.293594),(1.799197,20.294886),(1.778113,20.304291),(1.659154,20.397516),(1.649232,20.412089),(1.650059,20.487019),(1.643961,20.522676),(1.623704,20.551253),(1.559729,20.597504),(1.520351,20.616986),(1.483454,20.622618),(1.465781,20.633522),(1.447487,20.638741),(1.40718,20.645046),(1.363978,20.657707),(1.346925,20.669127),(1.331526,20.687937),(1.310545,20.722716),(1.296696,20.733464),(1.273338,20.739407),(1.252254,20.738994),(1.212463,20.73088),(1.191276,20.73057),(1.168538,20.733464),(1.154585,20.738787),(1.147247,20.751448),(1.14456,20.776252),(1.145284,20.795889),(1.167505,20.886013),(1.180114,20.995309),(1.177943,21.017323),(1.15934,21.081505),(1.146524,21.101711),(1.029322,21.178347),(0.942609,21.235036),(0.855999,21.291673),(0.769389,21.34831),(0.682676,21.404896),(0.596067,21.461585),(0.509457,21.518274),(0.422795,21.574963),(0.33616,21.631601),(0.249499,21.688238),(0.162966,21.744824),(0.076253,21.801461),(0.003735,21.848899),(-0.010408,21.85815),(-0.097044,21.914839),(-0.183731,21.971477),(-0.270392,22.028114),(-0.357028,22.084751),(-0.443663,22.141389),(-0.530325,22.198078),(-0.616934,22.254767),(-0.703647,22.311404),(-0.790309,22.368041),(-0.876918,22.424627),(-0.96358,22.481265),(-1.05019,22.537954),(-1.136903,22.594643),(-1.223512,22.65128),(-1.310122,22.707969),(-1.396783,22.764555),(-1.483496,22.821166),(-1.570054,22.877881),(-1.656716,22.93457),(-1.743326,22.991182),(-1.830039,23.047819),(-1.916648,23.104456),(-2.00331,23.161042),(-2.089919,23.217757),(-2.176632,23.274446),(-2.26319,23.331109),(-2.349852,23.387747),(-2.436513,23.444358),(-2.523226,23.500996),(-2.609836,23.557685),(-2.696446,23.614348),(-2.783107,23.670985),(-2.869768,23.727623),(-2.956404,23.784234),(-3.043065,23.840923),(-3.129649,23.897612),(-3.209489,23.949702),(-3.289123,24.001844),(-3.368808,24.053959),(-3.448544,24.106023),(-3.528281,24.158113),(-3.608018,24.210203),(-3.687625,24.262344),(-3.767336,24.314434),(-3.846996,24.366576),(-3.926732,24.418717),(-4.006495,24.470807),(-4.086154,24.522897),(-4.165865,24.574987),(-4.245498,24.627077),(-4.325235,24.679218),(-4.404946,24.731308),(-4.516025,24.803991),(-4.592351,24.851688),(-4.668677,24.899334),(-4.744925,24.947057),(-4.821226,24.994755),(-4.821355,24.994806),(-4.821536,24.994961),(-4.821613,24.995065),(-4.995194,25.102086),(-5.16875,25.20916),(-5.342331,25.316182),(-5.515964,25.423256),(-5.63699,25.494466),(-5.661525,25.508881),(-5.804628,25.592961),(-5.972266,25.691611),(-6.139905,25.79021),(-6.307491,25.888808),(-6.505412,26.005184),(-6.703333,26.121559),(-6.901202,26.237934),(-7.099123,26.354361),(-7.297043,26.470737),(-7.494912,26.587164),(-7.692782,26.703487),(-7.890754,26.819914),(-8.088623,26.936238),(-8.28644,27.052665),(-8.484413,27.168989),(-8.682385,27.285416),(-8.682385,27.379467),(-8.682385,27.473466),(-8.682385,27.567414),(-8.682385,27.661439),(-8.682385,27.721436),(-8.682385,27.781354),(-8.682385,27.841222),(-8.682385,27.90114),(-8.682385,27.961085),(-8.682385,28.02103),(-8.682385,28.080949),(-8.682385,28.140893),(-8.682385,28.20076),(-8.682385,28.260679),(-8.682385,28.320624),(-8.682385,28.380543),(-8.682385,28.440487),(-8.682385,28.500406),(-8.682385,28.560273),(-8.682385,28.620218),(-8.682385,28.6659),(-8.678768,28.692823),(-8.667606,28.711685),(-8.648847,28.725948),(-8.520819,28.787081),(-8.475835,28.818759),(-8.430411,28.841006),(-8.417802,28.852349),(-8.383489,28.905782),(-8.368451,28.916531),(-8.333259,28.93038),(-8.316774,28.939062),(-8.250474,28.994769),(-8.182312,29.035541),(-8.069658,29.079337),(-8.036326,29.099853),(-7.945014,29.176231),(-7.839129,29.239043),(-7.777996,29.289324),(-7.729989,29.311158),(-7.714667,29.321829),(-7.653611,29.376193),(-7.619453,29.389422),(-7.572686,29.387613),(-7.528502,29.380947),(-7.506126,29.380223),(-7.48406,29.382445),(-7.463286,29.389137),(-7.34961,29.383439),(-7.258755,29.467305),(-7.146934,29.509238),(-7.070057,29.516227),(-6.958236,29.509238),(-6.783515,29.446339),(-6.699649,29.516227),(-6.559872,29.530205),(-6.413107,29.565149),(-6.27333,29.579127),(-6.126564,29.579127),(-6.000765,29.579127),(-5.881955,29.600093),(-5.756156,29.614071),(-5.721212,29.523216),(-5.637346,29.495261),(-5.539503,29.523216),(-5.43467,29.642026),(-5.343815,29.767825),(-5.273927,29.886635),(-5.176083,29.97749),(-5.071251,30.04039),(-4.95943,30.124256),(-4.875564,30.180166),(-4.770731,30.229088),(-4.623966,30.284999),(-4.484189,30.382842),(-4.372368,30.508641),(-4.274524,30.557563),(-4.155714,30.585519),(-4.001959,30.592507),(-3.834228,30.627452),(-3.645529,30.711317),(-3.652518,30.774217),(-3.659507,30.837116),(-3.610585,30.879049),(-3.554674,30.955927),(-3.608741,31.030872),(-3.610085,31.050302),(-3.614529,31.068027),(-3.624141,31.086527),(-3.635872,31.095674),(-3.671942,31.110867),(-3.689718,31.125595),(-3.717107,31.163267),(-3.731421,31.176341),(-3.748862,31.180217),(-3.763719,31.173447),(-3.792968,31.149676),(-3.810796,31.142906),(-3.827462,31.143837),(-3.839322,31.152828),(-3.842836,31.170192),(-3.836169,31.189777),(-3.814982,31.220524),(-3.812915,31.243365),(-3.81922,31.318865),(-3.815189,31.337158),(-3.802502,31.350646),(-3.747467,31.385166),(-3.673484,31.389234),(-3.659507,31.647821),(-3.591378,31.678274),(-3.548745,31.669954),(-3.511564,31.672745),(-3.21921,31.717709),(-3.002556,31.77362),(-2.827836,31.794586),(-2.869769,31.89243),(-2.938731,32.048639),(-2.881189,32.076286),(-2.695567,32.08967),(-2.516147,32.1322),(-2.378636,32.126774),(-2.315177,32.124294),(-2.243398,32.1214),(-2.165109,32.118299),(-2.081858,32.11494),(-1.995455,32.111478),(-1.907553,32.107964),(-1.819962,32.104501),(-1.734334,32.101091),(-1.652375,32.097835),(-1.575791,32.094735),(-1.506337,32.091944),(-1.445618,32.089515),(-1.395388,32.087552),(-1.357406,32.086053),(-1.333428,32.085071),(-1.324953,32.084709),(-1.249557,32.08166),(-1.210335,32.08967),(-1.190594,32.125224),(-1.195607,32.146049),(-1.211833,32.158348),(-1.232711,32.163723),(-1.251831,32.163516),(-1.288986,32.150907),(-1.305161,32.151165),(-1.309554,32.167443),(-1.305678,32.173722),(-1.289193,32.184858),(-1.282992,32.190181),(-1.276636,32.200852),(-1.275189,32.209069),(-1.275499,32.217518),(-1.273423,32.229442),(-1.257515,32.320845),(-1.244131,32.356915),(-1.234158,32.374614),(-1.217983,32.392623),(-1.201705,32.399858),(-1.16026,32.404948),(-1.123157,32.417945),(-1.08998,32.439442),(-1.031999,32.4944),(-1.047502,32.517009),(-1.32702,32.69891),(-1.390531,32.718779),(-1.423345,32.742395),(-1.558789,32.93365),(-1.516363,32.959488),(-1.50887,32.966309),(-1.502978,32.974629),(-1.498844,32.984008),(-1.496519,32.994292),(-1.493367,33.016151),(-1.493057,33.039483),(-1.499516,33.060205),(-1.516363,33.073977),(-1.545508,33.091831),(-1.571398,33.111985),(-1.592069,33.136609),(-1.605608,33.168028),(-1.623591,33.196605),(-1.674234,33.237972),(-1.683381,33.270839),(-1.683226,33.36923),(-1.672839,33.394604),(-1.659145,33.41977),(-1.640386,33.475529),(-1.6254,33.494236),(-1.612739,33.521469),(-1.617338,33.554439),(-1.6624,33.644692),(-1.673252,33.6565),(-1.690719,33.667326),(-1.725394,33.677713),(-1.740742,33.686601),(-1.746788,33.702388),(-1.74224,33.717762),(-1.732577,33.727865),(-1.72095,33.736366),(-1.710821,33.747063),(-1.703225,33.761816),(-1.702501,33.772823),(-1.713043,33.801995),(-1.722087,33.851165),(-1.718728,33.898087),(-1.672115,34.059188),(-1.669635,34.079213),(-1.672085,34.092021),(-1.674751,34.105956),(-1.746064,34.290311),(-1.771334,34.334701),(-1.809626,34.372451),(-1.702966,34.479679),(-1.714232,34.485054),(-1.750664,34.494175),(-1.871121,34.596649),(-1.862957,34.613599),(-1.810505,34.680727),(-1.786114,34.72584),(-1.773143,34.734057),(-1.769526,34.741343),(-1.787716,34.756691),(-1.892825,34.811675),(-1.926725,34.838081),(-1.979745,34.865263),(-1.993491,34.878854),(-1.9984,34.892703),(-1.999692,34.906346),(-2.00362,34.91818),(-2.01628,34.926241),(-2.061239,34.929704),(-2.094932,34.947687),(-2.126041,34.971923),(-2.1633,34.994041),(-2.193789,35.003601),(-2.211669,35.023445),(-2.221126,35.049955),(-2.222564,35.089301),(-2.200103,35.096137),(-2.196116,35.094875),(-2.192616,35.094468),(-2.189443,35.093004),(-2.186391,35.08869),(-2.15689,35.100979),(-2.122222,35.094672),(-2.08609,35.081977),(-2.052358,35.075019),(-1.987701,35.082465),(-1.964752,35.076239),(-1.956451,35.075019),(-1.949818,35.077135),(-1.932485,35.08869),(-1.838694,35.110907),(-1.812734,35.126532),(-1.804351,35.128119),(-1.774241,35.127346),(-1.761138,35.129625),(-1.745595,35.138821),(-1.712799,35.1706),(-1.648834,35.188422),(-1.637685,35.194525),(-1.629506,35.212226),(-1.510365,35.295478),(-1.490875,35.300971),(-1.395904,35.309394),(-1.369537,35.315863),(-1.364003,35.318345),(-1.358957,35.322211),(-1.332672,35.349351),(-1.313791,35.353746),(-1.29483,35.364569),(-1.278635,35.377997),(-1.26773,35.390326),(-1.259185,35.410305),(-1.247304,35.45775),(-1.23705,35.475735),(-1.225413,35.491278),(-1.190338,35.566148),(-1.183339,35.576483),(-1.171539,35.581041),(-1.14802,35.582099),(-1.142812,35.5869),(-1.117014,35.616889),(-1.106353,35.623236),(-1.082753,35.637356),(-1.052073,35.660956),(-1.040395,35.676418),(-1.032948,35.682603),(-0.996693,35.689602),(-0.977651,35.699774),(-0.961537,35.711249),(-0.946278,35.719306),(-0.922678,35.725165),(-0.910227,35.724311),(-0.904693,35.715888),(-0.899403,35.711819),(-0.887563,35.715969),(-0.849477,35.73432),(-0.825022,35.768541),(-0.801666,35.773912),(-0.793528,35.770087),(-0.786122,35.763129),(-0.77717,35.756415),(-0.764027,35.753404),(-0.754018,35.752265),(-0.734486,35.747219),(-0.723134,35.745998),(-0.711293,35.742987),(-0.705881,35.735663),(-0.701324,35.726874),(-0.692454,35.719306),(-0.682607,35.717353),(-0.644521,35.719306),(-0.626454,35.722968),(-0.606109,35.730943),(-0.589345,35.742499),(-0.57726,35.770819),(-0.565053,35.772447),(-0.551259,35.769029),(-0.540924,35.767768),(-0.530426,35.772895),(-0.523427,35.77969),(-0.47704,35.859361),(-0.476064,35.870103),(-0.478424,35.87287),(-0.480336,35.879096),(-0.480824,35.885728),(-0.479482,35.890041),(-0.473785,35.891262),(-0.468007,35.888739),(-0.46288,35.885199),(-0.459055,35.883775),(-0.448964,35.884345),(-0.428131,35.882799),(-0.41804,35.883775),(-0.376129,35.900336),(-0.348541,35.90705),(-0.336171,35.900824),(-0.331451,35.889553),(-0.320709,35.884101),(-0.309193,35.881171),(-0.30191,35.87759),(-0.298492,35.867174),(-0.304596,35.853502),(-0.30191,35.842841),(-0.285553,35.828274),(-0.259429,35.817532),(-0.188059,35.805243),(-0.14509,35.790351),(-0.123891,35.786933),(-0.113678,35.788804),(-0.083079,35.794379),(-0.038482,35.8133),(0.00294,35.838039),(0.034516,35.863267),(0.069957,35.92182),(0.08017,35.947008),(0.114024,36.010199),(0.122406,36.033352),(0.12379,36.044582),(0.127289,36.050767),(0.13559,36.055609),(0.145518,36.059963),(0.153982,36.065009),(0.202159,36.106513),(0.219493,36.116523),(0.283458,36.134426),(0.294444,36.140774),(0.299083,36.147406),(0.321056,36.158881),(0.329275,36.164984),(0.332774,36.173814),(0.337576,36.197496),(0.342296,36.205959),(0.360037,36.213853),(0.384451,36.217963),(0.428396,36.219631),(0.451345,36.223212),(0.468272,36.232245),(0.483165,36.243598),(0.556651,36.284084),(0.594574,36.293158),(0.611827,36.305487),(0.627208,36.319241),(0.644054,36.328843),(0.663259,36.332587),(0.740408,36.337755),(0.753266,36.338609),(0.768728,36.344713),(0.802257,36.363593),(0.864757,36.377387),(0.880544,36.387152),(0.89088,36.396389),(0.913829,36.409125),(0.925141,36.418158),(0.929535,36.42593),(0.93214,36.434556),(0.93629,36.44359),(0.945567,36.452338),(0.962576,36.458157),(1.007091,36.466864),(1.04477,36.486884),(1.116954,36.487128),(1.138845,36.493394),(1.178722,36.510891),(1.202647,36.51439),(1.245453,36.513577),(1.265473,36.515326),(1.288259,36.521226),(1.34669,36.544989),(1.367686,36.547919),(1.385997,36.545152),(1.429535,36.532213),(1.45281,36.528022),(1.476329,36.528957),(1.517426,36.538723),(1.700938,36.547187),(1.716563,36.547919),(1.726736,36.549994),(1.750173,36.559149),(1.761241,36.561591),(1.77003,36.560492),(1.791515,36.555487),(1.802908,36.555365),(1.857595,36.56745),(1.913829,36.570217),(1.96046,36.562201),(1.97283,36.561591),(2.059906,36.570136),(2.309825,36.63052),(2.3296,36.637274),(2.351573,36.638332),(2.373302,36.633857),(2.391856,36.624254),(2.398204,36.615302),(2.400157,36.606187),(2.404063,36.599189),(2.416026,36.59634),(2.426768,36.595282),(2.447276,36.590562),(2.457042,36.589504),(2.600759,36.59634),(2.632986,36.605129),(2.72755,36.665229),(2.792979,36.692939),(2.818696,36.710883),(2.843598,36.740383),(2.849864,36.754055),(2.875662,36.774807),(2.933116,36.80858),(2.977061,36.815863),(2.984874,36.814968),(3.014171,36.811713),(3.047862,36.794989),(3.073985,36.771389),(3.101817,36.751899),(3.140147,36.741645),(3.173269,36.742621),(3.179373,36.742825),(3.21046,36.757392),(3.221202,36.77143),(3.226085,36.7862),(3.227306,36.812323),(3.237804,36.813056),(3.302989,36.788764),(3.340505,36.780707),(3.460704,36.775092),(3.480479,36.777248),(3.519054,36.786607),(3.539806,36.788764),(3.550466,36.791449),(3.558116,36.797675),(3.564301,36.804348),(3.570567,36.80858),(3.580414,36.809963),(3.601817,36.808092),(3.612071,36.80858),(3.649669,36.823961),(3.709483,36.873196),(3.741873,36.891181),(3.827485,36.912909),(3.873871,36.917222),(3.912608,36.911607),(3.948253,36.893297),(3.964041,36.891181),(3.974864,36.892279),(3.99643,36.896918),(4.031423,36.897773),(4.03948,36.896918),(4.08546,36.892076),(4.104828,36.883734),(4.146495,36.901801),(4.159516,36.904202),(4.17156,36.902167),(4.197032,36.893256),(4.21046,36.891181),(4.22283,36.894192),(4.249278,36.907864),(4.261974,36.911607),(4.278575,36.910468),(4.306,36.900458),(4.320323,36.898017),(4.440684,36.911607),(4.452973,36.910061),(4.46811,36.905992),(4.482432,36.900458),(4.491954,36.894599),(4.50408,36.889309),(4.536388,36.888577),(4.550548,36.883734),(4.581554,36.894924),(4.591482,36.89525),(4.622895,36.896389),(4.698009,36.891181),(4.769054,36.898017),(4.78712,36.895413),(4.94988,36.839789),(4.968272,36.82567),(4.973643,36.818915),(4.985688,36.817084),(4.999522,36.817125),(5.009288,36.816067),(5.016449,36.810981),(5.025238,36.798651),(5.029145,36.794989),(5.045909,36.78852),(5.065603,36.783515),(5.086192,36.780829),(5.104828,36.781317),(5.084809,36.732611),(5.09018,36.716783),(5.118419,36.699368),(5.23585,36.650946),(5.269054,36.64411),(5.304373,36.643012),(5.372406,36.650946),(5.428071,36.663886),(5.433849,36.665229),(5.464854,36.665229),(5.469574,36.667711),(5.482188,36.680243),(5.489106,36.685126),(5.529145,36.697659),(5.549001,36.709703),(5.562755,36.745998),(5.576182,36.761379),(5.593923,36.773871),(5.61199,36.781317),(5.655935,36.791815),(5.674571,36.799628),(5.71046,36.825507),(5.733735,36.832343),(5.7588,36.833401),(5.82781,36.821763),(5.868826,36.822943),(6.03712,36.853583),(6.197032,36.90233),(6.235688,36.92121),(6.256847,36.945787),(6.258556,36.966783),(6.254731,36.983303),(6.254405,36.998969),(6.266856,37.017768),(6.274425,37.024237),(6.314626,37.048651),(6.328868,37.061916),(6.338715,37.069281),(6.371593,37.083482),(6.415782,37.092963),(6.462413,37.09394),(6.502696,37.082953),(6.538585,37.06037),(6.5442,37.058783),(6.544688,37.04857),(6.547048,37.041205),(6.552257,37.036689),(6.56129,37.035142),(6.572765,37.027777),(6.583263,36.989814),(6.599457,36.97309),(6.614106,36.977851),(6.631602,36.972398),(6.651134,36.963853),(6.671153,36.959418),(6.822032,36.952623),(6.834809,36.949123),(6.852794,36.940334),(6.86964,36.929185),(6.880056,36.918443),(6.879649,36.902086),(6.909434,36.893052),(6.948578,36.890041),(6.975597,36.891181),(7.064464,36.913316),(7.092296,36.92593),(7.108084,36.920315),(7.133311,36.915269),(7.156993,36.9147),(7.167491,36.922187),(7.176443,36.931871),(7.218761,36.960842),(7.232921,36.966864),(7.239024,36.971503),(7.247081,36.982327),(7.254242,36.994696),(7.257335,37.004136),(7.255544,37.015367),(7.250499,37.023139),(7.211111,37.057034),(7.181651,37.076728),(7.181651,37.082953),(7.192719,37.084296),(7.212169,37.089301),(7.222667,37.089789),(7.232758,37.087226),(7.251313,37.078599),(7.260509,37.076728),(7.262706,37.075995),(7.266449,37.074693),(7.270681,37.071031),(7.27475,37.069322),(7.281016,37.073065),(7.288259,37.080268),(7.292654,37.082506),(7.297699,37.082953),(7.307302,37.080146),(7.325857,37.071194),(7.335948,37.069281),(7.344412,37.071438),(7.369965,37.082953),(7.383474,37.082994),(7.386241,37.082099),(7.386892,37.078111),(7.394054,37.069281),(7.398204,37.05801),(7.404633,37.051581),(7.418224,37.048814),(7.438324,37.04857),(7.447113,37.046617),(7.456065,37.041978),(7.472423,37.050035),(7.490245,37.054999),(7.526134,37.033149),(7.555919,37.00788),(7.588878,36.987616),(7.633556,36.980536),(7.643403,36.982652),(7.652192,36.986233),(7.661876,36.988471),(7.67449,36.986762),(7.685802,36.982408),(7.695974,36.976996),(7.704845,36.970526),(7.712738,36.963202),(7.760753,36.966864),(7.770763,36.97012),(7.789073,36.986558),(7.798595,36.993598),(7.791026,36.973212),(7.778575,36.951117),(7.774262,36.931464),(7.791189,36.918443),(7.773448,36.88996),(7.773774,36.889757),(7.809906,36.86815),(7.866466,36.854397),(7.908458,36.849555),(8.049978,36.87759),(8.073009,36.887397),(8.093028,36.901801),(8.233165,36.958075),(8.25115,36.948676),(8.268728,36.933743),(8.288097,36.92593),(8.333263,36.927802),(8.355968,36.92593),(8.374034,36.918443),(8.388845,36.923245),(8.401622,36.918606),(8.414399,36.910224),(8.428722,36.904202),(8.463227,36.901557),(8.497569,36.904202),(8.601899,36.939358),(8.60251,36.939511)] +Ethiopia [(38.13331,14.677762),(38.190258,14.687322),(38.213925,14.685875),(38.229325,14.679725),(38.239557,14.667555),(38.245841,14.652474),(38.247825,14.647712),(38.252683,14.62022),(38.257644,14.610427),(38.267152,14.601771),(38.278831,14.595467),(38.28927,14.587741),(38.295678,14.574874),(38.305186,14.536917),(38.313351,14.519347),(38.32503,14.504594),(38.340636,14.492682),(38.394276,14.464312),(38.402338,14.456871),(38.409056,14.43527),(38.41443,14.426304),(38.426832,14.417183),(38.435204,14.416305),(38.443679,14.418656),(38.492978,14.418294),(38.569356,14.426821),(38.606563,14.436484),(38.668471,14.467723),(38.688005,14.467103),(38.706195,14.46116),(38.724385,14.459403),(38.742885,14.461056),(38.761902,14.465449),(38.821537,14.489478),(38.866082,14.493664),(38.884582,14.506247),(38.917552,14.535703),(38.959203,14.554642),(38.979667,14.567122),(38.993826,14.585157),(38.996823,14.60358),(38.995273,14.622261),(38.996823,14.638901),(39.009742,14.651226),(39.011189,14.647763),(39.04695,14.643758),(39.075475,14.637402),(39.0855,14.633475),(39.107308,14.620116),(39.127461,14.602211),(39.144721,14.581566),(39.158467,14.560146),(39.187509,14.477205),(39.20818,14.440179),(39.233191,14.440438),(39.254999,14.474415),(39.268538,14.48643),(39.293446,14.490305),(39.347603,14.481805),(39.36662,14.482916),(39.448579,14.505111),(39.489403,14.524489),(39.50718,14.547821),(39.515035,14.56782),(39.532295,14.567587),(39.552138,14.556684),(39.567331,14.544307),(39.587692,14.520278),(39.59379,14.514567),(39.599474,14.511648),(39.650944,14.496584),(39.677712,14.494233),(39.722985,14.501717),(39.735073,14.503715),(39.766906,14.504775),(39.796878,14.495111),(39.824473,14.478135),(39.87708,14.433616),(39.892273,14.426562),(39.911186,14.42341),(39.93072,14.428784),(39.961519,14.454209),(39.979812,14.458731),(39.999839,14.455238),(40.023221,14.45116),(40.037483,14.451522),(40.086886,14.465759),(40.104559,14.465966),(40.194373,14.444649),(40.237678,14.427441),(40.277055,14.404574),(40.353687,14.335241),(40.421646,14.273755),(40.479834,14.244403),(40.585874,14.19469),(40.614089,14.185802),(40.704419,14.173219),(40.772322,14.148362),(40.833197,14.105962),(40.93779,13.989922),(41.043623,13.872488),(41.121345,13.738181),(41.192038,13.615863),(41.222217,13.586614),(41.357093,13.502278),(41.530726,13.393783),(41.635525,13.309344),(41.7118,13.247926),(41.750764,13.208316),(41.784767,13.164572),(41.8166,13.112792),(41.894321,12.94797),(41.946617,12.876166),(42.024649,12.82697),(42.0817,12.803922),(42.137304,12.77333),(42.184949,12.733048),(42.250165,12.623985),(42.33171,12.515465),(42.379459,12.465907),(42.319205,12.386377),(42.288715,12.321006),(42.155494,12.142257),(42.140301,12.105826),(42.132343,12.093475),(42.108778,12.082106),(42.097719,12.070169),(42.057308,11.996271),(41.97468,11.88091),(41.936386,11.827445),(41.925327,11.816437),(41.911477,11.805947),(41.897525,11.799384),(41.886259,11.796025),(41.877784,11.790134),(41.872203,11.775871),(41.862282,11.763056),(41.823007,11.746106),(41.808228,11.736236),(41.792415,11.704455),(41.778669,11.628645),(41.74911,11.537953),(41.749834,11.483383),(41.775672,11.368429),(41.787971,11.259727),(41.785594,11.067388),(41.779289,11.024677),(41.761306,10.996203),(41.766523,10.989466),(41.773811,10.980054),(41.79872,10.970675),(41.916852,10.947059),(41.920262,10.941943),(41.922846,10.936026),(41.928841,10.931065),(41.937522,10.929825),(41.942793,10.933546),(41.947341,10.938532),(41.954162,10.941271),(42.0108,10.943597),(42.038395,10.950444),(42.069401,10.981501),(42.096272,10.990261),(42.151359,10.996203),(42.202726,10.98455),(42.221639,10.984344),(42.235179,10.987703),(42.270835,11.003516),(42.279414,11.004394),(42.297294,11.003774),(42.305872,11.004601),(42.338532,11.015504),(42.361166,11.011887),(42.376669,11.006668),(42.391758,11.005893),(42.413256,11.015944),(42.479712,11.059119),(42.569732,11.086146),(42.608145,11.089088),(42.615621,11.08966),(42.686521,11.073046),(42.710395,11.072116),(42.729619,11.06501),(42.754837,11.010544),(42.771787,10.996462),(42.794111,10.991604),(42.835452,10.987444),(42.860153,10.980416),(42.873279,10.978246),(42.888059,10.983568),(42.898084,10.995687),(42.908109,11.004187),(42.923715,10.998787),(42.911313,10.977367),(42.901185,10.936595),(42.893536,10.919671),(42.876793,10.905744),(42.834832,10.888406),(42.819432,10.872567),(42.811578,10.85262),(42.80765,10.83611),(42.801242,10.820788),(42.785636,10.804406),(42.749876,10.775829),(42.738094,10.759784),(42.728585,10.735496),(42.718973,10.694852),(42.711635,10.675163),(42.699646,10.65855),(42.680216,10.647672),(42.660269,10.641625),(42.647247,10.63222),(42.64859,10.611033),(42.668537,10.56623),(42.695202,10.524708),(42.750393,10.471636),(42.765792,10.451947),(42.776644,10.42461),(42.78946,10.333324),(42.808167,10.269116),(42.836279,10.208086),(42.862324,10.177158),(42.958235,10.115559),(42.981903,10.091633),(42.999887,10.061971),(43.012599,10.029286),(43.020764,9.996419),(43.039884,9.949988),(43.067686,9.922522),(43.104273,9.907923),(43.149852,9.899991),(43.187214,9.883326),(43.206334,9.851209),(43.235273,9.691787),(43.248812,9.652332),(43.270671,9.628354),(43.297698,9.621533),(43.305966,9.617554),(43.315578,9.607658),(43.325086,9.585902),(43.331753,9.575076),(43.341364,9.566394),(43.361518,9.553165),(43.370665,9.544225),(43.393351,9.49893),(43.399449,9.480947),(43.401981,9.447409),(43.406322,9.42865),(43.419034,9.413018),(43.471227,9.382012),(43.548225,9.336072),(43.566829,9.334315),(43.59122,9.343591),(43.60724,9.344625),(43.621502,9.336899),(43.698449,9.267162),(43.78759,9.186701),(43.914921,9.071489),(43.984788,9.008314),(44.023855,8.985525),(44.104057,8.959222),(44.192217,8.930283),(44.280377,8.901396),(44.368537,8.872457),(44.456697,8.843544),(44.544753,8.814605),(44.633017,8.785718),(44.721073,8.756779),(44.809233,8.72784),(44.89729,8.698928),(44.985553,8.67004),(45.073558,8.641153),(45.16177,8.612137),(45.249878,8.583276),(45.33809,8.554414),(45.426147,8.525476),(45.51441,8.496537),(45.514462,8.496537),(45.598436,8.468425),(45.682358,8.440313),(45.766384,8.412227),(45.850203,8.384115),(45.934126,8.356003),(46.018049,8.327891),(46.101919,8.299727),(46.185894,8.271641),(46.269816,8.243555),(46.353842,8.215469),(46.437713,8.187357),(46.521687,8.159245),(46.605713,8.131133),(46.689532,8.102969),(46.773558,8.074909),(46.857377,8.046745),(46.920526,8.025609),(46.97923,7.996567),(47.068114,7.996516),(47.210586,7.996516),(47.36608,7.996516),(47.52359,7.996516),(47.653918,7.996516),(47.836697,7.996516),(47.979169,7.996567),(47.930593,7.949697),(47.881811,7.902826),(47.833183,7.855956),(47.784659,7.809137),(47.736032,7.762215),(47.687507,7.715396),(47.638932,7.668525),(47.590252,7.621655),(47.541676,7.574836),(47.532388,7.565864),(47.493101,7.527914),(47.444525,7.481043),(47.395949,7.434173),(47.347373,7.387302),(47.298797,7.34038),(47.250118,7.293509),(47.201439,7.246691),(47.152863,7.19982),(47.104287,7.153001),(47.055608,7.106079),(47.007032,7.059208),(46.95856,7.012286),(46.909984,6.965467),(46.861408,6.918597),(46.812729,6.871675),(46.764101,6.824882),(46.715577,6.777985),(46.667001,6.731115),(46.618425,6.684244),(46.598065,6.664633),(46.55321,6.621457),(46.508406,6.578308),(46.488046,6.558645),(46.466963,6.538292),(46.423915,6.496736),(46.362937,6.43426),(46.302062,6.371731),(46.240981,6.309228),(46.179899,6.246726),(46.118818,6.184223),(46.057839,6.12172),(45.99681,6.059192),(45.935986,5.996689),(45.828706,5.879513),(45.721426,5.762337),(45.614146,5.645057),(45.518477,5.540564),(45.506865,5.527881),(45.399585,5.410704),(45.292356,5.293476),(45.185024,5.176248),(45.077744,5.059072),(45.0209,4.99688),(45.020642,4.99688),(44.941525,4.911484),(44.912586,4.899392),(44.858378,4.902544),(44.806546,4.905541),(44.754766,4.908565),(44.702883,4.911562),(44.651104,4.914507),(44.59922,4.917505),(44.596808,4.917643),(44.547441,4.920476),(44.495557,4.923473),(44.443726,4.926445),(44.391998,4.929468),(44.340115,4.932439),(44.288335,4.935488),(44.236452,4.938485),(44.184672,4.941431),(44.132789,4.94448),(44.081009,4.947451),(44.029126,4.950448),(43.968975,4.953962),(43.932284,4.945203),(43.845158,4.914352),(43.815186,4.907479),(43.716484,4.884793),(43.640519,4.867353),(43.528485,4.841566),(43.459342,4.808829),(43.346997,4.755654),(43.232792,4.701497),(43.119259,4.647702),(43.03544,4.578895),(42.960406,4.517374),(42.952551,4.507581),(42.945936,4.496858),(42.9325,4.463217),(42.914724,4.393299),(42.899634,4.361104),(42.870195,4.328171),(42.868938,4.326765),(42.831628,4.302322),(42.78977,4.285605),(42.718663,4.273487),(42.568285,4.247856),(42.415013,4.221707),(42.297294,4.201734),(42.221846,4.200959),(42.13534,4.200081),(42.102887,4.19189),(42.068367,4.174553),(42.011833,4.129491),(41.941243,4.086212),(41.923466,4.070554),(41.916645,4.051098),(41.917472,4.020453),(41.912201,4.007974),(41.898455,3.996915),(41.885019,3.977226),(41.835927,3.94945),(41.791381,3.958157),(41.747353,3.981412),(41.699811,3.996915),(41.657436,3.972704),(41.642967,3.969449),(41.628704,3.972084),(41.602246,3.983065),(41.586329,3.984151),(41.506231,3.964384),(41.479773,3.962938),(41.429543,3.948882),(41.317405,3.942422),(41.215293,3.936608),(41.162996,3.94268),(41.114524,3.962343),(41.070082,3.996915),(41.0059,4.086677),(40.979751,4.110758),(40.963628,4.12037),(40.915879,4.136648),(40.897689,4.145924),(40.887354,4.156052),(40.870611,4.186981),(40.846013,4.214989),(40.785758,4.25584),(40.763744,4.284933),(40.700699,4.243515),(40.6175,4.211605),(40.511873,4.171064),(40.382682,4.121377),(40.376998,4.116081),(40.371106,4.099932),(40.365732,4.094867),(40.286874,4.067453),(40.185588,4.032158),(40.182797,4.032003),(40.1798,4.03283),(40.176803,4.034535),(40.167191,4.035465),(40.166261,4.031486),(40.166984,4.025259),(40.162437,4.019394),(40.117168,3.996915),(40.020223,3.950122),(39.93413,3.908703),(39.848451,3.867284),(39.828297,3.842583),(39.80866,3.790287),(39.780755,3.71657),(39.764218,3.685745),(39.745098,3.660579),(39.666447,3.588723),(39.600818,3.528907),(39.574979,3.497901),(39.553172,3.431316),(39.536325,3.405013),(39.504389,3.403333),(39.488473,3.413901),(39.480928,3.42726),(39.475657,3.440799),(39.466976,3.452013),(39.436176,3.462374),(39.311326,3.466094),(39.320525,3.484543),(39.315874,3.494904),(39.302748,3.495679),(39.296338,3.49199),(39.257583,3.469686),(39.219445,3.468704),(39.180481,3.476998),(39.090441,3.518334),(39.077542,3.524256),(39.06793,3.526582),(39.010466,3.514464),(38.994963,3.514257),(38.979977,3.519812),(38.963234,3.522086),(38.921272,3.513999),(38.895227,3.513585),(38.82071,3.533739),(38.722008,3.560404),(38.703715,3.570429),(38.688108,3.586294),(38.66103,3.621951),(38.661443,3.615336),(38.6601,3.601306),(38.660306,3.594459),(38.601912,3.59867),(38.596641,3.602133),(38.595608,3.607507),(38.593747,3.61084),(38.579588,3.605311),(38.57411,3.604561),(38.561088,3.606008),(38.547135,3.609522),(38.543208,3.615388),(38.541244,3.623294),(38.533182,3.632828),(38.514269,3.648512),(38.508998,3.650812),(38.499386,3.64691),(38.497319,3.63859),(38.498146,3.629676),(38.496906,3.62394),(38.445953,3.601668),(38.389935,3.596888),(38.283068,3.608902),(38.176925,3.620917),(38.145609,3.618437),(38.114087,3.610608),(38.101891,3.612649),(38.078843,3.632673),(38.048974,3.641846),(38.036158,3.648926),(38.020759,3.667167),(37.995334,3.707914),(37.976731,3.72644),(37.945931,3.746232),(37.846196,3.810337),(37.751008,3.871522),(37.647758,3.937874),(37.556084,3.996889),(37.475056,4.048979),(37.360954,4.122204),(37.263492,4.184888),(37.166031,4.247545),(37.111874,4.282298),(37.105983,4.283848),(37.099988,4.283693),(37.094821,4.284882),(37.091617,4.290256),(37.086449,4.312477),(37.082522,4.322166),(37.075907,4.33108),(37.068466,4.333458),(37.048415,4.331959),(37.041077,4.336817),(37.025367,4.363275),(37.015652,4.370587),(36.974828,4.37994),(36.903721,4.415778),(36.844087,4.432237),(36.651333,4.430583),(36.648857,4.43118),(36.642962,4.432599),(36.628182,4.441461),(36.619501,4.443373),(36.463025,4.440169),(36.277196,4.436449),(36.264277,4.438206),(36.246087,4.446991),(36.236268,4.449652),(36.225726,4.4496),(36.19131,4.444924),(36.045325,4.443716),(36.041345,4.443683),(36.018401,4.449135),(35.99711,4.462959),(35.958352,4.496858),(35.940472,4.508046),(35.933755,4.52218),(35.934065,4.539207),(35.937062,4.559258),(35.936028,4.578533),(35.922799,4.602072),(35.920835,4.619332),(35.784513,4.764181),(35.760018,4.805728),(35.751647,4.854356),(35.755884,5.063439),(35.760949,5.076332),(35.799189,5.124624),(35.807354,5.144674),(35.807147,5.165267),(35.798259,5.189271),(35.778415,5.22715),(35.775315,5.24658),(35.782033,5.26986),(35.809111,5.309109),(35.80415,5.318023),(35.749373,5.339158),(35.683641,5.379595),(35.658319,5.386417),(35.639819,5.382076),(35.621939,5.373782),(35.598168,5.368743),(35.57388,5.375332),(35.530782,5.410084),(35.508044,5.423417),(35.490164,5.428042),(35.469287,5.430755),(35.448203,5.430755),(35.430219,5.427215),(35.408205,5.412565),(35.367484,5.368046),(35.344953,5.352362),(35.320769,5.348719),(35.302372,5.357374),(35.287489,5.374092),(35.254623,5.425923),(35.250695,5.435147),(35.251832,5.447369),(35.258964,5.458143),(35.267645,5.468556),(35.27364,5.479873),(35.269299,5.491785),(35.261961,5.511887),(35.22341,5.542996),(35.143312,5.58966),(35.098663,5.622474),(35.088225,5.64175),(35.079543,5.699782),(35.06528,5.726447),(34.984355,5.841014),(34.974433,5.863106),(34.972676,5.876257),(34.974537,5.887239),(34.977741,5.898659),(34.979911,5.912844),(34.97681,5.924032),(34.960377,5.941706),(34.955313,5.952558),(34.955726,5.964211),(34.95924,5.975502),(34.969782,5.996689),(34.967964,6.008131),(34.959447,6.061724),(34.951489,6.08118),(34.934436,6.102368),(34.915522,6.119705),(34.898882,6.13867),(34.879969,6.187634),(34.844725,6.248689),(34.839764,6.268688),(34.839041,6.327599),(34.832633,6.353541),(34.792739,6.421676),(34.784264,6.44183),(34.776099,6.499449),(34.753878,6.556423),(34.743543,6.596808),(34.733518,6.637606),(34.726593,6.641947),(34.714501,6.655667),(34.709643,6.674012),(34.703545,6.684916),(34.635539,6.729823),(34.618486,6.736541),(34.596679,6.739202),(34.553994,6.739254),(34.53632,6.743078),(34.524745,6.752871),(34.517924,6.793824),(34.516683,6.798062),(34.512136,6.808268),(34.511102,6.814314),(34.513273,6.815296),(34.522575,6.821781),(34.524745,6.824572),(34.523298,6.844183),(34.519061,6.861649),(34.512343,6.876842),(34.503661,6.89002),(34.439169,6.934875),(34.297575,6.968568),(34.294475,6.972237),(34.287653,6.975286),(34.280729,6.980092),(34.275665,6.997403),(34.270807,7.003398),(34.229879,7.03337),(34.219957,7.046134),(34.213756,7.051974),(34.206005,7.054506),(34.198253,7.064376),(34.195773,7.086959),(34.195773,7.09774),(34.195773,7.129023),(34.190915,7.149539),(34.181407,7.167212),(34.167764,7.175377),(34.151124,7.167471),(34.132417,7.163388),(34.113194,7.177548),(34.085909,7.211499),(34.04002,7.247259),(34.033612,7.250256),(34.031132,7.255372),(34.030615,7.3487),(34.02369,7.382445),(34.006534,7.409936),(33.882407,7.536079),(33.852538,7.553545),(33.842099,7.555922),(33.821429,7.558403),(33.811507,7.560987),(33.761071,7.598142),(33.729445,7.642119),(33.71606,7.657156),(33.706552,7.661859),(33.675029,7.670851),(33.647744,7.688627),(33.637202,7.691315),(33.572297,7.685217),(33.550851,7.691315),(33.540361,7.698911),(33.526511,7.717101),(33.516796,7.726093),(33.506823,7.73095),(33.488477,7.73617),(33.479537,7.743146),(33.462329,7.749502),(33.436491,7.748572),(33.393289,7.739735),(33.384401,7.735446),(33.359803,7.719272),(33.347142,7.718961),(33.29159,7.733069),(33.273503,7.749192),(33.257794,7.767434),(33.242394,7.780715),(33.233919,7.783195),(33.201467,7.788156),(33.172941,7.799628),(33.164518,7.801127),(33.132117,7.793944),(33.126949,7.791567),(33.120851,7.783299),(33.107519,7.785211),(33.085401,7.794978),(33.058323,7.797975),(33.051295,7.801127),(33.047677,7.807277),(33.044629,7.816423),(33.040753,7.824846),(33.023493,7.835078),(33.015018,7.850633),(32.9898,7.917244),(32.993572,7.928148),(33.006801,7.942462),(33.007569,7.944058),(33.012021,7.953314),(33.016775,7.958327),(33.021633,7.965251),(33.026077,7.986284),(33.031141,7.996309),(33.043853,8.013465),(33.100594,8.071033),(33.106589,8.08049),(33.111343,8.090644),(33.11341,8.099093),(33.117544,8.104158),(33.147516,8.109067),(33.164776,8.117051),(33.177282,8.127102),(33.185137,8.14108),(33.187824,8.160898),(33.184723,8.166247),(33.171081,8.175962),(33.16798,8.181362),(33.16829,8.195392),(33.169944,8.205495),(33.173975,8.21459),(33.181623,8.225726),(33.190511,8.232419),(33.199865,8.235519),(33.206893,8.240738),(33.208288,8.253683),(33.194852,8.259239),(33.185757,8.26451),(33.178419,8.275672),(33.171391,8.283113),(33.164363,8.292777),(33.161159,8.304585),(33.163123,8.312052),(33.171804,8.330888),(33.174078,8.343058),(33.172321,8.34652),(33.163329,8.352954),(33.161159,8.356106),(33.161882,8.361506),(33.166843,8.368276),(33.16798,8.372823),(33.167877,8.389722),(33.16953,8.397421),(33.174078,8.404475),(33.187824,8.411038),(33.202913,8.414113),(33.210355,8.420779),(33.207358,8.426593),(33.206427,8.430572),(33.23516,8.455635),(33.25273,8.458167),(33.361353,8.434293),(33.370862,8.437393),(33.384608,8.448013),(33.392101,8.451862),(33.400162,8.452638),(33.413133,8.449718),(33.480519,8.45765),(33.489924,8.462921),(33.490338,8.466513),(33.484757,8.474006),(33.505117,8.474884),(33.521964,8.465324),(33.537053,8.453206),(33.552143,8.446824),(33.57116,8.450131),(33.585371,8.458115),(33.600099,8.463955),(33.620407,8.460699),(33.651672,8.434499),(33.671309,8.400289),(33.695545,8.372875),(33.74102,8.367087),(33.751872,8.368793),(33.756213,8.370136),(33.797658,8.405612),(33.808096,8.412614),(33.824116,8.419487),(33.840859,8.423983),(33.875172,8.427936),(33.931706,8.428143),(33.95031,8.433207),(33.970774,8.445377),(34.069579,8.533615),(34.090249,8.556507),(34.103169,8.579322),(34.107251,8.601531),(34.11185,8.626555),(34.097473,8.915836),(34.083096,9.205117),(34.070698,9.454592),(34.066892,9.531176),(34.098208,9.67972),(34.221921,10.02603),(34.280832,10.080109),(34.303466,10.113544),(34.305017,10.124603),(34.301606,10.148994),(34.301813,10.160285),(34.304603,10.165634),(34.314215,10.175452),(34.317419,10.181266),(34.325894,10.223563),(34.32486,10.268651),(34.276181,10.488715),(34.271737,10.530082),(34.279489,10.565506),(34.365582,10.685783),(34.404235,10.759835),(34.420048,10.780816),(34.437308,10.795673),(34.557818,10.877787),(34.574768,10.884143),(34.587067,10.879285),(34.708093,10.774072),(34.737445,10.755391),(34.750674,10.743945),(34.756979,10.728804),(34.752948,10.698728),(34.754395,10.684129),(34.764834,10.680254),(34.772895,10.688263),(34.786228,10.718985),(34.798527,10.729656),(34.815373,10.73131),(34.827569,10.72777),(34.838524,10.72914),(34.85134,10.745753),(34.857334,10.763556),(34.857438,10.775674),(34.861572,10.787586),(34.879762,10.804613),(34.933816,10.845308),(34.950662,10.869183),(34.95831,10.903418),(34.952832,10.91843),(34.92317,10.939928),(34.913558,10.952976),(34.914282,10.963957),(34.980324,11.155263),(34.984148,11.186398),(34.971436,11.206888),(34.953969,11.226112),(34.944254,11.253242),(34.947148,11.274868),(35.073135,11.54896),(35.076856,11.568649),(35.074375,11.587356),(35.053498,11.628077),(35.046263,11.648644),(35.048124,11.68952),(35.040579,11.727399),(35.041199,11.747604),(35.048227,11.771376),(35.059079,11.79587),(35.072722,11.818866),(35.088018,11.838193),(35.126672,11.862946),(35.148556,11.871229),(35.215555,11.896588),(35.245734,11.929867),(35.247802,11.939634),(35.248379,11.957858),(35.248525,11.962475),(35.251419,11.971725),(35.260411,11.980407),(35.297824,12.001594),(35.317358,12.023712),(35.32604,12.047483),(35.335962,12.102312),(35.353738,12.14603),(35.361283,12.157347),(35.371102,12.165512),(35.392909,12.176726),(35.403348,12.185097),(35.412546,12.198636),(35.41544,12.211142),(35.418127,12.238996),(35.428772,12.266953),(35.616875,12.575151),(35.625866,12.585124),(35.634445,12.588587),(35.653772,12.590034),(35.662453,12.593651),(35.672375,12.604296),(35.675992,12.614528),(35.677439,12.625225),(35.684261,12.650753),(35.684054,12.656076),(35.687671,12.659228),(35.70137,12.665421),(35.702761,12.66605),(35.728392,12.67437),(36.029976,12.717158),(36.038451,12.717468),(36.050647,12.715452),(36.057261,12.712145),(36.063049,12.707908),(36.072144,12.70305),(36.099429,12.69566),(36.115035,12.70181),(36.123614,12.721447),(36.143251,12.832551),(36.143044,12.856942),(36.138703,12.871851),(36.115346,12.911719),(36.114415,12.933889),(36.125991,12.950968),(36.140874,12.96554),(36.149865,12.980242),(36.149555,12.988821),(36.146351,12.997373),(36.138393,13.013315),(36.136946,13.032436),(36.233581,13.36164),(36.382099,13.571033),(36.391298,13.599352),(36.394812,13.655938),(36.398429,13.67604),(36.439942,13.776176),(36.458167,13.820139),(36.455376,13.870007),(36.438013,13.919952),(36.432535,13.944499),(36.432122,13.969924),(36.436566,13.991214),(36.52638,14.263523),(36.545707,14.263162),(36.553045,14.282773),(36.565654,14.292927),(36.5825,14.296751),(36.603791,14.29732),(36.61764,14.300446),(36.648543,14.31458),(36.668593,14.317784),(36.713655,14.317784),(36.72213,14.320057),(36.738357,14.329798),(36.748072,14.332072),(36.816388,14.332072),(36.848531,14.327783),(36.913746,14.309024),(36.946923,14.304735),(36.952814,14.300963),(36.970901,14.27683),(36.978859,14.27112),(36.986714,14.266831),(36.995395,14.264092),(37.005627,14.263162),(37.011518,14.265074),(37.026091,14.27683),(37.034256,14.277502),(37.052446,14.275331),(37.060197,14.27683),(37.072703,14.285305),(37.083452,14.297733),(37.090997,14.314218),(37.093787,14.335173),(37.094407,14.35915),(37.097818,14.379511),(37.105879,14.399226),(37.121072,14.420826),(37.149701,14.441936),(37.184221,14.449558),(37.258221,14.448111),(37.280029,14.45545),(37.293775,14.457439),(37.318166,14.43713),(37.33708,14.426356),(37.374907,14.373026),(37.390203,14.358169),(37.394027,14.350081),(37.395474,14.335173),(37.394957,14.312383),(37.397748,14.301738),(37.412217,14.293599),(37.452628,14.260578),(37.456969,14.254609),(37.464307,14.235825),(37.469371,14.210813),(37.475366,14.199574),(37.488182,14.194897),(37.498517,14.193088),(37.508749,14.188127),(37.5165,14.180557),(37.519498,14.170997),(37.520634,14.145443),(37.525285,14.128829),(37.535724,14.11684),(37.553707,14.105497),(37.564973,14.116685),(37.601043,14.200917),(37.658507,14.335173),(37.721242,14.481753),(37.785631,14.632183),(37.85064,14.783879),(37.891464,14.879532),(37.908828,14.864727),(37.92092,14.847519),(37.94004,14.81088),(37.944381,14.80734),(37.954096,14.806255),(37.95761,14.802844),(37.958127,14.798762),(37.957817,14.788194),(37.958437,14.785093),(37.962261,14.777859),(37.964432,14.771193),(37.968772,14.766387),(37.980038,14.764552),(37.989856,14.757317),(37.992027,14.749514),(37.99275,14.740755),(37.998435,14.730911),(38.006703,14.7244),(38.115223,14.681017),(38.13331,14.677762)] +Georgia [(40.479834,43.508741),(40.519624,43.505175),(40.550837,43.511247),(40.615536,43.535845),(40.651916,43.538971),(40.681062,43.528068),(40.689966,43.523129),(40.740179,43.495279),(40.842706,43.469389),(40.874952,43.455643),(41.011791,43.375416),(41.042487,43.369834),(41.146666,43.37986),(41.180773,43.374692),(41.213122,43.362781),(41.243921,43.344203),(41.278751,43.333196),(41.350271,43.34335),(41.380657,43.334772),(41.389752,43.324876),(41.403808,43.301518),(41.41311,43.291286),(41.427579,43.283199),(41.479773,43.271236),(41.506128,43.25979),(41.550569,43.226277),(41.577544,43.215296),(41.614131,43.213022),(41.687408,43.220205),(41.723789,43.217234),(41.788901,43.203566),(41.82032,43.20124),(41.88998,43.207028),(41.919332,43.205943),(41.948271,43.200077),(41.97969,43.188657),(42.011316,43.181861),(42.043356,43.18057),(42.075292,43.185272),(42.154334,43.217498),(42.159834,43.21974),(42.185363,43.225476),(42.354551,43.236018),(42.36256,43.235194),(42.422867,43.22899),(42.479712,43.200904),(42.506067,43.181551),(42.534902,43.165067),(42.59588,43.140029),(42.615207,43.13698),(42.629366,43.14127),(42.656238,43.159796),(42.673602,43.165893),(42.704917,43.166436),(42.75153,43.176952),(42.79132,43.176177),(42.829768,43.168761),(42.857673,43.155455),(42.885785,43.135844),(42.914827,43.121943),(43.000093,43.098662),(43.000197,43.085356),(42.992548,43.068819),(42.989758,43.05267),(42.998853,43.042206),(43.048256,43.016962),(43.155588,42.942393),(43.175228,42.934471),(43.194345,42.926761),(43.386178,42.886882),(43.479599,42.867462),(43.517426,42.86046),(43.586259,42.835629),(43.603002,42.824803),(43.644343,42.788578),(43.662843,42.779845),(43.755964,42.763127),(43.782526,42.753213),(43.800613,42.746462),(43.811775,42.717265),(43.788727,42.69308),(43.753794,42.674657),(43.725682,42.6544),(43.722581,42.624867),(43.751107,42.598745),(43.796169,42.58983),(43.845003,42.58704),(43.885362,42.579211),(43.908161,42.566283),(43.920812,42.559109),(43.939726,42.55221),(43.958433,42.554406),(43.973212,42.563992),(43.998017,42.589365),(44.011504,42.600321),(44.055068,42.615307),(44.150824,42.618666),(44.185803,42.626508),(44.197384,42.629105),(44.211351,42.639634),(44.230147,42.653806),(44.248648,42.681995),(44.272005,42.702382),(44.360682,42.703751),(44.401403,42.713518),(44.479228,42.744291),(44.508115,42.750286),(44.558293,42.753102),(44.600977,42.749123),(44.638759,42.740149),(44.642422,42.739279),(44.679422,42.723672),(44.695029,42.714216),(44.724484,42.691039),(44.73637,42.677551),(44.761071,42.619234),(44.773473,42.609648),(44.78231,42.61665),(44.798485,42.671738),(44.827424,42.717962),(44.833676,42.734085),(44.85936,42.75951),(44.902974,42.753076),(45.012115,42.695302),(45.029788,42.688765),(45.048082,42.685897),(45.066995,42.688455),(45.076018,42.691412),(45.103892,42.700547),(45.122961,42.702278),(45.155362,42.693261),(45.184198,42.674838),(45.282693,42.586394),(45.293648,42.572906),(45.301571,42.559842),(45.312562,42.54172),(45.32269,42.530118),(45.35597,42.519964),(45.398551,42.524382),(45.47927,42.54234),(45.536838,42.541358),(45.620657,42.530377),(45.698688,42.507587),(45.739616,42.471466),(45.739506,42.470647),(45.736412,42.447539),(45.62138,42.224478),(45.631405,42.201172),(45.661585,42.186703),(45.701789,42.17275),(45.811601,42.115492),(45.881364,42.102031),(45.895162,42.091876),(45.923481,42.039631),(45.934126,42.028495),(45.947562,42.022914),(45.966372,42.022061),(45.973503,42.024154),(45.986733,42.031906),(45.995156,42.033456),(46.001615,42.030976),(46.018359,42.020046),(46.02673,42.01679),(46.044817,42.017721),(46.05846,42.02033),(46.068278,42.015318),(46.074996,41.993484),(46.099181,41.985061),(46.129876,41.984493),(46.188581,41.993536),(46.188891,41.993639),(46.189201,41.993769),(46.197676,41.9955),(46.206151,41.996094),(46.214574,41.9955),(46.224341,41.993484),(46.250489,41.977723),(46.294156,41.93863),(46.322629,41.929018),(46.382057,41.925246),(46.406552,41.91504),(46.430892,41.890442),(46.392754,41.831685),(46.371309,41.805692),(46.328314,41.766418),(46.313741,41.756651),(46.297773,41.750812),(46.276947,41.749313),(46.230129,41.757323),(46.208321,41.755514),(46.188994,41.740141),(46.179537,41.705879),(46.180002,41.655159),(46.192767,41.610174),(46.21969,41.593302),(46.228475,41.598728),(46.233436,41.607952),(46.24005,41.615497),(46.2539,41.615911),(46.256174,41.610329),(46.278394,41.578393),(46.279871,41.571172),(46.287851,41.532143),(46.29674,41.510387),(46.313948,41.493747),(46.366244,41.466566),(46.377923,41.462483),(46.398284,41.458711),(46.445103,41.425948),(46.542461,41.394994),(46.591554,41.372928),(46.607367,41.345023),(46.62287,41.349622),(46.629841,41.346136),(46.631034,41.345539),(46.637752,41.336961),(46.657079,41.320631),(46.688499,41.284355),(46.694803,41.269782),(46.691703,41.268542),(46.683434,41.269472),(46.674649,41.261669),(46.672686,41.253969),(46.6716,41.236451),(46.669482,41.229888),(46.663591,41.223531),(46.650361,41.214178),(46.64447,41.207977),(46.634755,41.181053),(46.629484,41.14674),(46.621113,41.114597),(46.615539,41.108666),(46.601786,41.09403),(46.582148,41.091653),(46.563132,41.095581),(46.543546,41.097027),(46.522411,41.087002),(46.511145,41.070983),(46.505564,41.055273),(46.496779,41.044834),(46.47492,41.044111),(46.456988,41.052431),(46.429031,41.080956),(46.41265,41.09186),(46.353119,41.106536),(46.332345,41.115889),(46.273433,41.1563),(46.244391,41.183741),(46.228578,41.195419),(46.210595,41.200174),(46.135406,41.199915),(46.113133,41.19604),(46.087608,41.183659),(46.061353,41.170925),(46.041613,41.165447),(46.017428,41.163793),(45.969163,41.168289),(45.820748,41.208804),(45.770337,41.232102),(45.751088,41.240998),(45.709747,41.267715),(45.685872,41.29624),(45.708093,41.317117),(45.731038,41.323267),(45.7453,41.329158),(45.74406,41.335359),(45.720702,41.342387),(45.65559,41.352361),(45.511826,41.39458),(45.47927,41.41768),(45.464801,41.430185),(45.450021,41.432201),(45.416948,41.424604),(45.396794,41.423261),(45.38124,41.425586),(45.333096,41.444352),(45.314422,41.451631),(45.281711,41.452923),(45.24962,41.4445),(45.097834,41.349919),(45.0024,41.290452),(44.989998,41.284458),(44.967363,41.269007),(44.955168,41.262702),(44.917237,41.261772),(44.820706,41.273347),(44.801275,41.258516),(44.809543,41.244409),(44.847061,41.230766),(44.85382,41.223514),(44.857706,41.219346),(44.847784,41.208907),(44.821532,41.20622),(44.674926,41.208494),(44.63312,41.221051),(44.612863,41.223118),(44.591366,41.21578),(44.578446,41.202809),(44.566251,41.186944),(44.551523,41.177023),(44.531008,41.181467),(44.52553,41.189063),(44.521912,41.199295),(44.516641,41.20684),(44.505893,41.206582),(44.499382,41.202809),(44.479228,41.185808),(44.45494,41.180485),(44.432461,41.181673),(44.410601,41.18772),(44.357271,41.212163),(44.344921,41.213248),(44.333087,41.210354),(44.324922,41.204825),(44.317739,41.198572),(44.308489,41.193817),(44.284976,41.190872),(44.266476,41.196195),(44.218107,41.221568),(44.190977,41.230043),(44.180331,41.229939),(44.168446,41.223583),(44.165862,41.216142),(44.16519,41.207667),(44.160074,41.1979),(44.144364,41.186066),(44.124727,41.178056),(44.103643,41.175162),(44.061269,41.184154),(44.041322,41.182552),(44.001117,41.168858),(43.978186,41.164617),(43.977755,41.164537),(43.955849,41.160486),(43.863245,41.158988),(43.820353,41.1455),(43.773741,41.114494),(43.754156,41.108241),(43.729713,41.106691),(43.566622,41.124054),(43.524144,41.122814),(43.470142,41.106174),(43.460324,41.104521),(43.450453,41.104676),(43.440428,41.106588),(43.451797,41.132581),(43.437586,41.156197),(43.410559,41.175162),(43.383274,41.187203),(43.351751,41.193611),(43.322606,41.19206),(43.230622,41.17263),(43.216204,41.180537),(43.192226,41.224978),(43.172021,41.242342),(43.152332,41.24415),(43.130318,41.24229),(43.103136,41.248801),(43.157241,41.26973),(43.171866,41.279342),(43.185353,41.293811),(43.18401,41.298979),(43.154761,41.301873),(43.12391,41.312932),(43.075644,41.344868),(43.002057,41.382695),(42.987588,41.394684),(42.957719,41.437007),(42.949967,41.443673),(42.941079,41.446308),(42.936221,41.450236),(42.93219,41.454783),(42.926093,41.459073),(42.896637,41.466566),(42.888989,41.469976),(42.880721,41.481242),(42.87514,41.493696),(42.868008,41.500207),(42.854572,41.493799),(42.829974,41.472508),(42.811164,41.477159),(42.792147,41.492869),(42.766516,41.504341),(42.774887,41.514263),(42.794628,41.52682),(42.802689,41.534107),(42.806823,41.542995),(42.80889,41.552917),(42.812198,41.562994),(42.819949,41.572347),(42.800932,41.57922),(42.660992,41.588264),(42.610556,41.58506),(42.590914,41.580169),(42.586648,41.579107),(42.585235,41.578755),(42.565184,41.567128),(42.554952,41.550333),(42.545547,41.509612),(42.535522,41.493489),(42.513818,41.476229),(42.483846,41.442174),(42.463072,41.431839),(42.451033,41.43137),(42.437854,41.430857),(42.262464,41.482327),(42.213268,41.480208),(42.18929,41.481707),(42.17265,41.493489),(42.158387,41.499897),(42.143195,41.500259),(42.111775,41.493489),(42.097513,41.498347),(42.083457,41.500104),(42.069401,41.498605),(42.054931,41.493489),(42.019585,41.485066),(41.947961,41.505581),(41.907757,41.493489),(41.894011,41.485531),(41.862695,41.451786),(41.822594,41.426),(41.812982,41.421814),(41.800787,41.42569),(41.760996,41.453543),(41.747767,41.45685),(41.718518,41.459589),(41.706839,41.463155),(41.702601,41.46946),(41.702808,41.477624),(41.703945,41.485117),(41.702601,41.489045),(41.694953,41.489097),(41.669839,41.480467),(41.63997,41.47871),(41.627257,41.480518),(41.520763,41.514228),(41.586274,41.602729),(41.615733,41.632636),(41.676036,41.662177),(41.692882,41.692288),(41.739757,41.749905),(41.742361,41.761664),(41.742442,41.770697),(41.743907,41.778632),(41.750011,41.787502),(41.766287,41.804185),(41.771821,41.812567),(41.773936,41.821601),(41.773936,41.90261),(41.773936,41.902615),(41.773936,41.906928),(41.761974,41.969875),(41.760265,41.99258),(41.755707,42.006415),(41.715261,42.059353),(41.684906,42.098944),(41.674327,42.105536),(41.664073,42.113959),(41.65919,42.133002),(41.657237,42.16706),(41.649181,42.212226),(41.596202,42.349433),(41.592296,42.355414),(41.585216,42.36286),(41.55836,42.382799),(41.554861,42.389838),(41.551199,42.40644),(41.551195,42.406457),(41.500173,42.64057),(41.482758,42.680243),(41.457367,42.71369),(41.424327,42.739895),(41.383474,42.75727),(41.307302,42.767646),(41.291026,42.774359),(41.274913,42.785305),(41.250743,42.795233),(41.225352,42.802314),(41.205333,42.804429),(41.193696,42.801907),(41.173595,42.792792),(41.160899,42.790839),(41.150238,42.79564),(41.104747,42.846584),(41.081798,42.908149),(41.040294,42.96133),(41.023123,42.989976),(40.998383,42.989447),(40.958995,42.976386),(40.933767,42.982733),(40.903982,43.016343),(40.886567,43.024156),(40.886241,43.029283),(40.862804,43.058987),(40.855968,43.063056),(40.783051,43.084174),(40.682872,43.094306),(40.636241,43.092475),(40.604015,43.086493),(40.591807,43.085639),(40.579926,43.088813),(40.56072,43.102973),(40.550548,43.106106),(40.546072,43.108832),(40.528982,43.12226),(40.520193,43.127265),(40.510265,43.12995),(40.478526,43.134019),(40.398285,43.16234),(40.361176,43.165473),(40.335134,43.140855),(40.325043,43.14883),(40.310313,43.175727),(40.301036,43.188666),(40.278331,43.205512),(40.268403,43.216376),(40.272797,43.247992),(40.257172,43.277411),(40.235199,43.304429),(40.219086,43.319037),(40.188243,43.329576),(40.133474,43.34162),(40.101329,43.36518),(40.086925,43.370307),(40.040782,43.3758),(40.009776,43.385159),(39.986013,43.388983),(39.985976,43.38899),(39.991285,43.406318),(40.059187,43.535199),(40.07283,43.551064),(40.096705,43.562639),(40.164297,43.575843),(40.23313,43.575765),(40.479834,43.508741)] +Ghana [(-0.166109,11.13498),(-0.158668,11.118444),(-0.14208,11.103329),(-0.121745,11.092192),(-0.103348,11.087541),(-0.085029,11.089402),(-0.051077,11.098264),(-0.032267,11.098574),(0.001116,11.085991),(0.016205,11.062582),(0.019409,11.031628),(0.016567,10.996203),(0.01419,10.983672),(0.007188,10.976799),(-0.001571,10.971295),(-0.009581,10.963001),(-0.014439,10.953596),(-0.036091,10.853137),(-0.035316,10.843448),(-0.0302,10.823785),(-0.032061,10.813165),(-0.04069,10.805026),(-0.061103,10.791358),(-0.07521,10.773659),(-0.082807,10.756218),(-0.088129,10.714412),(-0.091564,10.700254),(-0.09769,10.675008),(-0.098336,10.654157),(-0.088129,10.633486),(-0.079344,10.626252),(-0.068363,10.621058),(-0.056452,10.618009),(-0.033352,10.615064),(-0.026221,10.610361),(-0.019968,10.604341),(-0.010925,10.598269),(0.020339,10.588037),(0.029434,10.582533),(0.037341,10.57318),(0.04902,10.550959),(0.057262,10.541115),(0.110179,10.508249),(0.126018,10.491609),(0.176971,10.397687),(0.179865,10.394173),(0.187513,10.394948),(0.19175,10.400839),(0.194437,10.407376),(0.197073,10.41027),(0.223609,10.399961),(0.23322,10.398617),(0.244563,10.401537),(0.253943,10.406084),(0.263012,10.408926),(0.273244,10.406601),(0.283114,10.396808),(0.283553,10.385775),(0.28022,10.375182),(0.278825,10.366629),(0.290039,10.348491),(0.307066,10.333272),(0.317582,10.31733),(0.308797,10.297099),(0.32275,10.297254),(0.366597,10.304488),(0.376183,10.299941),(0.396596,10.283224),(0.372049,10.265137),(0.367295,10.249815),(0.364427,10.233407),(0.357192,10.219997),(0.358846,10.18633),(0.353601,10.115508),(0.363393,10.089669),(0.37608,10.081582),(0.387087,10.078947),(0.395149,10.072358),(0.398146,10.052127),(0.39457,10.035557),(0.393908,10.03249),(0.382746,10.029596),(0.367295,10.032128),(0.349777,10.02882),(0.355719,10.018976),(0.355125,10.01262),(0.35174,10.006419),(0.349777,9.997169),(0.35143,9.990451),(0.363393,9.966783),(0.370189,9.947017),(0.369569,9.938826),(0.362592,9.932676),(0.349777,9.918956),(0.341715,9.903789),(0.339674,9.889837),(0.344196,9.849762),(0.343886,9.838393),(0.32244,9.760671),(0.323887,9.742068),(0.329132,9.731293),(0.336289,9.72349),(0.342955,9.713543),(0.347606,9.698841),(0.34988,9.680651),(0.347089,9.663158),(0.336651,9.650833),(0.318719,9.648611),(0.301924,9.657835),(0.275285,9.685586),(0.260971,9.657164),(0.261694,9.627941),(0.277636,9.606986),(0.308797,9.603678),(0.349363,9.61391),(0.369155,9.610138),(0.377734,9.589416),(0.370809,9.575644),(0.354608,9.571096),(0.33616,9.574197),(0.32244,9.583137),(0.30456,9.571562),(0.28053,9.570166),(0.230197,9.575747),(0.227743,9.569339),(0.223066,9.541176),(0.223402,9.534794),(0.225908,9.531926),(0.23322,9.525595),(0.243116,9.518697),(0.253503,9.514252),(0.279006,9.519007),(0.293139,9.518283),(0.301924,9.507457),(0.2981,9.497096),(0.28531,9.488363),(0.26973,9.482342),(0.228053,9.473971),(0.227949,9.459734),(0.234977,9.443766),(0.226813,9.432345),(0.23136,9.418961),(0.249886,9.416946),(0.26849,9.420641),(0.314223,9.436479),(0.32182,9.442836),(0.325747,9.451336),(0.328796,9.471568),(0.333783,9.479474),(0.34895,9.486037),(0.371429,9.490016),(0.411659,9.492238),(0.430444,9.489189),(0.483515,9.470017),(0.489923,9.461129),(0.49168,9.451285),(0.489406,9.441027),(0.482792,9.429839),(0.482585,9.428857),(0.482792,9.427875),(0.483515,9.426842),(0.513281,9.416791),(0.531368,9.401107),(0.537569,9.377646),(0.528267,9.326951),(0.526613,9.297651),(0.522479,9.285067),(0.512351,9.274706),(0.501085,9.268195),(0.49292,9.258609),(0.49199,9.238895),(0.504393,9.203109),(0.504703,9.187166),(0.49261,9.166754),(0.469976,9.14673),(0.463646,9.137092),(0.463749,9.12146),(0.458478,9.08924),(0.441554,9.058182),(0.43127,9.02759),(0.44468,8.996558),(0.444887,8.996558),(0.444887,8.996455),(0.493127,8.915219),(0.505633,8.866333),(0.483629,8.834973),(0.483515,8.834811),(0.478451,8.822331),(0.477004,8.80675),(0.47349,8.793547),(0.462483,8.788302),(0.449512,8.790369),(0.439409,8.793444),(0.430134,8.794736),(0.419592,8.791247),(0.424966,8.78732),(0.4183,8.770603),(0.407809,8.759053),(0.397112,8.781532),(0.385278,8.78608),(0.372669,8.783754),(0.365874,8.774272),(0.368084,8.761481),(0.374426,8.724766),(0.403727,8.662082),(0.443518,8.606866),(0.483515,8.579787),(0.500568,8.560176),(0.524753,8.538033),(0.550798,8.519326),(0.616324,8.488759),(0.63379,8.452018),(0.646709,8.414165),(0.685053,8.382564),(0.687224,8.372203),(0.686914,8.360731),(0.689394,8.346055),(0.688567,8.33603),(0.689187,8.331301),(0.693115,8.327891),(0.705104,8.325979),(0.708825,8.322568),(0.712752,8.29797),(0.705207,8.282751),(0.689187,8.272855),(0.645056,8.253425),(0.628313,8.24247),(0.595033,8.21273),(0.586661,8.208751),(0.579013,8.207821),(0.573846,8.203945),(0.572709,8.191),(0.576843,8.180484),(0.584594,8.173068),(0.591519,8.16449),(0.593276,8.150666),(0.587798,8.137721),(0.579943,8.131701),(0.574983,8.124621),(0.580254,8.100075),(0.583974,8.05305),(0.593173,8.015739),(0.593689,7.996567),(0.592863,7.959309),(0.602688,7.893132),(0.603405,7.888305),(0.602578,7.828412),(0.611673,7.771258),(0.609502,7.718961),(0.612293,7.699428),(0.583354,7.704285),(0.570538,7.683925),(0.567438,7.652919),(0.567748,7.625737),(0.562063,7.612301),(0.548524,7.605377),(0.532505,7.601036),(0.519379,7.595196),(0.50925,7.585378),(0.503049,7.574681),(0.499432,7.562382),(0.495608,7.504298),(0.500568,7.45505),(0.516692,7.411022),(0.548214,7.383271),(0.566404,7.380791),(0.586248,7.384357),(0.623042,7.397896),(0.629656,7.389162),(0.645676,7.323585),(0.644436,7.301933),(0.631103,7.265242),(0.621801,7.218837),(0.59772,7.158892),(0.59431,7.119722),(0.598754,7.074711),(0.59803,7.0312),(0.57891,6.996783),(0.565991,6.989652),(0.523823,6.978697),(0.509147,6.977611),(0.494574,6.973116),(0.506046,6.957819),(0.534468,6.935909),(0.54625,6.914773),(0.543873,6.897926),(0.522789,6.862838),(0.516071,6.841806),(0.519275,6.832246),(0.528887,6.826535),(0.541083,6.817182),(0.570022,6.763516),(0.576636,6.754731),(0.593793,6.751114),(0.611259,6.741528),(0.625832,6.727756),(0.634307,6.711607),(0.635341,6.695381),(0.626659,6.644893),(0.63224,6.62399),(0.645366,6.612026),(0.659422,6.601717),(0.668207,6.585827),(0.677612,6.584896),(0.705517,6.585775),(0.714612,6.583914),(0.727428,6.571435),(0.726808,6.562107),(0.71978,6.552728),(0.713475,6.53999),(0.713076,6.533936),(0.711718,6.513376),(0.71792,6.48883),(0.729908,6.465085),(0.745721,6.4409),(0.766805,6.419351),(0.816208,6.395063),(0.841323,6.379224),(0.873879,6.340131),(0.886798,6.33039),(0.907262,6.324912),(0.983536,6.324602),(1.009685,6.244452),(1.025188,6.222334),(1.033146,6.216547),(1.040587,6.213472),(1.048132,6.20939),(1.05578,6.20063),(1.068906,6.180347),(1.079655,6.167919),(1.093401,6.160917),(1.176186,6.151512),(1.187968,6.135647),(1.185396,6.100491),(1.185395,6.100491),(1.184825,6.100328),(1.178396,6.097968),(1.133067,6.073635),(1.098806,6.047024),(1.048025,5.992662),(1.036388,5.975165),(1.011729,5.926256),(1.007091,5.906684),(1.005626,5.886054),(0.995291,5.839342),(0.986583,5.820746),(0.954845,5.791083),(0.914399,5.777086),(0.723481,5.755439),(0.364919,5.78148),(0.321951,5.779202),(0.298106,5.773668),(0.285981,5.768866),(0.280935,5.763007),(0.27589,5.760159),(0.25172,5.759101),(0.243337,5.756171),(0.224376,5.742621),(0.1574,5.724555),(0.1421,5.71426),(0.114594,5.688666),(0.075694,5.677558),(0.061697,5.662828),(0.050629,5.644761),(0.034516,5.628363),(-0.045033,5.60163),(-0.049672,5.598863),(-0.062734,5.585842),(-0.068593,5.581204),(-0.077382,5.57807),(-0.093251,5.576646),(-0.307851,5.507392),(-0.353098,5.501695),(-0.359283,5.498684),(-0.371571,5.492743),(-0.445058,5.431383),(-0.45287,5.420111),(-0.458119,5.404731),(-0.471588,5.390815),(-0.507436,5.368842),(-0.577382,5.35163),(-0.589345,5.351508),(-0.596669,5.344306),(-0.612864,5.332017),(-0.629465,5.326728),(-0.637766,5.340888),(-0.689524,5.304755),(-0.702301,5.299994),(-0.760732,5.252183),(-0.784495,5.22427),(-0.79955,5.21483),(-0.873891,5.204006),(-0.89684,5.205024),(-0.911488,5.218004),(-0.918284,5.209418),(-0.927724,5.206122),(-0.952463,5.204413),(-0.976552,5.19831),(-0.988393,5.198798),(-0.993479,5.20775),(-0.99706,5.216783),(-1.005035,5.214545),(-1.017323,5.204413),(-1.033803,5.202948),(-1.049794,5.198676),(-1.154124,5.153876),(-1.164703,5.139228),(-1.173655,5.130561),(-1.194081,5.118598),(-1.233632,5.100735),(-1.25414,5.096503),(-1.319244,5.09455),(-1.329986,5.091539),(-1.353139,5.077786),(-1.364003,5.073432),(-1.374135,5.072659),(-1.394765,5.07392),(-1.404937,5.073432),(-1.423451,5.06745),(-1.459706,5.04975),(-1.529286,5.039862),(-1.551869,5.031399),(-1.568796,5.019273),(-1.569488,5.018785),(-1.583852,5.025377),(-1.601471,5.026679),(-1.618479,5.022447),(-1.630849,5.012641),(-1.632436,5.004543),(-1.625478,4.989488),(-1.627756,4.981594),(-1.634023,4.974433),(-1.638173,4.970689),(-1.706654,4.936916),(-1.718821,4.92768),(-1.74767,4.895901),(-1.749908,4.888577),(-1.748118,4.881903),(-1.748606,4.877183),(-1.757436,4.875434),(-1.766754,4.874701),(-1.835439,4.855129),(-1.912099,4.820868),(-1.92809,4.806789),(-1.95226,4.772447),(-1.967275,4.758124),(-1.981435,4.752427),(-2.050364,4.743638),(-2.063832,4.738186),(-2.090566,4.737128),(-2.096588,4.738471),(-2.103871,4.745063),(-2.106679,4.755357),(-2.105621,4.766547),(-2.107981,4.77558),(-2.120961,4.779202),(-2.129018,4.780341),(-2.144154,4.78498),(-2.155385,4.786078),(-2.154368,4.790676),(-2.163726,4.800523),(-2.206288,4.834459),(-2.227406,4.843411),(-2.23705,4.849189),(-2.241119,4.858059),(-2.242828,4.865383),(-2.247222,4.873033),(-2.252756,4.879136),(-2.356597,4.919623),(-2.525787,4.954413),(-2.690419,5.010199),(-2.820872,5.020087),(-2.964996,5.045315),(-3.103749,5.087714),(-3.119601,5.091331),(-3.115281,5.107821),(-3.108306,5.109605),(-3.098988,5.113227),(-3.087636,5.114976),(-3.016103,5.114447),(-2.994496,5.10814),(-2.988515,5.10224),(-2.976308,5.084621),(-2.970937,5.080878),(-2.957753,5.082668),(-2.937245,5.091295),(-2.92634,5.09455),(-2.929026,5.122016),(-2.901235,5.133612),(-2.865305,5.139309),(-2.843699,5.149115),(-2.843658,5.149115),(-2.803855,5.147568),(-2.780885,5.150875),(-2.766622,5.16103),(-2.75701,5.179866),(-2.762488,5.1863),(-2.775666,5.197539),(-2.778818,5.201001),(-2.779645,5.210122),(-2.775407,5.231025),(-2.774891,5.239578),(-2.779335,5.251076),(-2.793287,5.271101),(-2.79613,5.284976),(-2.789567,5.346858),(-2.755874,5.340709),(-2.742593,5.343138),(-2.732671,5.355721),(-2.730139,5.373162),(-2.734428,5.391145),(-2.761713,5.454914),(-2.779438,5.526485),(-2.781815,5.578885),(-2.785588,5.595034),(-2.793442,5.608134),(-2.806258,5.618495),(-2.877494,5.636815),(-2.893746,5.630355),(-2.926302,5.610718),(-2.945862,5.608289),(-2.969504,5.621441),(-2.974904,5.647279),(-2.964801,5.709782),(-3.029759,5.704252),(-3.019966,5.818354),(-3.022524,5.854502),(-3.03472,5.890701),(-3.073244,5.960955),(-3.087765,5.996689),(-3.118074,6.163475),(-3.139364,6.219286),(-3.168794,6.246054),(-3.171722,6.249585),(-3.183599,6.263908),(-3.262509,6.617142),(-3.261114,6.633937),(-3.253905,6.644428),(-3.235483,6.654582),(-3.230057,6.661119),(-3.210419,6.715999),(-3.212745,6.722666),(-3.226232,6.748581),(-3.238738,6.764627),(-3.243079,6.774756),(-3.241684,6.810903),(-3.224941,6.849402),(-3.109599,7.046393),(-3.097274,7.054053),(-3.096593,7.054477),(-3.095465,7.055178),(-3.045933,7.071249),(-3.040869,7.078329),(-3.032601,7.128352),(-3.027537,7.138428),(-2.9817,7.195531),(-2.972811,7.214961),(-2.972088,7.228604),(-2.976532,7.236717),(-2.983224,7.244985),(-2.989529,7.258938),(-2.990459,7.270668),(-2.941521,7.577161),(-2.928163,7.617676),(-2.855945,7.771568),(-2.852069,7.778131),(-2.842018,7.790275),(-2.838168,7.796838),(-2.83791,7.802264),(-2.84083,7.815235),(-2.840003,7.820247),(-2.831399,7.82836),(-2.809152,7.841693),(-2.801194,7.85022),(-2.797887,7.861278),(-2.793546,7.935951),(-2.790626,7.943289),(-2.784347,7.944012),(-2.777681,7.93962),(-2.772617,7.933935),(-2.771221,7.930732),(-2.754892,7.944374),(-2.709261,7.996722),(-2.690865,8.009745),(-2.631178,8.029589),(-2.610559,8.040001),(-2.600689,8.052946),(-2.599759,8.070387),(-2.606219,8.094313),(-2.619448,8.123097),(-2.621877,8.135732),(-2.617639,8.151493),(-2.610663,8.164852),(-2.604255,8.170794),(-2.595987,8.170278),(-2.583274,8.164335),(-2.57175,8.16312),(-2.558108,8.167694),(-2.513201,8.194023),(-2.506328,8.209267),(-2.552346,8.489367),(-2.598364,8.769466),(-2.603118,8.78515),(-2.612161,8.780964),(-2.612382,8.781321),(-2.617226,8.78918),(-2.614642,8.801919),(-2.607252,8.808559),(-2.596658,8.814398),(-2.595573,8.828067),(-2.615934,8.89783),(-2.617174,8.915013),(-2.619448,8.923617),(-2.625029,8.925994),(-2.631747,8.926976),(-2.63769,8.931471),(-2.653296,8.978394),(-2.654329,8.998832),(-2.660789,9.014903),(-2.686059,9.028261),(-2.711328,9.033894),(-2.73696,9.035134),(-2.750809,9.037408),(-2.758664,9.04286),(-2.765072,9.049475),(-2.774839,9.054978),(-2.765434,9.069112),(-2.7613,9.084795),(-2.759388,9.134818),(-2.755202,9.143138),(-2.733911,9.164842),(-2.716496,9.200266),(-2.704817,9.218405),(-2.673088,9.23489),(-2.661151,9.253907),(-2.659807,9.272898),(-2.675517,9.281502),(-2.692983,9.285326),(-2.707143,9.295635),(-2.714998,9.311061),(-2.713344,9.329923),(-2.70306,9.343255),(-2.689418,9.349534),(-2.677532,9.357001),(-2.672416,9.374028),(-2.672416,9.401004),(-2.677377,9.417773),(-2.678669,9.42555),(-2.674587,9.457486),(-2.675672,9.471723),(-2.689211,9.488724),(-2.725281,9.533864),(-2.761093,9.566239),(-2.766261,9.576523),(-2.768018,9.592801),(-2.766467,9.608898),(-2.761506,9.625253),(-2.752928,9.639904),(-2.740164,9.650833),(-2.743404,9.653325),(-2.751016,9.659179),(-2.75422,9.668352),(-2.75546,9.677498),(-2.760524,9.685586),(-2.769258,9.689926),(-2.774839,9.689306),(-2.780317,9.690237),(-2.788481,9.699254),(-2.795303,9.720002),(-2.791582,9.740931),(-2.774839,9.77434),(-2.740267,9.812606),(-2.733911,9.822787),(-2.736753,9.832579),(-2.760524,9.870536),(-2.764865,9.895754),(-2.755564,9.941151),(-2.754375,9.966783),(-2.760886,9.984766),(-2.783572,10.018511),(-2.788481,10.038768),(-2.788481,10.124448),(-2.79892,10.169613),(-2.798455,10.189534),(-2.785381,10.210101),(-2.765124,10.225837),(-2.757682,10.234648),(-2.754375,10.247954),(-2.754943,10.260796),(-2.758354,10.266119),(-2.764865,10.269116),(-2.774839,10.27524),(-2.784451,10.278805),(-2.793184,10.278547),(-2.799669,10.280924),(-2.802098,10.292319),(-2.80569,10.299011),(-2.814216,10.301078),(-2.824448,10.302215),(-2.833182,10.305987),(-2.841295,10.322291),(-2.841295,10.343272),(-2.836282,10.363658),(-2.829461,10.378282),(-2.822329,10.387584),(-2.81463,10.393708),(-2.80494,10.397118),(-2.791995,10.398152),(-2.78104,10.402415),(-2.771893,10.41182),(-2.767552,10.4212),(-2.771428,10.425489),(-2.795871,10.426109),(-2.812149,10.428822),(-2.824448,10.435023),(-2.859562,10.465616),(-2.867391,10.47825),(-2.87044,10.497784),(-2.873386,10.502487),(-2.886899,10.515793),(-2.891524,10.521659),(-2.894211,10.531425),(-2.895865,10.552768),(-2.898294,10.562612),(-2.928266,10.615219),(-2.932504,10.634313),(-2.929661,10.644209),(-2.916251,10.668084),(-2.910154,10.684491),(-2.907337,10.688315),(-2.905115,10.692733),(-2.905141,10.699193),(-2.908035,10.703637),(-2.912634,10.705808),(-2.916949,10.706609),(-2.918913,10.706609),(-2.919959,10.711088),(-2.922323,10.721207),(-2.919274,10.727202),(-2.908577,10.737666),(-2.9031,10.747149),(-2.899482,10.76999),(-2.882662,10.797068),(-2.871629,10.843448),(-2.864239,10.864273),(-2.850803,10.879544),(-2.834861,10.89161),(-2.821399,10.90626),(-2.815767,10.929153),(-2.821761,10.948299),(-2.832716,10.966024),(-2.838711,10.985119),(-2.835946,10.992224),(-2.837341,10.998012),(-2.751119,10.996462),(-2.750706,10.985842),(-2.728798,10.986057),(-2.634951,10.986979),(-2.439769,10.988943),(-2.197871,10.991294),(-1.972872,10.993516),(-1.754074,10.995635),(-1.598683,10.997133),(-1.587004,11.003671),(-1.579821,11.021215),(-1.562406,11.026589),(-1.436057,11.022713),(-1.423584,11.017911),(-1.413553,11.01405),(-1.38035,11.001268),(-1.355287,10.99672),(-1.22806,10.99548),(-1.10755,10.994343),(-1.098714,11.009562),(-1.070343,11.013902),(-0.932471,11.003102),(-0.924047,11.001423),(-0.916451,10.996203),(-0.909475,10.98269),(-0.904359,10.979486),(-0.89392,10.979899),(-0.900586,10.966231),(-0.883171,10.968634),(-0.860795,10.992922),(-0.839401,10.996462),(-0.833665,11.003412),(-0.827774,11.005841),(-0.822141,11.003619),(-0.816974,10.996462),(-0.816974,10.996203),(-0.703017,10.994159),(-0.695999,10.994033),(-0.694656,10.982742),(-0.690212,10.981811),(-0.683235,10.984344),(-0.673933,10.983517),(-0.667991,10.976515),(-0.67228,10.968505),(-0.679773,10.960572),(-0.68277,10.953596),(-0.634763,10.907966),(-0.617244,10.918637),(-0.607116,10.94122),(-0.599829,10.965766),(-0.590579,10.982432),(-0.576213,10.987754),(-0.555439,10.98995),(-0.516475,10.988633),(-0.512961,10.989744),(-0.509706,10.991449),(-0.506709,10.993671),(-0.504228,10.996203),(-0.504228,10.996358),(-0.494823,11.007805),(-0.46852,11.020129),(-0.456686,11.029612),(-0.45126,11.040206),(-0.449038,11.062892),(-0.444387,11.077439),(-0.425215,11.101468),(-0.405888,11.101468),(-0.386923,11.086405),(-0.368939,11.065217),(-0.318813,11.101365),(-0.306126,11.113535),(-0.298297,11.128392),(-0.300545,11.137409),(-0.304473,11.146788),(-0.301682,11.162937),(-0.166109,11.13498)] +Gibraltar [(-5.358387,36.141109),(-5.338773,36.14112),(-5.339915,36.129828),(-5.33906,36.123847),(-5.34203,36.1105),(-5.35025,36.119289),(-5.358387,36.141109)] +Guinea [(-13.338613,12.63923),(-13.332773,12.639643),(-13.330034,12.642072),(-13.327709,12.644914),(-13.322877,12.646516),(-13.292931,12.652717),(-13.284146,12.653337),(-13.275722,12.651064),(-13.263398,12.643209),(-13.25469,12.641813),(-13.246008,12.643157),(-13.229084,12.647808),(-13.22154,12.648376),(-13.21601,12.645741),(-13.20645,12.635664),(-13.201903,12.63339),(-13.197872,12.634062),(-13.185211,12.637783),(-13.176271,12.637731),(-13.169217,12.638765),(-13.162629,12.638144),(-13.154696,12.632822),(-13.145317,12.643932),(-13.127308,12.634837),(-13.108988,12.635406),(-13.091703,12.638196),(-13.076458,12.635922),(-13.063642,12.62228),(-13.059327,12.60347),(-13.060413,12.583367),(-13.064211,12.566159),(-13.079094,12.532156),(-13.082711,12.515671),(-13.078267,12.496241),(-13.066743,12.480118),(-13.051989,12.472263),(-13.034626,12.470558),(-13.015247,12.472676),(-12.997419,12.465855),(-12.981038,12.466992),(-12.969514,12.476811),(-12.966232,12.496086),(-12.949489,12.535928),(-12.913135,12.536342),(-12.874042,12.516395),(-12.849211,12.495001),(-12.84965,12.491073),(-12.851252,12.484355),(-12.849133,12.475829),(-12.838617,12.466372),(-12.829057,12.462755),(-12.799421,12.460636),(-12.783479,12.453091),(-12.779164,12.443273),(-12.773272,12.435056),(-12.752654,12.432421),(-12.688058,12.435986),(-12.667517,12.433661),(-12.648009,12.425754),(-12.63155,12.41268),(-12.603412,12.381933),(-12.598064,12.372424),(-12.597314,12.365448),(-12.593671,12.361572),(-12.579408,12.361159),(-12.57813,12.361528),(-12.570649,12.363691),(-12.541452,12.379452),(-12.521918,12.386894),(-12.505072,12.390253),(-12.48776,12.389477),(-12.466754,12.384465),(-12.423397,12.369117),(-12.405517,12.356456),(-12.377121,12.313668),(-12.36092,12.305607),(-12.192042,12.348756),(-12.155041,12.369014),(-12.121917,12.398728),(-12.103985,12.407357),(-12.07918,12.408133),(-12.018874,12.388444),(-11.997583,12.386377),(-11.984303,12.389012),(-11.946269,12.409425),(-11.93521,12.417021),(-11.930869,12.418726),(-11.923944,12.418778),(-11.921981,12.417693),(-11.920637,12.416039),(-11.860176,12.391079),(-11.839609,12.386687),(-11.757805,12.383328),(-11.720029,12.389477),(-11.643083,12.417641),(-11.601535,12.425238),(-11.515391,12.431645),(-11.481646,12.428235),(-11.416017,12.40498),(-11.388422,12.403895),(-11.388628,12.384465),(-11.407594,12.381933),(-11.431675,12.382966),(-11.447229,12.374543),(-11.451467,12.352115),(-11.444904,12.312531),(-11.444594,12.289484),(-11.463249,12.249951),(-11.491671,12.220909),(-11.507794,12.191608),(-11.489604,12.151197),(-11.470794,12.134609),(-11.409557,12.107893),(-11.391729,12.093733),(-11.351318,12.040403),(-11.334678,12.026192),(-11.315144,12.013325),(-11.294681,12.003093),(-11.274992,11.996271),(-11.25551,11.996168),(-11.223315,12.009294),(-11.206986,12.010172),(-11.191173,12.01441),(-11.176342,12.029499),(-11.165644,12.04862),(-11.159392,12.077507),(-11.152725,12.080866),(-11.14425,12.081331),(-11.136292,12.085103),(-11.122081,12.107272),(-11.117477,12.112702),(-11.116604,12.113732),(-11.084306,12.136573),(-11.072782,12.149492),(-11.059811,12.192435),(-11.052318,12.202512),(-11.038779,12.205251),(-11.015473,12.204424),(-10.972013,12.218583),(-10.952117,12.219462),(-10.927675,12.212951),(-10.909794,12.200135),(-10.869642,12.138433),(-10.846387,12.12138),(-10.822926,12.110476),(-10.804943,12.095955),(-10.798535,12.068102),(-10.801222,12.059213),(-10.811041,12.04154),(-10.812436,12.033427),(-10.807785,12.022833),(-10.781017,11.99622),(-10.740347,11.919894),(-10.711357,11.890386),(-10.669964,11.89204),(-10.655081,11.898965),(-10.645159,11.90837),(-10.634152,11.925423),(-10.625264,11.943872),(-10.621543,11.957669),(-10.613792,11.967694),(-10.595653,11.97989),(-10.574983,11.990329),(-10.55948,11.995186),(-10.566508,12.017252),(-10.555449,12.029344),(-10.535399,12.038698),(-10.51509,12.052909),(-10.514883,12.060144),(-10.517674,12.070737),(-10.517312,12.080349),(-10.507959,12.084586),(-10.504445,12.088359),(-10.512661,12.108461),(-10.511628,12.118073),(-10.493489,12.124429),(-10.445688,12.120708),(-10.435973,12.135178),(-10.428945,12.143394),(-10.39458,12.17161),(-10.381403,12.180136),(-10.37484,12.174814),(-10.368225,12.171506),(-10.353394,12.166494),(-10.354118,12.18086),(-10.348433,12.184787),(-10.339338,12.185459),(-10.329882,12.19042),(-10.325592,12.199773),(-10.323577,12.201995),(-10.316497,12.196879),(-10.313603,12.191143),(-10.31102,12.19104),(-10.304974,12.202874),(-10.26694,12.217808),(-10.258981,12.213778),(-10.254124,12.207215),(-10.247819,12.201065),(-10.21485,12.194606),(-10.179762,12.178224),(-10.160228,12.174503),(-10.135837,12.175485),(-10.128654,12.174503),(-10.118835,12.170163),(-10.105192,12.158639),(-10.097286,12.153678),(-10.09034,12.151584),(-10.087002,12.150577),(-10.070363,12.149854),(-10.060182,12.147528),(-10.04809,12.141379),(-10.027678,12.125669),(-10.015534,12.119881),(-9.996414,12.114145),(-9.961584,12.096007),(-9.941533,12.092751),(-9.923188,12.087584),(-9.888772,12.060557),(-9.870736,12.052082),(-9.861125,12.051875),(-9.840661,12.055028),(-9.833684,12.055131),(-9.823039,12.050893),(-9.806813,12.038439),(-9.796632,12.032342),(-9.778649,12.026657),(-9.722994,12.025417),(-9.698809,12.050997),(-9.686303,12.068153),(-9.681549,12.080814),(-9.683668,12.101485),(-9.682273,12.118538),(-9.675141,12.133989),(-9.66,12.149802),(-9.628167,12.170163),(-9.515616,12.20706),(-9.495876,12.224681),(-9.479598,12.235843),(-9.438877,12.254757),(-9.421513,12.257082),(-9.360173,12.246644),(-9.336816,12.269846),(-9.331906,12.282766),(-9.335007,12.306537),(-9.321829,12.310206),(-9.312889,12.32607),(-9.308497,12.345036),(-9.309169,12.357748),(-9.314801,12.362657),(-9.331648,12.366326),(-9.339167,12.370616),(-9.343947,12.380124),(-9.344464,12.389012),(-9.347151,12.396454),(-9.374694,12.41113),(-9.392781,12.428028),(-9.407251,12.445133),(-9.412573,12.455365),(-9.398155,12.473245),(-9.350872,12.484614),(-9.33418,12.496293),(-9.327307,12.497533),(-9.321519,12.496603),(-9.308187,12.488955),(-9.294079,12.483787),(-9.286379,12.488128),(-9.278938,12.494432),(-9.265864,12.495207),(-9.189486,12.479239),(-9.147318,12.465493),(-9.027765,12.404751),(-8.993839,12.387514),(-8.975907,12.368704),(-8.964745,12.346276),(-8.963092,12.32421),(-8.972135,12.301989),(-8.985261,12.282094),(-8.995906,12.26101),(-8.99756,12.23481),(-8.994278,12.224836),(-8.984537,12.20892),(-8.981178,12.198946),(-8.97384,12.187578),(-8.961696,12.187991),(-8.942008,12.195846),(-8.927021,12.187371),(-8.913896,12.169853),(-8.906041,12.147735),(-8.906971,12.125359),(-8.921957,12.086033),(-8.926298,12.064278),(-8.922112,12.045364),(-8.903715,12.030378),(-8.88165,12.029189),(-8.858757,12.031825),(-8.837983,12.028156),(-8.819793,12.012653),(-8.815452,11.995703),(-8.816434,11.976841),(-8.814909,11.955395),(-8.809974,11.94444),(-8.803205,11.934932),(-8.79783,11.925113),(-8.797004,11.913227),(-8.847233,11.657946),(-8.828526,11.659186),(-8.81168,11.651745),(-8.795195,11.641926),(-8.777211,11.635932),(-8.756541,11.638826),(-8.740366,11.646164),(-8.726517,11.649471),(-8.712874,11.640066),(-8.690705,11.568029),(-8.687346,11.55002),(-8.679026,11.52984),(-8.667967,11.510875),(-8.656754,11.496431),(-8.602183,11.472092),(-8.575208,11.470283),(-8.549577,11.490127),(-8.543996,11.477647),(-8.539425,11.456312),(-8.535521,11.438088),(-8.527563,11.423387),(-8.51578,11.418968),(-8.488134,11.418193),(-8.427724,11.40008),(-8.397648,11.385895),(-8.375324,11.367654),(-8.393359,11.363003),(-8.414133,11.353468),(-8.42607,11.340472),(-8.417957,11.325511),(-8.39956,11.322152),(-8.381267,11.325098),(-8.371035,11.32055),(-8.376719,11.294661),(-8.388398,11.281406),(-8.406691,11.275282),(-8.426897,11.274197),(-8.44457,11.276264),(-8.483224,11.28492),(-8.492578,11.277788),(-8.50312,11.255412),(-8.502345,11.25164),(-8.499244,11.246705),(-8.497022,11.24071),(-8.498779,11.233501),(-8.502138,11.231176),(-8.51206,11.230298),(-8.515625,11.229057),(-8.5241,11.22376),(-8.544616,11.214975),(-8.551799,11.210738),(-8.563943,11.193426),(-8.569679,11.157796),(-8.578154,11.14206),(-8.586991,11.137461),(-8.607222,11.137151),(-8.615413,11.13405),(-8.624611,11.122035),(-8.624921,11.112191),(-8.622389,11.102605),(-8.623112,11.091262),(-8.63368,11.071289),(-8.679801,11.025194),(-8.68869,11.012559),(-8.696906,10.996048),(-8.70073,10.978452),(-8.696234,10.962743),(-8.680938,10.952304),(-8.665229,10.956955),(-8.647969,10.965818),(-8.628228,10.967833),(-8.611382,10.965146),(-8.593347,10.964707),(-8.575622,10.966748),(-8.55955,10.971605),(-8.541567,10.983775),(-8.531645,10.999046),(-8.505755,11.052789),(-8.489064,11.052737),(-8.469013,11.046381),(-8.448704,11.047105),(-8.438162,11.04974),(-8.429067,11.048293),(-8.410464,11.041911),(-8.400645,11.043332),(-8.381318,11.053926),(-8.369329,11.054236),(-8.347315,11.043126),(-8.326593,11.02385),(-8.311142,11.000803),(-8.305096,10.978246),(-8.303649,10.874893),(-8.305871,10.856289),(-8.311814,10.847246),(-8.318893,10.83952),(-8.339822,10.783865),(-8.341941,10.763246),(-8.315586,10.753092),(-8.311142,10.735289),(-8.295535,10.537446),(-8.284425,10.511246),(-8.253884,10.469827),(-8.228873,10.423422),(-8.210579,10.414068),(-8.18903,10.413629),(-8.165983,10.418099),(-8.150583,10.424533),(-8.142056,10.429649),(-8.135442,10.427323),(-8.125417,10.411665),(-8.122109,10.399496),(-8.120921,10.373037),(-8.115495,10.360247),(-8.096116,10.346734),(-8.070071,10.341876),(-8.015708,10.339344),(-7.996277,10.32826),(-7.981549,10.307021),(-7.971214,10.281802),(-7.9646,10.258936),(-7.962584,10.233252),(-7.96801,10.209998),(-7.989663,10.161991),(-7.999843,10.150699),(-8.007233,10.138323),(-8.012349,10.124861),(-8.015708,10.110366),(-8.03488,10.085794),(-8.057876,10.073081),(-8.108777,10.054194),(-8.127535,10.037115),(-8.147741,10.010036),(-8.15849,9.984921),(-8.148878,9.973888),(-8.136269,9.969444),(-8.140093,9.959703),(-8.152392,9.949988),(-8.173837,9.941875),(-8.174716,9.933038),(-8.171512,9.922832),(-8.167895,9.914693),(-8.164536,9.912678),(-8.158955,9.912368),(-8.153219,9.910921),(-8.14955,9.90534),(-8.147224,9.887925),(-8.145674,9.882499),(-8.147327,9.880122),(-8.152133,9.87883),(-8.155079,9.875238),(-8.150996,9.866143),(-8.146862,9.864696),(-8.128104,9.866246),(-8.123505,9.844852),(-8.160293,9.584814),(-8.16159,9.575644),(-8.161022,9.553604),(-8.157611,9.530866),(-8.152857,9.513116),(-8.145364,9.497148),(-8.087176,9.415395),(-8.070433,9.397541),(-8.054051,9.389092),(-8.032296,9.384648),(-8.009868,9.383614),(-7.991575,9.38532),(-7.971059,9.392968),(-7.933025,9.414259),(-7.91189,9.418651),(-7.8706,9.418599),(-7.865381,9.409918),(-7.891736,9.330233),(-7.89494,9.307133),(-7.930648,9.220291),(-7.929563,9.183885),(-7.878713,9.163912),(-7.866311,9.166031),(-7.856234,9.170217),(-7.847914,9.168563),(-7.83422,9.142983),(-7.823368,9.131976),(-7.801044,9.114794),(-7.759392,9.091668),(-7.746783,9.07645),(-7.748203,9.075403),(-7.764198,9.063608),(-7.788073,9.060042),(-7.807813,9.060042),(-7.827037,9.05782),(-7.916747,9.012345),(-7.931785,8.996558),(-7.931837,8.996558),(-7.931837,8.996455),(-7.931888,8.996455),(-7.941604,8.972218),(-7.946461,8.948602),(-7.950699,8.899535),(-7.96894,8.812848),(-7.958915,8.781997),(-7.91313,8.768226),(-7.890961,8.765693),(-7.831016,8.747658),(-7.826572,8.748227),(-7.816056,8.753524),(-7.81019,8.753369),(-7.803679,8.749054),(-7.795695,8.73647),(-7.790915,8.730941),(-7.772053,8.714534),(-7.765129,8.706085),(-7.741202,8.662909),(-7.731823,8.652083),(-7.703944,8.633479),(-7.696812,8.624849),(-7.691593,8.606142),(-7.69397,8.567773),(-7.691696,8.546663),(-7.679242,8.505089),(-7.679294,8.487726),(-7.686477,8.462585),(-7.689578,8.438659),(-7.683221,8.417317),(-7.662447,8.374865),(-7.720738,8.368534),(-7.748334,8.372307),(-7.77102,8.386518),(-7.802439,8.449201),(-7.823833,8.477856),(-7.845744,8.474316),(-7.849413,8.459201),(-7.846777,8.44269),(-7.848586,8.428634),(-7.865588,8.420882),(-7.882331,8.421451),(-7.898583,8.426283),(-7.912871,8.434189),(-7.923827,8.443775),(-7.931578,8.45703),(-7.936953,8.471422),(-7.943877,8.484625),(-7.95628,8.494366),(-7.970542,8.49695),(-7.98589,8.494935),(-8.015708,8.487209),(-8.024906,8.488604),(-8.042476,8.487157),(-8.050667,8.487674),(-8.057204,8.490852),(-8.068107,8.500464),(-8.076634,8.503255),(-8.096891,8.501704),(-8.130119,8.488604),(-8.150531,8.486486),(-8.186343,8.493695),(-8.200296,8.491834),(-8.248872,8.453568),(-8.254401,8.446514),(-8.254298,8.434499),(-8.249078,8.423776),(-8.242102,8.412769),(-8.236883,8.400083),(-8.235281,8.379515),(-8.247631,8.322568),(-8.247631,8.303835),(-8.245306,8.285077),(-8.248252,8.273579),(-8.264581,8.2565),(-8.265977,8.245984),(-8.182932,8.191672),(-8.085522,8.162035),(-8.075962,8.163379),(-8.015708,8.183894),(-8.003305,8.184049),(-8.002427,8.174308),(-8.008266,8.160433),(-8.015708,8.14816),(-8.021702,8.117723),(-8.021289,8.102659),(-8.015708,8.088474),(-7.997052,8.077338),(-7.980413,8.058992),(-7.968217,8.03703),(-7.965638,8.026927),(-7.962636,8.015171),(-7.980361,8.016566),(-7.992505,8.024162),(-8.002168,8.032431),(-8.011987,8.035557),(-8.053845,8.028762),(-8.069089,8.029278),(-8.067229,8.020752),(-8.068883,7.996567),(-8.079115,7.957655),(-8.128879,7.882569),(-8.131204,7.842416),(-8.123763,7.83203),(-8.101439,7.812806),(-8.096323,7.801902),(-8.098261,7.791877),(-8.103919,7.786348),(-8.110482,7.78242),(-8.115133,7.776891),(-8.119009,7.760819),(-8.122626,7.727488),(-8.12738,7.713019),(-8.159523,7.676328),(-8.160195,7.672194),(-8.157404,7.662376),(-8.158024,7.658242),(-8.162107,7.654159),(-8.173424,7.647803),(-8.177868,7.643876),(-8.197867,7.618554),(-8.202621,7.607185),(-8.203035,7.599589),(-8.199779,7.583363),(-8.200244,7.576335),(-8.228976,7.544295),(-8.265356,7.560056),(-8.303235,7.589305),(-8.336773,7.597832),(-8.372275,7.58729),(-8.390878,7.585791),(-8.414805,7.612921),(-8.440023,7.599899),(-8.485446,7.557989),(-8.515625,7.577161),(-8.54782,7.600777),(-8.566527,7.623412),(-8.57278,7.650749),(-8.567405,7.688214),(-8.686571,7.694364),(-8.694477,7.674416),(-8.720677,7.642739),(-8.727576,7.622017),(-8.730031,7.587445),(-8.731478,7.581761),(-8.737369,7.571425),(-8.739178,7.565689),(-8.738041,7.559488),(-8.73401,7.557679),(-8.729514,7.556387),(-8.726827,7.55184),(-8.725742,7.528534),(-8.729617,7.50869),(-8.739539,7.490552),(-8.756489,7.472413),(-8.784394,7.455722),(-8.790389,7.450812),(-8.793955,7.441511),(-8.795453,7.421099),(-8.799226,7.41221),(-8.807701,7.40451),(-8.82403,7.399808),(-8.83341,7.393865),(-8.851626,7.371489),(-8.860617,7.35764),(-8.865371,7.346891),(-8.863304,7.32989),(-8.855915,7.311855),(-8.851367,7.292889),(-8.857827,7.273046),(-8.868885,7.266638),(-8.91219,7.250153),(-8.925419,7.248603),(-8.944385,7.278678),(-8.9572,7.286481),(-8.962575,7.262969),(-8.973117,7.267671),(-8.977716,7.266224),(-8.981023,7.250566),(-8.985467,7.25005),(-9.007637,7.243487),(-9.015698,7.238887),(-9.032855,7.240283),(-9.046652,7.232738),(-9.059261,7.221369),(-9.073111,7.211344),(-9.086392,7.20721),(-9.100448,7.204833),(-9.106085,7.202975),(-9.113935,7.200388),(-9.125407,7.190208),(-9.116054,7.224676),(-9.11962,7.237957),(-9.139153,7.247879),(-9.146905,7.25408),(-9.147473,7.271392),(-9.15308,7.275474),(-9.17543,7.274596),(-9.181476,7.275681),(-9.206281,7.298367),(-9.219872,7.360999),(-9.234341,7.381308),(-9.249715,7.383065),(-9.283796,7.374073),(-9.299505,7.376605),(-9.3055,7.383478),(-9.312424,7.403322),(-9.319401,7.411952),(-9.327772,7.417068),(-9.335007,7.419652),(-9.349218,7.421564),(-9.365961,7.421099),(-9.375159,7.41929),(-9.379242,7.415828),(-9.381412,7.404975),(-9.386477,7.401668),(-9.392264,7.39986),(-9.407354,7.378052),(-9.418723,7.387767),(-9.438101,7.421564),(-9.449263,7.405079),(-9.478357,7.376915),(-9.486626,7.372833),(-9.487099,7.373204),(-9.490708,7.376037),(-9.479701,7.38539),(-9.4735,7.39557),(-9.470864,7.407353),(-9.470244,7.420995),(-9.466213,7.433449),(-9.456705,7.443061),(-9.436086,7.458564),(-9.4134,7.492257),(-9.404925,7.513599),(-9.408697,7.527449),(-9.390817,7.548223),(-9.38366,7.55954),(-9.378777,7.586256),(-9.372989,7.601346),(-9.364411,7.614265),(-9.353507,7.62243),(-9.374694,7.646925),(-9.376245,7.680566),(-9.366374,7.716171),(-9.355471,7.741906),(-9.380999,7.77441),(-9.389681,7.791464),(-9.415674,7.824433),(-9.43867,7.866239),(-9.448437,7.907839),(-9.446008,7.950058),(-9.433093,7.993468),(-9.431745,7.996567),(-9.424562,8.005817),(-9.42234,8.015791),(-9.424149,8.026178),(-9.429265,8.036901),(-9.440944,8.050569),(-9.451537,8.051758),(-9.462183,8.043464),(-9.474223,8.028813),(-9.472776,8.040363),(-9.461873,8.058424),(-9.459805,8.068785),(-9.478047,8.141287),(-9.478099,8.152785),(-9.481406,8.164697),(-9.491328,8.169968),(-9.515616,8.174877),(-9.530137,8.185496),(-9.531894,8.212316),(-9.525435,8.24079),(-9.515616,8.256603),(-9.51081,8.261047),(-9.509156,8.265595),(-9.510758,8.270065),(-9.515616,8.274406),(-9.521249,8.284405),(-9.525124,8.295438),(-9.530189,8.30598),(-9.539387,8.314584),(-9.528483,8.32572),(-9.522282,8.330681),(-9.515616,8.334376),(-9.511482,8.336133),(-9.499131,8.343471),(-9.504351,8.346158),(-9.511482,8.353781),(-9.529052,8.366312),(-9.579178,8.387293),(-9.592045,8.405095),(-9.600159,8.410883),(-9.607342,8.402925),(-9.612148,8.396336),(-9.619537,8.392719),(-9.628064,8.391634),(-9.636125,8.392564),(-9.653385,8.392099),(-9.668372,8.38874),(-9.67726,8.39153),(-9.675916,8.409643),(-9.666511,8.422381),(-9.653385,8.43145),(-9.645117,8.443413),(-9.650543,8.464807),(-9.663514,8.477856),(-9.683513,8.487054),(-9.703253,8.487261),(-9.7155,8.473334),(-9.717981,8.452689),(-9.718188,8.438272),(-9.722115,8.435636),(-9.735913,8.450493),(-9.7463,8.468063),(-9.750899,8.485866),(-9.757307,8.53271),(-9.763043,8.54997),(-9.773585,8.563018),(-9.790586,8.565396),(-9.790018,8.553071),(-9.794824,8.544544),(-9.802007,8.53718),(-9.808854,8.528473),(-9.808828,8.520463),(-9.805469,8.512789),(-9.806813,8.506252),(-9.831617,8.499017),(-9.849704,8.48969),(-9.858644,8.487054),(-9.863502,8.49354),(-9.868153,8.498087),(-9.872804,8.500361),(-9.886911,8.49664),(-9.891872,8.495917),(-9.911354,8.495658),(-9.928149,8.493436),(-9.944169,8.488346),(-9.961119,8.479561),(-10.000186,8.449305),(-10.04039,8.425663),(-10.061681,8.422174),(-10.075013,8.426644),(-10.079354,8.439951),(-10.069277,8.486873),(-10.076099,8.501498),(-10.091085,8.510102),(-10.147981,8.524287),(-10.164879,8.524649),(-10.181829,8.519584),(-10.215625,8.486589),(-10.23242,8.477055),(-10.240275,8.493746),(-10.260842,8.485917),(-10.271332,8.484109),(-10.282236,8.484625),(-10.293708,8.483075),(-10.302235,8.485866),(-10.310245,8.490361),(-10.337581,8.498552),(-10.344299,8.499069),(-10.374737,8.49478),(-10.389775,8.489095),(-10.402384,8.481008),(-10.414062,8.470182),(-10.423778,8.456565),(-10.447962,8.407627),(-10.46021,8.39215),(-10.519276,8.33479),(-10.554364,8.311845),(-10.572657,8.304585),(-10.583251,8.30691),(-10.61188,8.325255),(-10.626711,8.331508),(-10.659784,8.333265),(-10.688154,8.324067),(-10.707895,8.303138),(-10.715181,8.2696),(-10.735283,8.287299),(-10.725,8.319855),(-10.702004,8.353574),(-10.683813,8.374865),(-10.669086,8.399075),(-10.654668,8.485504),(-10.643868,8.486873),(-10.641077,8.49478),(-10.64118,8.50664),(-10.638855,8.519895),(-10.631879,8.532013),(-10.616479,8.546508),(-10.600511,8.575653),(-10.584646,8.596841),(-10.565423,8.612783),(-10.545166,8.616762),(-10.522118,8.618571),(-10.503308,8.631567),(-10.489665,8.651049),(-10.481862,8.672469),(-10.524753,8.729546),(-10.530231,8.739158),(-10.545321,8.750036),(-10.5863,8.804089),(-10.589091,8.806595),(-10.596274,8.811246),(-10.599684,8.81538),(-10.600201,8.819024),(-10.599116,8.829617),(-10.599374,8.834036),(-10.608469,8.862303),(-10.610123,8.872302),(-10.61188,8.94514),(-10.607126,8.979841),(-10.591778,9.039062),(-10.592179,9.041658),(-10.593101,9.047617),(-10.594103,9.0541),(-10.605989,9.063763),(-10.629346,9.070352),(-10.669086,9.074434),(-10.710427,9.072987),(-10.746342,9.083814),(-10.753473,9.120116),(-10.74257,9.163292),(-10.724741,9.194504),(-10.714974,9.201352),(-10.703761,9.206313),(-10.693167,9.21285),(-10.685209,9.224503),(-10.683917,9.233753),(-10.687948,9.250703),(-10.688051,9.259281),(-10.683452,9.271812),(-10.677664,9.282897),(-10.67384,9.293982),(-10.675132,9.306461),(-10.717765,9.343333),(-10.728203,9.34819),(-10.741536,9.357053),(-10.753473,9.367569),(-10.765462,9.385216),(-10.774764,9.387335),(-10.785409,9.387232),(-10.795228,9.388524),(-10.801687,9.387283),(-10.819361,9.388059),(-10.831763,9.392141),(-10.822151,9.4009),(-10.811454,9.408264),(-10.813418,9.413897),(-10.829076,9.423948),(-10.843959,9.440252),(-10.854862,9.455264),(-10.8591,9.472989),(-10.853674,9.497871),(-10.852589,9.512082),(-10.860185,9.518542),(-10.870572,9.523399),(-10.877703,9.532675),(-10.882819,9.560167),(-10.886333,9.568409),(-10.896049,9.578305),(-10.92168,9.595901),(-10.92907,9.605694),(-10.935788,9.631894),(-10.940129,9.639697),(-10.94664,9.644839),(-10.962918,9.650782),(-10.968499,9.654244),(-10.974597,9.663778),(-10.986327,9.697755),(-11.010098,9.74274),(-11.044928,9.78713),(-11.085959,9.826171),(-11.16027,9.872758),(-11.16766,9.884462),(-11.181251,9.950376),(-11.188537,9.972597),(-11.199596,9.982157),(-11.213445,9.983371),(-11.247293,9.993396),(-11.272666,9.996006),(-11.484875,9.994845),(-11.910095,9.992518),(-11.914953,9.931488),(-11.921774,9.922212),(-12.109807,9.881676),(-12.141347,9.874876),(-12.158349,9.8756),(-12.174834,9.879191),(-12.193644,9.886064),(-12.217389,9.90056),(-12.235605,9.91676),(-12.253588,9.928413),(-12.276739,9.929266),(-12.426989,9.897614),(-12.472335,9.881258),(-12.508327,9.860381),(-12.514322,9.851312),(-12.514994,9.845111),(-12.513728,9.838341),(-12.513624,9.827825),(-12.527267,9.753618),(-12.526647,9.75062),(-12.522874,9.739432),(-12.522461,9.734472),(-12.525561,9.732069),(-12.530729,9.732844),(-12.53569,9.732792),(-12.537654,9.727934),(-12.537473,9.715713),(-12.538765,9.711915),(-12.54202,9.71132),(-12.573078,9.692562),(-12.582251,9.683364),(-12.59858,9.654864),(-12.601552,9.651712),(-12.602766,9.609363),(-12.606823,9.600707),(-12.614858,9.600087),(-12.624599,9.601276),(-12.633849,9.597865),(-12.638552,9.589416),(-12.647285,9.556627),(-12.649921,9.552105),(-12.652065,9.549444),(-12.655269,9.547739),(-12.660954,9.546033),(-12.668628,9.542364),(-12.669274,9.53823),(-12.66731,9.533709),(-12.667517,9.528696),(-12.701597,9.420227),(-12.706196,9.413948),(-12.713121,9.408161),(-12.716454,9.404414),(-12.719038,9.398368),(-12.72294,9.392089),(-12.727849,9.393123),(-12.732939,9.396508),(-12.737228,9.397231),(-12.754075,9.3878),(-12.759759,9.382839),(-12.767795,9.372323),(-12.767562,9.364391),(-12.763557,9.355347),(-12.764152,9.347673),(-12.777923,9.343849),(-12.795261,9.33509),(-12.819135,9.29579),(-12.835827,9.281967),(-12.856885,9.278505),(-12.876109,9.279848),(-12.895642,9.278505),(-12.917527,9.267007),(-12.937009,9.287083),(-12.957912,9.272433),(-12.973751,9.241582),(-12.97835,9.21285),(-12.973932,9.202799),(-12.960212,9.186081),(-12.959153,9.177839),(-12.962796,9.176702),(-12.97848,9.175203),(-12.984164,9.172309),(-12.993802,9.158693),(-13.002044,9.14412),(-13.015247,9.112752),(-13.028864,9.095983),(-13.047003,9.084537),(-13.085579,9.065985),(-13.115913,9.043945),(-13.131054,9.041465),(-13.153844,9.04932),(-13.191774,9.072987),(-13.207535,9.076708),(-13.233632,9.072057),(-13.277376,9.058595),(-13.301096,9.04149),(-13.312367,9.048326),(-13.321604,9.056627),(-13.325795,9.067776),(-13.322174,9.083075),(-13.319447,9.083564),(-13.304514,9.083075),(-13.300649,9.084621),(-13.300933,9.088202),(-13.302154,9.092515),(-13.301096,9.096137),(-13.273793,9.12401),(-13.254872,9.154934),(-13.243072,9.169745),(-13.225942,9.179267),(-13.208241,9.18008),(-13.176137,9.173651),(-13.157704,9.179267),(-13.157704,9.185492),(-13.218495,9.183254),(-13.247304,9.186021),(-13.259511,9.196357),(-13.25768,9.200263),(-13.248891,9.208319),(-13.245839,9.213446),(-13.245839,9.226467),(-13.237904,9.246649),(-13.232818,9.267401),(-13.254872,9.244818),(-13.264556,9.220445),(-13.270375,9.194037),(-13.280629,9.165025),(-13.304921,9.175482),(-13.315297,9.182074),(-13.322174,9.192939),(-13.313588,9.197943),(-13.311635,9.207221),(-13.314687,9.233303),(-13.313588,9.23314),(-13.311187,9.237982),(-13.308949,9.244778),(-13.307932,9.250312),(-13.310048,9.253811),(-13.319651,9.259263),(-13.322174,9.261217),(-13.325063,9.281317),(-13.325347,9.311021),(-13.318674,9.329495),(-13.301096,9.315863),(-13.303822,9.337795),(-13.303375,9.347113),(-13.301096,9.356838),(-13.307932,9.356838),(-13.313954,9.349555),(-13.322174,9.345404),(-13.332834,9.343573),(-13.345774,9.343166),(-13.352854,9.338772),(-13.357818,9.328437),(-13.367909,9.282172),(-13.374501,9.272773),(-13.397532,9.28384),(-13.407786,9.287014),(-13.411977,9.293402),(-13.404124,9.308417),(-13.414052,9.317206),(-13.423818,9.332913),(-13.430816,9.352037),(-13.431996,9.37108),(-13.42516,9.389879),(-13.40331,9.418158),(-13.396637,9.439358),(-13.404124,9.439358),(-13.428375,9.420722),(-13.465403,9.418158),(-13.499176,9.428778),(-13.513987,9.449612),(-13.520863,9.479478),(-13.520741,9.495103),(-13.510243,9.511054),(-13.50064,9.521796),(-13.493235,9.534857),(-13.488393,9.550605),(-13.486684,9.569078),(-13.49352,9.569078),(-13.515614,9.524482),(-13.529042,9.505683),(-13.547475,9.50019),(-13.561391,9.508979),(-13.575266,9.527248),(-13.58552,9.54914),(-13.58845,9.569078),(-13.619008,9.556383),(-13.643259,9.542548),(-13.677968,9.522691),(-13.7058,9.514472),(-13.707102,9.512152),(-13.714345,9.507636),(-13.722401,9.505805),(-13.726226,9.511054),(-13.72411,9.519517),(-13.718902,9.522284),(-13.71231,9.523668),(-13.7058,9.528062),(-13.673329,9.573798),(-13.652659,9.597154),(-13.640777,9.623725),(-13.625803,9.647284),(-13.623036,9.662909),(-13.624379,9.720282),(-13.623199,9.727362),(-13.61856,9.732082),(-13.604888,9.737372),(-13.602162,9.743801),(-13.595448,9.755032),(-13.580719,9.76203),(-13.566518,9.771064),(-13.561106,9.788235),(-13.581776,9.777167),(-13.594309,9.774237),(-13.604115,9.780178),(-13.647776,9.831488),(-13.651194,9.842841),(-13.655181,9.841742),(-13.658111,9.840522),(-13.664784,9.836615),(-13.653798,9.805243),(-13.650543,9.777004),(-13.661285,9.754543),(-13.692128,9.740383),(-13.728912,9.744086),(-13.747182,9.767768),(-13.749827,9.799872),(-13.739898,9.829169),(-13.698313,9.880764),(-13.681996,9.913479),(-13.685292,9.946479),(-13.693959,9.953803),(-13.697499,9.940416),(-13.699208,9.921332),(-13.702016,9.911689),(-13.712758,9.905178),(-13.732493,9.876776),(-13.746693,9.870754),(-13.745432,9.866523),(-13.749745,9.863471),(-13.784657,9.850246),(-13.788686,9.850043),(-13.809682,9.85163),(-13.827707,9.855373),(-13.842844,9.860785),(-13.849192,9.867621),(-13.855051,9.878852),(-13.86913,9.896226),(-13.886098,9.912177),(-13.900624,9.919135),(-13.927642,9.93594),(-13.933176,9.943345),(-13.945383,9.966946),(-13.954254,9.970933),(-13.971099,9.971829),(-13.979482,9.974351),(-13.98705,9.980414),(-14.006744,10.001044),(-14.021718,10.00727),(-14.032297,10.008979),(-14.042958,10.012844),(-14.058339,10.025295),(-14.061879,10.050116),(-14.046132,10.079495),(-14.020334,10.094428),(-13.993764,10.076158),(-14.001088,10.088202),(-14.014801,10.104804),(-14.028188,10.116604),(-14.034088,10.114),(-14.041615,10.101304),(-14.056752,10.106594),(-14.068349,10.118109),(-14.0655,10.124579),(-14.043813,10.133246),(-14.026967,10.153957),(-13.999908,10.199693),(-14.014516,10.192776),(-14.024892,10.183743),(-14.044667,10.162177),(-14.055491,10.155341),(-14.082834,10.14289),(-14.089345,10.138251),(-14.091176,10.126044),(-14.089345,10.079901),(-14.092275,10.06859),(-14.100575,10.058295),(-14.113433,10.051011),(-14.130279,10.048896),(-14.153188,10.05565),(-14.170481,10.070787),(-14.179799,10.090277),(-14.178782,10.110297),(-14.16275,10.126614),(-14.138173,10.144477),(-14.123647,10.162584),(-14.137766,10.179185),(-14.141672,10.164537),(-14.153147,10.156317),(-14.168609,10.152737),(-14.184926,10.151923),(-14.182485,10.129543),(-14.200185,10.112738),(-14.222401,10.106106),(-14.233388,10.114),(-14.236562,10.120917),(-14.24356,10.129381),(-14.2506,10.14053),(-14.253814,10.155341),(-14.250478,10.162584),(-14.244049,10.168891),(-14.240061,10.175116),(-14.243886,10.182318),(-14.249257,10.184272),(-14.25475,10.182847),(-14.259023,10.179592),(-14.26065,10.175767),(-14.270131,10.159735),(-14.292104,10.17178),(-14.352366,10.226223),(-14.362701,10.231187),(-14.376698,10.234442),(-14.391835,10.233385),(-14.405507,10.229397),(-14.418568,10.227973),(-14.431956,10.234442),(-14.452545,10.214586),(-14.462636,10.225165),(-14.465891,10.249701),(-14.466135,10.27204),(-14.458241,10.304267),(-14.458608,10.316962),(-14.463043,10.330024),(-14.468617,10.336249),(-14.475331,10.340318),(-14.537262,10.403632),(-14.548004,10.425605),(-14.550893,10.446601),(-14.550526,10.472113),(-14.545522,10.495022),(-14.535593,10.507473),(-14.535024,10.508205),(-14.53543,10.508165),(-14.551422,10.506781),(-14.562408,10.499335),(-14.571604,10.489447),(-14.582834,10.480862),(-14.596425,10.475979),(-14.613515,10.473375),(-14.628977,10.476264),(-14.637441,10.487738),(-14.644276,10.487738),(-14.651194,10.475084),(-14.657786,10.47956),(-14.662709,10.494127),(-14.664703,10.511623),(-14.663808,10.529202),(-14.661122,10.542629),(-14.650461,10.570258),(-14.639394,10.566636),(-14.625966,10.577379),(-14.611399,10.592963),(-14.596425,10.603746),(-14.620595,10.604315),(-14.628651,10.617255),(-14.627431,10.635484),(-14.615224,10.691311),(-14.607289,10.70539),(-14.596425,10.699368),(-14.59024,10.699368),(-14.588287,10.714301),(-14.580719,10.722073),(-14.572418,10.726304),(-14.568512,10.731024),(-14.555491,10.775702),(-14.531321,10.823472),(-14.517445,10.829047),(-14.509674,10.842475),(-14.508372,10.858466),(-14.513905,10.871894),(-14.509999,10.876451),(-14.500234,10.891099),(-14.519928,10.885403),(-14.522572,10.877631),(-14.519154,10.866523),(-14.521352,10.850816),(-14.554921,10.827623),(-14.558909,10.823472),(-14.573476,10.812405),(-14.590403,10.787258),(-14.60436,10.760443),(-14.615956,10.728013),(-14.629709,10.706448),(-14.657867,10.672675),(-14.686106,10.648179),(-14.699818,10.643134),(-14.705719,10.65526),(-14.703725,10.670844),(-14.69811,10.68183),(-14.689443,10.688951),(-14.678334,10.693101),(-14.68578,10.694729),(-14.691762,10.694485),(-14.697865,10.69184),(-14.705719,10.686347),(-14.71935,10.699368),(-14.706899,10.739203),(-14.699086,10.756252),(-14.688385,10.771959),(-14.6822,10.777777),(-14.66808,10.787095),(-14.661285,10.792792),(-14.655995,10.800605),(-14.65331,10.807603),(-14.651357,10.809963),(-14.656565,10.811957),(-14.664703,10.816636),(-14.677968,10.799628),(-14.723134,10.765123),(-14.734771,10.748114),(-14.746449,10.710761),(-14.760325,10.699368),(-14.770009,10.718817),(-14.782704,10.731269),(-14.792836,10.745022),(-14.795074,10.768256),(-14.781606,10.767768),(-14.770009,10.776923),(-14.760813,10.790432),(-14.75414,10.802965),(-14.749257,10.816107),(-14.746083,10.831204),(-14.744985,10.844062),(-14.746693,10.850816),(-14.743886,10.856594),(-14.742421,10.860989),(-14.740468,10.871894),(-14.758901,10.858466),(-14.765289,10.850328),(-14.76773,10.840888),(-14.772572,10.836493),(-14.801259,10.823472),(-14.808705,10.823472),(-14.809682,10.834784),(-14.809071,10.845608),(-14.806508,10.855455),(-14.801259,10.864447),(-14.807281,10.873603),(-14.807973,10.882473),(-14.803822,10.890815),(-14.795074,10.898586),(-14.813873,10.900336),(-14.819732,10.912014),(-14.816762,10.927191),(-14.808705,10.939602),(-14.796132,10.947577),(-14.778635,10.954088),(-14.759918,10.958441),(-14.74356,10.960028),(-14.73176,10.966457),(-14.724965,10.980536),(-14.720611,10.994574),(-14.716298,11.000963),(-14.699452,11.00552),(-14.680776,11.027493),(-14.664703,11.035793),(-14.672231,11.041449),(-14.677235,11.047593),(-14.68517,11.063666),(-14.687001,11.054267),(-14.690094,11.045233),(-14.694976,11.038479),(-14.70226,11.035793),(-14.707875,11.034491),(-14.723541,11.028266),(-14.726796,11.025824),(-14.730824,11.005845),(-14.741526,10.989081),(-14.756825,10.981187),(-14.774566,10.987982),(-14.779449,10.983303),(-14.784576,10.981106),(-14.791412,10.980373),(-14.801259,10.980536),(-14.795481,10.999701),(-14.801259,11.011908),(-14.810658,11.014472),(-14.815541,11.004706),(-14.843495,10.967475),(-14.874623,10.973293),(-14.894439,11.03026),(-14.918568,11.028957),(-14.901479,11.011664),(-14.898793,10.993232),(-14.904124,10.975491),(-14.911122,10.960028),(-14.931956,10.975653),(-14.943918,10.980048),(-14.959584,10.980536),(-14.926381,10.955552),(-14.914418,10.942328),(-14.911122,10.92593),(-14.920888,10.90766),(-14.939809,10.889106),(-14.958119,10.876207),(-14.96642,10.874986),(-14.968495,10.877875),(-14.973215,10.878852),(-14.977895,10.877875),(-14.980051,10.874986),(-14.978993,10.868842),(-14.974233,10.85928),(-14.973215,10.854193),(-14.973215,10.820054),(-14.968984,10.814358),(-14.959584,10.809963),(-14.950185,10.803778),(-14.945912,10.792792),(-14.947662,10.787584),(-14.959584,10.768256),(-14.977528,10.777045),(-15.013905,10.78262),(-15.031565,10.792792),(-15.052602,10.814399),(-15.069447,10.837144),(-15.079457,10.85871),(-15.081125,10.878241),(-15.07433,10.896877),(-15.058909,10.915961),(-15.051625,10.919623),(-15.03189,10.925482),(-15.027821,10.929348),(-15.026682,10.936672),(-15.02359,10.94359),(-15.019399,10.94953),(-15.014801,10.953803),(-15.014801,10.960028),(-15.019276,10.959703),(-15.020334,10.961371),(-15.020131,10.964179),(-15.020985,10.967475),(-14.992594,10.996203),(-14.992594,10.996358),(-14.959056,11.035762),(-14.863145,11.218645),(-14.843249,11.297193),(-14.828212,11.334787),(-14.728993,11.478009),(-14.711061,11.497568),(-14.686773,11.51072),(-14.64538,11.515061),(-14.562259,11.505604),(-14.520944,11.51289),(-14.432268,11.560575),(-14.339223,11.61061),(-14.326485,11.620584),(-14.319793,11.630506),(-14.308218,11.654535),(-14.300389,11.663165),(-14.289692,11.66885),(-14.284472,11.668178),(-14.278736,11.665077),(-14.19502,11.659703),(-14.171973,11.662752),(-14.161844,11.660943),(-14.153085,11.654845),(-14.144481,11.647404),(-14.134921,11.641771),(-14.118565,11.637999),(-14.104664,11.638567),(-14.07464,11.643735),(-14.058827,11.644045),(-14.015135,11.63712),(-13.996454,11.643838),(-13.953355,11.669676),(-13.945423,11.675671),(-13.923745,11.665026),(-13.903643,11.665387),(-13.886409,11.675568),(-13.873515,11.694533),(-13.870673,11.704145),(-13.868529,11.727037),(-13.87305,11.738354),(-13.870053,11.743677),(-13.855041,11.743419),(-13.846282,11.737269),(-13.842975,11.71727),(-13.834551,11.712103),(-13.820134,11.708072),(-13.819514,11.701664),(-13.821684,11.694223),(-13.815767,11.686833),(-13.795691,11.684042),(-13.770007,11.688693),(-13.745771,11.698202),(-13.729932,11.709829),(-13.724765,11.72311),(-13.719571,11.766105),(-13.719365,11.784036),(-13.734635,11.901859),(-13.731328,11.943406),(-13.722594,11.983869),(-13.723938,12.002783),(-13.734919,12.019267),(-13.744428,12.023918),(-13.779645,12.029344),(-13.795897,12.036269),(-13.807757,12.044279),(-13.829642,12.068102),(-13.835197,12.077765),(-13.837729,12.085413),(-13.842406,12.091304),(-13.869717,12.10071),(-13.879768,12.107686),(-13.899302,12.126238),(-13.918396,12.137762),(-13.938654,12.144273),(-13.964853,12.14789),(-13.972527,12.151559),(-13.968367,12.162566),(-13.968264,12.18396),(-13.965732,12.194244),(-13.943925,12.218635),(-13.883153,12.246437),(-13.858968,12.265971),(-13.840003,12.277133),(-13.812641,12.283592),(-13.795691,12.278735),(-13.808558,12.256101),(-13.740836,12.256927),(-13.71182,12.267521),(-13.695025,12.292946),(-13.69102,12.319301),(-13.68301,12.33868),(-13.682028,12.350307),(-13.685155,12.379194),(-13.684147,12.39201),(-13.682028,12.400329),(-13.664433,12.441516),(-13.660712,12.458672),(-13.663399,12.475777),(-13.67469,12.496086),(-13.725075,12.558149),(-13.734635,12.585331),(-13.736314,12.607604),(-13.728279,12.673388),(-13.404758,12.661761),(-13.359801,12.649737),(-13.356648,12.648893),(-13.352049,12.646981),(-13.343444,12.640987),(-13.338613,12.63923)] +Gambia [(-14.74093,13.615449),(-14.728579,13.619325),(-14.667188,13.652889),(-14.626674,13.663508),(-14.585539,13.660459),(-14.542596,13.640822),(-14.523243,13.625655),(-14.50973,13.609093),(-14.500221,13.589973),(-14.486863,13.546539),(-14.480378,13.533129),(-14.470275,13.522354),(-14.462135,13.516656),(-14.389582,13.465872),(-14.365553,13.454839),(-14.347285,13.452358),(-14.329947,13.456441),(-14.271217,13.476956),(-14.215794,13.510753),(-14.196829,13.518788),(-14.139132,13.531552),(-14.092882,13.554729),(-14.072599,13.55969),(-14.06185,13.560052),(-14.044461,13.558605),(-14.034022,13.560207),(-14.022266,13.565323),(-14.001905,13.577028),(-13.988495,13.579146),(-13.967489,13.575581),(-13.94209,13.566925),(-13.918086,13.554988),(-13.901343,13.541629),(-13.896175,13.532922),(-13.889793,13.513957),(-13.8846,13.505533),(-13.882504,13.503782),(-13.875479,13.497911),(-13.852793,13.484811),(-13.84269,13.476646),(-13.818713,13.429362),(-13.822562,13.378203),(-13.851036,13.33575),(-13.900568,13.314563),(-13.976119,13.308207),(-14.016272,13.297639),(-14.056579,13.297174),(-14.099496,13.281955),(-14.116808,13.282162),(-14.131794,13.275573),(-14.179827,13.240123),(-14.201687,13.229555),(-14.230625,13.228574),(-14.284911,13.238547),(-14.341781,13.233638),(-14.368834,13.235705),(-14.394982,13.242965),(-14.43144,13.26144),(-14.442034,13.268545),(-14.45149,13.276865),(-14.459139,13.286916),(-14.470326,13.298259),(-14.483633,13.301928),(-14.515104,13.303168),(-14.529574,13.307277),(-14.542854,13.314666),(-14.552109,13.323094),(-14.580733,13.34916),(-14.592154,13.35314),(-14.624555,13.345181),(-14.661607,13.340918),(-14.698142,13.345181),(-14.731577,13.359005),(-14.759482,13.38337),(-14.779636,13.410888),(-14.790333,13.417348),(-14.810797,13.421172),(-14.829142,13.427011),(-14.862576,13.447061),(-14.877614,13.451376),(-14.915907,13.454425),(-14.949703,13.463081),(-15.015074,13.495741),(-15.015229,13.495844),(-15.015435,13.495999),(-15.01559,13.496051),(-15.065251,13.531268),(-15.110158,13.57248),(-15.13765,13.589973),(-15.160491,13.580981),(-15.181331,13.559843),(-15.203951,13.536901),(-15.217955,13.51468),(-15.221728,13.452823),(-15.227774,13.425176),(-15.248341,13.398977),(-15.277073,13.380296),(-15.309836,13.368436),(-15.342392,13.36257),(-15.379237,13.362519),(-15.488326,13.385256),(-15.519539,13.3866),(-15.542948,13.377996),(-15.566048,13.365671),(-15.596123,13.355827),(-15.612453,13.354225),(-15.679891,13.360658),(-15.6925,13.360348),(-15.737407,13.346344),(-15.807118,13.339781),(-15.818694,13.333528),(-15.822673,13.319421),(-15.824367,13.248512),(-15.82474,13.232914),(-15.8266,13.161678),(-15.833318,13.156847),(-15.870784,13.157157),(-15.897441,13.157399),(-15.961734,13.157984),(-16.092062,13.15912),(-16.313289,13.161084),(-16.465218,13.162428),(-16.630014,13.1639),(-16.673525,13.164314),(-16.708407,13.156692),(-16.723186,13.132249),(-16.726339,13.122637),(-16.742152,13.107392),(-16.748508,13.099227),(-16.752125,13.088039),(-16.753651,13.065009),(-16.76887,13.077826),(-16.784332,13.082994),(-16.786733,13.090074),(-16.782541,13.098334),(-16.775502,13.112738),(-16.777333,13.127834),(-16.796742,13.177232),(-16.797475,13.189114),(-16.795033,13.235907),(-16.797353,13.248928),(-16.802968,13.262193),(-16.820058,13.281317),(-16.824452,13.294582),(-16.81664,13.310614),(-16.820302,13.315823),(-16.829701,13.338528),(-16.820709,13.349107),(-16.809967,13.379869),(-16.79955,13.386298),(-16.787343,13.389146),(-16.774322,13.396186),(-16.762929,13.404975),(-16.704457,13.475409),(-16.678822,13.496161),(-16.676747,13.485907),(-16.671132,13.478664),(-16.662506,13.473131),(-16.652252,13.468248),(-16.634633,13.477362),(-16.616851,13.478176),(-16.601389,13.472235),(-16.590728,13.461371),(-16.585317,13.443345),(-16.596303,13.440253),(-16.612782,13.439154),(-16.624257,13.427232),(-16.608713,13.413723),(-16.59553,13.385077),(-16.588368,13.355292),(-16.590728,13.338528),(-16.553863,13.295803),(-16.545766,13.290107),(-16.495188,13.287909),(-16.480824,13.283881),(-16.467763,13.275865),(-16.45995,13.268866),(-16.449696,13.264065),(-16.429351,13.262193),(-16.419667,13.255561),(-16.41393,13.239976),(-16.413482,13.222073),(-16.419423,13.208197),(-16.39977,13.224311),(-16.390859,13.224799),(-16.377797,13.215033),(-16.383656,13.225165),(-16.401926,13.243354),(-16.405751,13.246039),(-16.408274,13.258734),(-16.415273,13.267035),(-16.426015,13.270738),(-16.439931,13.269599),(-16.439931,13.276435),(-16.410512,13.275865),(-16.396799,13.277899),(-16.384633,13.283881),(-16.374745,13.263861),(-16.363271,13.268297),(-16.34968,13.282172),(-16.333404,13.290107),(-16.314809,13.295559),(-16.277943,13.319485),(-16.257965,13.324897),(-16.230133,13.316392),(-16.225901,13.296576),(-16.230214,13.273627),(-16.22761,13.256008),(-16.209706,13.251166),(-16.185455,13.258287),(-16.151275,13.276435),(-16.151275,13.283881),(-16.162262,13.282701),(-16.172515,13.279283),(-16.181752,13.273749),(-16.189809,13.265937),(-16.19929,13.259101),(-16.203521,13.26496),(-16.208079,13.292385),(-16.208608,13.303534),(-16.210764,13.3133),(-16.21703,13.317369),(-16.222035,13.31977),(-16.22525,13.325832),(-16.227122,13.333686),(-16.22761,13.341946),(-16.224436,13.360297),(-16.216217,13.372748),(-16.176178,13.405422),(-16.168691,13.413316),(-16.165517,13.423814),(-16.161204,13.428697),(-16.151438,13.426947),(-16.135121,13.420478),(-15.994862,13.413031),(-15.941314,13.425442),(-15.922231,13.427232),(-15.911285,13.426703),(-15.905629,13.425767),(-15.900624,13.425523),(-15.891225,13.427232),(-15.883778,13.430406),(-15.878407,13.434801),(-15.874379,13.43887),(-15.871327,13.440904),(-15.849517,13.442206),(-15.785024,13.43476),(-15.764475,13.436916),(-15.706207,13.454576),(-15.696767,13.459866),(-15.678049,13.473049),(-15.668691,13.475735),(-15.658925,13.472398),(-15.644683,13.457913),(-15.634918,13.454576),(-15.620839,13.45482),(-15.610422,13.456448),(-15.600901,13.460435),(-15.589589,13.468248),(-15.580922,13.478176),(-15.565053,13.502509),(-15.555409,13.509223),(-15.543446,13.50967),(-15.530995,13.505845),(-15.519643,13.499661),(-15.510732,13.492743),(-15.500396,13.488186),(-15.489654,13.489936),(-15.47936,13.493964),(-15.470041,13.496161),(-15.45108,13.490912),(-15.438873,13.478583),(-15.429433,13.464748),(-15.418853,13.454576),(-15.384429,13.443508),(-15.340566,13.440823),(-15.304799,13.455308),(-15.294749,13.496161),(-15.299957,13.496161),(-15.30191,13.496161),(-15.302154,13.496161),(-15.304067,13.481147),(-15.311391,13.467841),(-15.321848,13.458238),(-15.332875,13.454576),(-15.351674,13.456732),(-15.385976,13.466132),(-15.401479,13.468248),(-15.415761,13.473212),(-15.43224,13.484768),(-15.456451,13.50609),(-15.46524,13.510159),(-15.47411,13.508531),(-15.482818,13.505032),(-15.490834,13.502997),(-15.499867,13.505113),(-15.507558,13.509833),(-15.51358,13.514553),(-15.517893,13.516669),(-15.531728,13.519761),(-15.54304,13.525539),(-15.556142,13.528306),(-15.575836,13.522895),(-15.586008,13.515041),(-15.600697,13.49551),(-15.610666,13.489325),(-15.627756,13.488511),(-15.654652,13.500963),(-15.672109,13.502997),(-15.690175,13.498969),(-15.734202,13.475735),(-15.769887,13.465074),(-16.09024,13.440497),(-16.121897,13.451606),(-16.141591,13.454576),(-16.16039,13.450588),(-16.178456,13.440985),(-16.206532,13.420478),(-16.248443,13.378974),(-16.257965,13.372016),(-16.265614,13.36872),(-16.27302,13.362616),(-16.280588,13.359768),(-16.289133,13.365871),(-16.289703,13.373236),(-16.286733,13.383612),(-16.284901,13.395331),(-16.289133,13.406806),(-16.30602,13.391669),(-16.308095,13.383368),(-16.302113,13.372016),(-16.312123,13.366929),(-16.316396,13.365871),(-16.316396,13.359036),(-16.311635,13.357611),(-16.306996,13.35456),(-16.302113,13.352769),(-16.321889,13.342841),(-16.355946,13.337958),(-16.390533,13.336859),(-16.411977,13.338528),(-16.489491,13.357123),(-16.52184,13.359036),(-16.515777,13.367865),(-16.503529,13.392564),(-16.501332,13.403062),(-16.503529,13.416938),(-16.513417,13.436754),(-16.515696,13.444322),(-16.519765,13.451321),(-16.538197,13.46483),(-16.544504,13.475898),(-16.554433,13.481838),(-16.556549,13.485582),(-16.556549,13.50609),(-16.548004,13.548082),(-16.549143,13.56387),(-16.554799,13.577053),(-16.561391,13.5869),(-16.561399,13.586914),(-16.498756,13.586665),(-16.436641,13.586459),(-16.374577,13.5862),(-16.312462,13.585994),(-16.250295,13.585735),(-16.188232,13.585528),(-16.126117,13.58527),(-16.085383,13.585168),(-16.064054,13.585115),(-16.001938,13.584908),(-15.939772,13.58465),(-15.877708,13.584443),(-15.815593,13.584185),(-15.753426,13.583978),(-15.691363,13.58372),(-15.629196,13.583513),(-15.567133,13.583255),(-15.518195,13.5831),(-15.502486,13.588267),(-15.50047,13.627981),(-15.49803,13.641522),(-15.496801,13.648341),(-15.488946,13.670329),(-15.478611,13.691258),(-15.467501,13.708286),(-15.43634,13.741178),(-15.394069,13.771512),(-15.347766,13.788643),(-15.304462,13.781873),(-15.295108,13.773191),(-15.27573,13.748051),(-15.267255,13.741798),(-15.245964,13.746733),(-15.17062,13.793784),(-15.097704,13.819984),(-15.07631,13.818951),(-15.016779,13.796885),(-14.915803,13.792441),(-14.879268,13.780581),(-14.860314,13.765595),(-14.843973,13.752676),(-14.831312,13.735623),(-14.822372,13.7172),(-14.802942,13.65232),(-14.796017,13.644698),(-14.754934,13.620384),(-14.74093,13.615449)] +Guatemala [(-89.160496,17.814314),(-89.156217,17.598243),(-89.150728,17.321032),(-89.149205,17.036271),(-89.166067,16.777009),(-89.184353,16.495872),(-89.19314,16.392626),(-89.208517,16.186132),(-89.234135,15.954945),(-89.236022,15.906493),(-89.236512,15.893915),(-89.228244,15.880841),(-89.225996,15.884044),(-89.216539,15.888644),(-89.204835,15.892416),(-89.195765,15.892933),(-89.177446,15.900271),(-89.100913,15.896809),(-89.072388,15.901511),(-89.040323,15.901718),(-88.951878,15.879652),(-88.913971,15.893948),(-88.900014,15.887844),(-88.8662,15.860338),(-88.831614,15.868638),(-88.787343,15.859076),(-88.753285,15.839789),(-88.749501,15.818793),(-88.726796,15.815172),(-88.625966,15.753892),(-88.638295,15.708808),(-88.63622,15.702094),(-88.609242,15.702094),(-88.598378,15.706122),(-88.595204,15.714667),(-88.596344,15.722154),(-88.598704,15.723212),(-88.598988,15.727362),(-88.602366,15.730902),(-88.60558,15.735541),(-88.605458,15.743069),(-88.600453,15.744574),(-88.591176,15.743557),(-88.582183,15.745022),(-88.578196,15.753892),(-88.57433,15.769965),(-88.5655,15.780951),(-88.55606,15.789496),(-88.550282,15.798285),(-88.549062,15.813666),(-88.556711,15.837348),(-88.557688,15.852932),(-88.550282,15.852932),(-88.550649,15.842475),(-88.550282,15.83926),(-88.544057,15.83926),(-88.532135,15.846829),(-88.503041,15.841376),(-88.48884,15.846747),(-88.511952,15.86758),(-88.52481,15.877021),(-88.543284,15.885159),(-88.551015,15.895168),(-88.557688,15.906562),(-88.564524,15.914984),(-88.607574,15.938422),(-88.619862,15.953274),(-88.605458,15.969631),(-88.590199,15.961005),(-88.561838,15.949042),(-88.550282,15.942328),(-88.52123,15.912746),(-88.500234,15.901068),(-88.447906,15.85871),(-88.344838,15.811957),(-88.311025,15.782416),(-88.300404,15.777818),(-88.256337,15.740383),(-88.221547,15.725898),(-88.220937,15.725653),(-88.220922,15.725647),(-88.23262,15.721419),(-88.235746,15.712427),(-88.23492,15.701575),(-88.241586,15.688242),(-88.247761,15.695684),(-88.264995,15.688604),(-88.279697,15.680749),(-88.295588,15.675013),(-88.316672,15.6746),(-88.322304,15.667262),(-88.352561,15.616903),(-88.398992,15.572797),(-88.467434,15.52074),(-88.50002,15.495954),(-88.50002,15.495903),(-88.587379,15.4303),(-88.674195,15.365058),(-88.760899,15.299962),(-88.847027,15.235299),(-88.973427,15.140395),(-89.008283,15.124401),(-89.109827,15.091457),(-89.140523,15.076394),(-89.14694,15.071284),(-89.160806,15.060245),(-89.172769,15.04221),(-89.188582,14.996088),(-89.1691,14.978415),(-89.169152,14.95206),(-89.181528,14.923664),(-89.189215,14.913059),(-89.198814,14.899815),(-89.223619,14.879015),(-89.231448,14.867311),(-89.23243,14.8485),(-89.227676,14.834574),(-89.218968,14.82168),(-89.198814,14.79809),(-89.189409,14.783001),(-89.170547,14.738791),(-89.159669,14.725123),(-89.150523,14.717294),(-89.146213,14.710858),(-89.144502,14.708302),(-89.142694,14.691275),(-89.145226,14.683446),(-89.155845,14.672258),(-89.159411,14.665979),(-89.155225,14.615595),(-89.155742,14.597844),(-89.160393,14.581282),(-89.172149,14.570404),(-89.183699,14.569525),(-89.208814,14.577949),(-89.221087,14.580093),(-89.238114,14.577949),(-89.245685,14.572988),(-89.250542,14.565184),(-89.259612,14.554255),(-89.290927,14.528003),(-89.304854,14.513353),(-89.314802,14.495964),(-89.323044,14.487463),(-89.345265,14.48196),(-89.355497,14.475448),(-89.361983,14.4624),(-89.363791,14.446561),(-89.361621,14.415478),(-89.390611,14.435993),(-89.391697,14.43372),(-89.396864,14.426046),(-89.398182,14.445373),(-89.408362,14.441523),(-89.4311,14.418708),(-89.446835,14.415529),(-89.458127,14.419586),(-89.469418,14.425374),(-89.485283,14.427389),(-89.496148,14.422897),(-89.503033,14.420051),(-89.527761,14.391061),(-89.541351,14.381526),(-89.544245,14.400052),(-89.555175,14.410827),(-89.569877,14.412015),(-89.584062,14.401809),(-89.590573,14.385971),(-89.586284,14.374679),(-89.578972,14.364783),(-89.576078,14.35313),(-89.582408,14.343363),(-89.592434,14.336387),(-89.598351,14.32799),(-89.592175,14.31383),(-89.571272,14.311143),(-89.564373,14.308146),(-89.558586,14.302823),(-89.555692,14.299025),(-89.549878,14.288276),(-89.548586,14.2836),(-89.546778,14.268329),(-89.544917,14.261818),(-89.54055,14.257606),(-89.527864,14.251457),(-89.52466,14.247374),(-89.524505,14.231768),(-89.530939,14.225567),(-89.638322,14.200556),(-89.664626,14.188851),(-89.689844,14.170015),(-89.709868,14.148724),(-89.752605,14.07524),(-89.755447,14.067075),(-89.754465,14.059401),(-89.74801,14.044895),(-89.747256,14.043201),(-89.747644,14.037646),(-89.762268,14.029997),(-89.776944,14.035785),(-89.802963,14.055474),(-89.821102,14.060073),(-89.835855,14.059091),(-89.880116,14.042684),(-89.890788,14.035889),(-89.912078,14.015192),(-90.008171,13.949692),(-90.022976,13.936954),(-90.031477,13.922924),(-90.038091,13.908377),(-90.047367,13.894295),(-90.05964,13.884709),(-90.08708,13.870472),(-90.099044,13.858509),(-90.106976,13.844066),(-90.112299,13.828253),(-90.114779,13.812),(-90.114314,13.796265),(-90.092982,13.728903),(-90.098328,13.731414),(-90.245553,13.790726),(-90.401159,13.858588),(-90.500209,13.8947),(-90.580413,13.913267),(-90.638019,13.922358),(-90.707278,13.928889),(-90.784615,13.921538),(-90.796247,13.918161),(-90.910333,13.911135),(-91.04374,13.913585),(-91.165761,13.926703),(-91.316461,13.955679),(-91.551869,14.057278),(-91.637115,14.104438),(-91.762558,14.180174),(-91.908193,14.28384),(-92.049591,14.408026),(-92.246234,14.546283),(-92.226097,14.549346),(-92.208062,14.570507),(-92.186074,14.629573),(-92.164731,14.66815),(-92.160804,14.683498),(-92.161734,14.702334),(-92.179382,14.751581),(-92.180105,14.75879),(-92.178813,14.773389),(-92.179382,14.781244),(-92.188658,14.805893),(-92.190828,14.814239),(-92.191655,14.835297),(-92.186797,14.84726),(-92.166023,14.870825),(-92.15468,14.900797),(-92.157574,14.963041),(-92.154215,14.995933),(-92.142356,15.007483),(-92.129876,15.010945),(-92.116982,15.012392),(-92.103831,15.01787),(-92.093599,15.02942),(-92.073807,15.073706),(-92.20336,15.237159),(-92.21093,15.253359),(-92.211292,15.272066),(-92.204651,15.289507),(-92.186177,15.320384),(-92.137446,15.401826),(-92.105931,15.454469),(-92.068536,15.516935),(-91.9896,15.648968),(-91.910561,15.78095),(-91.841676,15.896085),(-91.792971,15.977579),(-91.774471,16.00843),(-91.751888,16.046308),(-91.739848,16.060985),(-91.723776,16.068788),(-91.678405,16.068891),(-91.54048,16.069149),(-91.402607,16.069305),(-91.264786,16.069511),(-91.126914,16.06977),(-90.994798,16.069869),(-90.988989,16.069873),(-90.851116,16.070131),(-90.713295,16.070338),(-90.575474,16.070596),(-90.485738,16.0707),(-90.466153,16.072922),(-90.448195,16.07926),(-90.448144,16.079278),(-90.447841,16.079687),(-90.444165,16.084652),(-90.437421,16.098863),(-90.434475,16.107183),(-90.440211,16.104858),(-90.442743,16.104186),(-90.444526,16.103256),(-90.448144,16.099742),(-90.455585,16.099742),(-90.459487,16.116795),(-90.435302,16.136277),(-90.448144,16.148214),(-90.448144,16.154416),(-90.42613,16.163149),(-90.432718,16.173226),(-90.461812,16.189142),(-90.465584,16.208107),(-90.458505,16.22175),(-90.446232,16.230845),(-90.434475,16.236323),(-90.447989,16.24149),(-90.457833,16.249138),(-90.459435,16.25906),(-90.448144,16.271101),(-90.443725,16.266864),(-90.440625,16.265313),(-90.42768,16.263608),(-90.431426,16.268931),(-90.437524,16.280041),(-90.441297,16.285364),(-90.436749,16.284847),(-90.435509,16.286242),(-90.435509,16.288774),(-90.434475,16.291565),(-90.428558,16.287637),(-90.420238,16.285364),(-90.414063,16.287844),(-90.414011,16.298386),(-90.420187,16.296009),(-90.434734,16.301228),(-90.444888,16.30836),(-90.437886,16.31208),(-90.419463,16.317816),(-90.404684,16.331511),(-90.398793,16.347582),(-90.40719,16.36045),(-90.414011,16.36045),(-90.414011,16.353008),(-90.420807,16.353008),(-90.418223,16.367167),(-90.40874,16.372335),(-90.395124,16.371405),(-90.379853,16.367271),(-90.391377,16.385978),(-90.392695,16.391714),(-90.392902,16.40484),(-90.394917,16.419206),(-90.400601,16.420549),(-90.409464,16.416673),(-90.420807,16.415123),(-90.426698,16.417707),(-90.434114,16.42241),(-90.444371,16.426802),(-90.475842,16.430729),(-90.478426,16.436414),(-90.477082,16.444992),(-90.482302,16.456051),(-90.488219,16.46158),(-90.497753,16.46804),(-90.508915,16.471089),(-90.532893,16.459927),(-90.539068,16.468867),(-90.543719,16.490209),(-90.553409,16.490261),(-90.57935,16.482768),(-90.584724,16.480235),(-90.590616,16.483388),(-90.604672,16.486178),(-90.620743,16.486747),(-90.633094,16.483336),(-90.627874,16.492896),(-90.618986,16.500079),(-90.612061,16.507624),(-90.61263,16.518114),(-90.624154,16.524936),(-90.639502,16.525866),(-90.648183,16.529586),(-90.639967,16.544831),(-90.643532,16.561006),(-90.637021,16.577904),(-90.633765,16.592167),(-90.647356,16.600073),(-90.65025,16.593407),(-90.653609,16.5901),(-90.658828,16.588446),(-90.6672,16.586999),(-90.6672,16.5932),(-90.654023,16.61661),(-90.667717,16.652576),(-90.73531,16.746576),(-90.749779,16.757686),(-90.785591,16.774998),(-90.80037,16.786832),(-90.79696,16.798666),(-90.79696,16.805435),(-90.810602,16.812928),(-90.819956,16.805332),(-90.831738,16.805435),(-90.900623,16.826003),(-90.919071,16.836338),(-90.948165,16.864708),(-90.968887,16.874372),(-90.952764,16.890908),(-90.955193,16.898763),(-90.968835,16.901037),(-90.98625,16.901088),(-90.987956,16.896903),(-90.984287,16.887756),(-90.983253,16.878609),(-90.993072,16.874372),(-90.998343,16.877162),(-91.0109,16.890288),(-91.016688,16.894836),(-91.054928,16.908013),(-91.066866,16.918193),(-91.07131,16.938916),(-91.076943,16.949509),(-91.112238,16.990489),(-91.116113,16.999274),(-91.121229,17.018394),(-91.126552,17.024595),(-91.137146,17.026507),(-91.161227,17.023975),(-91.1712,17.028006),(-91.206754,17.065368),(-91.215952,17.079217),(-91.220241,17.089294),(-91.225357,17.107019),(-91.229595,17.113995),(-91.238793,17.119215),(-91.259205,17.124331),(-91.263133,17.130738),(-91.265148,17.146241),(-91.270832,17.164276),(-91.279514,17.180089),(-91.290418,17.189081),(-91.317755,17.190476),(-91.344523,17.186342),(-91.364884,17.189753),(-91.372945,17.213576),(-91.388345,17.221586),(-91.419247,17.227735),(-91.442502,17.237967),(-91.438264,17.253677),(-91.430771,17.254969),(-90.991986,17.25192),(-90.991444,17.526942),(-90.990901,17.801964),(-90.98284,17.810542),(-90.962221,17.81602),(-90.919123,17.81602),(-90.699239,17.815813),(-90.47946,17.815606),(-90.259654,17.815348),(-90.039771,17.815141),(-89.820017,17.814986),(-89.600159,17.814728),(-89.380302,17.814521),(-89.160496,17.814314)] +Guam [(144.886404,13.640204),(144.896658,13.617987),(144.914317,13.605414),(144.934418,13.59984),(144.951915,13.598578),(144.952159,13.586859),(144.937673,13.560533),(144.906993,13.516669),(144.871837,13.485175),(144.808279,13.445787),(144.783458,13.420478),(144.769379,13.379136),(144.760102,13.285631),(144.735606,13.249172),(144.718028,13.241848),(144.69752,13.241034),(144.680675,13.246772),(144.670421,13.264838),(144.656749,13.28205),(144.653575,13.287014),(144.647472,13.324897),(144.644298,13.33161),(144.639496,13.33747),(144.633637,13.342108),(144.626313,13.345364),(144.636567,13.355414),(144.643077,13.365709),(144.646495,13.378485),(144.647472,13.396226),(144.645518,13.404486),(144.640473,13.414781),(144.634776,13.423529),(144.624197,13.43122),(144.628673,13.438788),(144.636485,13.443101),(144.640636,13.437812),(144.65447,13.439154),(144.714854,13.473456),(144.72877,13.485582),(144.783458,13.516669),(144.794119,13.527086),(144.803233,13.53913),(144.811209,13.553616),(144.832205,13.620673),(144.838634,13.632758),(144.850434,13.643744),(144.86671,13.653022),(144.880626,13.65412),(144.886404,13.640204)] +Heard Island and McDonald Islands [(73.735118,-53.1124),(73.761892,-53.11891),(73.789073,-53.120538),(73.812185,-53.118504),(73.661632,-53.146661),(73.609548,-53.179864),(73.580821,-53.187595),(73.507335,-53.19256),(73.473399,-53.189223),(73.440196,-53.173272),(73.430431,-53.165297),(73.404145,-53.139337),(73.370942,-53.090509),(73.36378,-53.074802),(73.371267,-53.06463),(73.359711,-53.058852),(73.353282,-53.05169),(73.354177,-53.044203),(73.364431,-53.037286),(73.344737,-53.029229),(73.328868,-53.025079),(73.271007,-53.021742),(73.253673,-53.015069),(73.24171,-53.002211),(73.236013,-52.982029),(73.269379,-52.975274),(73.296886,-52.961602),(73.330903,-52.984796),(73.337169,-52.985772),(73.344574,-52.996515),(73.361095,-53.00921),(73.377452,-53.017022),(73.384939,-53.013116),(73.389171,-52.997817),(73.399587,-52.990981),(73.412934,-52.992852),(73.426524,-53.003188),(73.412852,-53.009373),(73.425629,-53.025323),(73.447032,-53.02809),(73.470225,-53.02158),(73.487966,-53.009373),(73.50766,-53.015313),(73.56422,-53.016778),(73.587576,-53.026788),(73.598481,-53.033868),(73.620942,-53.039646),(73.632579,-53.044122),(73.640147,-53.050714),(73.65561,-53.067966),(73.663341,-53.071466),(73.688975,-53.090265),(73.699474,-53.100844),(73.735118,-53.1124)] +Hungary [(20.981489,48.516859),(21.0065,48.518151),(21.035956,48.514637),(21.063861,48.506239),(21.084015,48.49301),(21.109336,48.489109),(21.186748,48.513707),(21.219924,48.518719),(21.238011,48.513448),(21.250413,48.506498),(21.261782,48.50319),(21.276561,48.50872),(21.28824,48.519934),(21.293925,48.530579),(21.302296,48.539907),(21.32183,48.54758),(21.338573,48.549854),(21.372679,48.550345),(21.424563,48.561275),(21.439135,48.558329),(21.472725,48.544997),(21.490812,48.540268),(21.49939,48.535075),(21.506005,48.526496),(21.5151,48.507118),(21.521818,48.50009),(21.537734,48.495232),(21.574631,48.495568),(21.591684,48.49301),(21.600366,48.481641),(21.613388,48.440352),(21.621553,48.429655),(21.67757,48.372346),(21.701238,48.353949),(21.727697,48.340901),(21.759012,48.333769),(21.789398,48.335526),(21.841178,48.353174),(21.884276,48.357463),(21.914765,48.36909),(21.929338,48.372914),(21.981531,48.374723),(21.999928,48.37896),(22.018015,48.379735),(22.077856,48.375808),(22.09646,48.379425),(22.113926,48.38865),(22.13284,48.404798),(22.156508,48.40206),(22.158263,48.402222),(22.158315,48.402227),(22.159298,48.402318),(22.16922,48.409527),(22.201983,48.418157),(22.236089,48.415289),(22.271849,48.403455),(22.256967,48.373224),(22.25676,48.357282),(22.284355,48.358393),(22.29128,48.357566),(22.298721,48.349143),(22.298721,48.339324),(22.296447,48.327801),(22.297378,48.314003),(22.308126,48.293694),(22.357116,48.243103),(22.363627,48.23871),(22.370861,48.237393),(22.378613,48.238865),(22.386468,48.243051),(22.390498,48.244343),(22.394529,48.244757),(22.398767,48.244343),(22.418404,48.238969),(22.434217,48.236747),(22.44972,48.237677),(22.469047,48.244136),(22.473284,48.244498),(22.477418,48.24393),(22.481449,48.242586),(22.55576,48.177164),(22.568886,48.156519),(22.583045,48.124816),(22.600098,48.101122),(22.605472,48.097039),(22.608056,48.096833),(22.621182,48.101768),(22.693219,48.101768),(22.711616,48.105824),(22.728566,48.113137),(22.745722,48.116289),(22.762052,48.109261),(22.765566,48.104533),(22.801429,48.090968),(22.830988,48.072442),(22.844321,48.061047),(22.85476,48.047301),(22.861581,48.028387),(22.857964,48.018026),(22.851349,48.008802),(22.849489,47.993144),(22.832435,47.978933),(22.840807,47.966789),(22.877601,47.946739),(22.861167,47.933819),(22.836053,47.902452),(22.819723,47.892323),(22.779622,47.882298),(22.763602,47.874753),(22.752854,47.86124),(22.753267,47.852687),(22.758331,47.846228),(22.760295,47.838916),(22.75182,47.827676),(22.745826,47.824989),(22.724225,47.82349),(22.703864,47.817186),(22.691669,47.8107),(22.666967,47.78879),(22.637719,47.771555),(22.601235,47.760936),(22.562994,47.757215),(22.528475,47.761039),(22.454371,47.787394),(22.423675,47.782563),(22.407345,47.743082),(22.395873,47.735692),(22.382644,47.732023),(22.368278,47.73117),(22.322079,47.735873),(22.309366,47.735046),(22.29159,47.730705),(22.27309,47.723755),(22.261721,47.715848),(22.23981,47.693472),(22.232162,47.688253),(22.215212,47.679933),(22.207874,47.673732),(22.204153,47.666291),(22.200743,47.647945),(22.197642,47.639315),(22.172837,47.615389),(22.16984,47.608775),(22.169117,47.601385),(22.167608,47.594862),(22.16736,47.593789),(22.162089,47.586244),(22.154177,47.582213),(22.148549,47.579345),(22.09956,47.570948),(22.037445,47.539322),(22.007886,47.517411),(21.988869,47.492942),(21.991453,47.461807),(22.000238,47.427184),(22.001582,47.393827),(21.981531,47.366102),(21.936986,47.357162),(21.919003,47.349669),(21.900813,47.335742),(21.862159,47.297424),(21.856061,47.285745),(21.844589,47.249934),(21.839318,47.240839),(21.827742,47.226007),(21.823608,47.214923),(21.823298,47.203321),(21.825675,47.194278),(21.825985,47.185054),(21.819887,47.172729),(21.811516,47.164693),(21.789398,47.150301),(21.77989,47.140741),(21.775446,47.131672),(21.770485,47.114025),(21.763767,47.105214),(21.74351,47.091597),(21.69421,47.069169),(21.671886,47.054726),(21.632819,47.022686),(21.63427,47.019422),(21.636643,47.014082),(21.645221,47.01124),(21.654833,47.009948),(21.661757,47.006072),(21.670749,46.994394),(21.671369,46.99336),(21.667545,46.992378),(21.648528,46.942976),(21.640053,46.935689),(21.594371,46.910006),(21.589927,46.908869),(21.588687,46.906182),(21.587137,46.8944),(21.588067,46.882204),(21.591477,46.871533),(21.591788,46.860707),(21.583416,46.847943),(21.573081,46.841767),(21.536597,46.835023),(21.51572,46.821588),(21.502904,46.80531),(21.48151,46.764976),(21.477066,46.760222),(21.473655,46.754873),(21.471381,46.749034),(21.470451,46.743014),(21.472622,46.740197),(21.475206,46.737846),(21.478203,46.735934),(21.505178,46.723247),(21.501767,46.703507),(21.483577,46.684852),(21.463527,46.677049),(21.436241,46.673741),(21.425493,46.662011),(21.423539,46.658231),(21.416811,46.645216),(21.396037,46.626354),(21.374436,46.618448),(21.337643,46.620411),(21.316249,46.616639),(21.300953,46.603926),(21.295268,46.585039),(21.291341,46.546721),(21.278938,46.528401),(21.261679,46.513338),(21.247623,46.497473),(21.245142,46.47688),(21.274391,46.438355),(21.280695,46.416393),(21.257544,46.404171),(21.21517,46.402905),(21.195636,46.398099),(21.17879,46.384457),(21.168661,46.362753),(21.164527,46.318259),(21.155949,46.298932),(21.144476,46.283739),(21.134865,46.27852),(21.105616,46.278675),(21.099208,46.27635),(21.051459,46.236094),(21.033475,46.231339),(21.013942,46.24307),(21.007017,46.248858),(20.999162,46.251597),(20.990584,46.251597),(20.981489,46.248858),(20.961748,46.248341),(20.924438,46.259555),(20.906558,46.26219),(20.899737,46.260692),(20.885061,46.255007),(20.875139,46.254387),(20.866974,46.257126),(20.848991,46.267771),(20.839689,46.271079),(20.819638,46.271699),(20.798658,46.267616),(20.787369,46.26339),(20.778504,46.260072),(20.739333,46.237489),(20.734992,46.231908),(20.735509,46.222503),(20.744811,46.200282),(20.744707,46.192272),(20.736646,46.186691),(20.727137,46.187725),(20.717836,46.189998),(20.710291,46.188086),(20.70533,46.180645),(20.704368,46.168526),(20.704193,46.16633),(20.698819,46.15646),(20.683523,46.144678),(20.663989,46.137753),(20.607558,46.129485),(20.600117,46.12964),(20.588025,46.132844),(20.578103,46.137547),(20.548957,46.15615),(20.509373,46.167674),(20.468549,46.174134),(20.444157,46.1469),(20.283237,46.1438),(20.242826,46.108091),(20.188462,46.140389),(20.170479,46.145505),(20.145364,46.137082),(20.138026,46.136461),(20.130378,46.139355),(20.120146,46.149226),(20.114772,46.152223),(20.098442,46.154962),(20.088623,46.154135),(20.063405,46.145298),(20.034983,46.142973),(19.993125,46.159406),(19.92915,46.16354),(19.888946,46.15739),(19.873649,46.152992),(19.79045,46.129072),(19.772984,46.131552),(19.711889,46.15871),(19.690095,46.168398),(19.669321,46.1731),(19.647824,46.173875),(19.589739,46.165969),(19.568449,46.166434),(19.549948,46.16416),(19.525247,46.156409),(19.501993,46.145608),(19.487523,46.134239),(19.48928,46.126023),(19.496722,46.116876),(19.499305,46.108608),(19.47295,46.098686),(19.465922,46.091968),(19.460858,46.084475),(19.453727,46.07755),(19.43688,46.06799),(19.428302,46.06551),(19.417243,46.064321),(19.404738,46.060239),(19.396573,46.051557),(19.389131,46.041532),(19.378899,46.033677),(19.362156,46.029646),(19.325156,46.029491),(19.306966,46.026649),(19.298315,46.022123),(19.286915,46.016159),(19.279474,46.003808),(19.274823,45.991612),(19.263454,45.981432),(19.235652,45.977711),(19.148009,45.984068),(19.125788,45.993111),(19.125788,45.993266),(19.111009,46.012955),(19.088478,46.018846),(19.06543,46.012025),(19.049721,45.993111),(19.048584,45.963449),(19.03091,45.960038),(19.005589,45.96257),(18.981818,45.950788),(18.978717,45.947171),(18.977684,45.943502),(18.97882,45.939781),(18.986469,45.931254),(18.988742,45.927017),(18.987502,45.923813),(18.981818,45.921849),(18.962697,45.927947),(18.901306,45.931203),(18.886526,45.930428),(18.876604,45.922418),(18.865442,45.918077),(18.845392,45.913943),(18.828339,45.905726),(18.822451,45.905582),(18.817797,45.905468),(18.804878,45.913633),(18.794852,45.903039),(18.790408,45.893892),(18.785964,45.886916),(18.775525,45.882834),(18.76333,45.88397),(18.723849,45.89844),(18.674343,45.910377),(18.655636,45.907587),(18.633002,45.891929),(18.629281,45.886864),(18.626284,45.874824),(18.623597,45.868674),(18.62215,45.868416),(18.60737,45.856685),(18.585459,45.82692),(18.57347,45.816688),(18.530269,45.79085),(18.504224,45.784028),(18.481797,45.791418),(18.465467,45.783718),(18.43074,45.753642),(18.411723,45.743204),(18.404385,45.741809),(18.397564,45.741343),(18.390743,45.741809),(18.384128,45.7431),(18.383818,45.743204),(18.367178,45.75819),(18.351158,45.758397),(18.334932,45.751989),(18.317672,45.747286),(18.300516,45.751834),(18.283256,45.764908),(18.260518,45.765115),(18.229822,45.781238),(18.211219,45.785372),(18.12895,45.785372),(18.120165,45.783408),(18.102905,45.774623),(18.092053,45.771729),(18.080477,45.771729),(17.975367,45.792141),(17.906234,45.792141),(17.889791,45.792141),(17.88049,45.788524),(17.875735,45.780669),(17.870051,45.773486),(17.858062,45.771729),(17.857959,45.775863),(17.838218,45.799635),(17.809176,45.814414),(17.687323,45.840614),(17.664689,45.841647),(17.656524,45.84542),(17.654669,45.852113),(17.653217,45.857357),(17.65208,45.868829),(17.646912,45.883712),(17.645775,45.891825),(17.638437,45.901334),(17.591102,45.936215),(17.554308,45.947791),(17.511933,45.95394),(17.426667,45.956731),(17.418192,45.95301),(17.415402,45.949703),(17.411578,45.946602),(17.406203,45.943657),(17.399692,45.959935),(17.38915,45.963087),(17.365276,45.956731),(17.345328,45.955697),(17.342124,45.958643),(17.343675,45.967531),(17.337887,45.984636),(17.327138,45.972027),(17.316596,45.973784),(17.306613,45.979914),(17.304814,45.981019),(17.290138,45.984636),(17.290138,45.991457),(17.296959,45.992646),(17.309362,45.996625),(17.316803,45.997659),(17.307811,46.006392),(17.291482,46.007942),(17.275875,46.012025),(17.268951,46.028716),(17.266574,46.038793),(17.254068,46.070832),(17.24859,46.080238),(17.208593,46.116566),(17.197327,46.121165),(17.116195,46.123129),(17.101209,46.128193),(17.052943,46.153463),(17.041264,46.162196),(17.036303,46.172997),(17.028035,46.18049),(16.974808,46.210565),(16.9653,46.219454),(16.940702,46.251493),(16.903288,46.281931),(16.896054,46.286271),(16.889232,46.292163),(16.879312,46.312062),(16.871766,46.327199),(16.875073,46.342857),(16.865461,46.359135),(16.859411,46.364758),(16.850475,46.373062),(16.837659,46.381873),(16.832388,46.381925),(16.830218,46.377351),(16.827531,46.374018),(16.820916,46.3781),(16.816575,46.381976),(16.812338,46.385025),(16.807894,46.387351),(16.803449,46.388694),(16.776474,46.39288),(16.769343,46.39611),(16.761901,46.381873),(16.75508,46.381873),(16.742885,46.399624),(16.712395,46.412672),(16.693585,46.429622),(16.677462,46.44869),(16.659272,46.464193),(16.637671,46.474477),(16.61111,46.478069),(16.602118,46.482048),(16.594263,46.482978),(16.588062,46.479567),(16.583721,46.470653),(16.577623,46.470653),(16.564291,46.479929),(16.521089,46.498532),(16.515302,46.501711),(16.500832,46.544809),(16.467139,46.564704),(16.430242,46.604392),(16.394585,46.619016),(16.376395,46.629093),(16.372246,46.636341),(16.368437,46.642994),(16.377636,46.652864),(16.396652,46.659143),(16.402607,46.663109),(16.410502,46.668367),(16.405024,46.687255),(16.390038,46.694154),(16.371434,46.694929),(16.366216,46.696467),(16.365383,46.696712),(16.357585,46.699011),(16.357275,46.715832),(16.343426,46.714178),(16.334124,46.721749),(16.325546,46.733273),(16.314177,46.743324),(16.300431,46.772082),(16.298157,46.775802),(16.29949,46.77951),(16.302188,46.787016),(16.311097,46.797519),(16.3149,46.802002),(16.321825,46.813268),(16.327509,46.825463),(16.329783,46.834403),(16.325339,46.839442),(16.310663,46.84001),(16.301878,46.843214),(16.297392,46.847033),(16.282241,46.859932),(16.272009,46.863962),(16.179486,46.858468),(16.135376,46.855849),(16.130246,46.856708),(16.094035,46.862774),(16.110055,46.867916),(16.122871,46.876365),(16.159148,46.910316),(16.170723,46.918533),(16.196148,46.931297),(16.217025,46.937395),(16.22395,46.941064),(16.230668,46.94835),(16.231185,46.954422),(16.230358,46.959977),(16.232942,46.966075),(16.24307,46.972018),(16.252992,46.973516),(16.261054,46.97809),(16.265394,46.993257),(16.274903,47.004315),(16.288545,47.005582),(16.325856,47.00044),(16.366577,47.003825),(16.387764,47.002042),(16.405024,46.993153),(16.410398,46.990415),(16.415566,46.989433),(16.420424,46.99026),(16.424764,46.992998),(16.424764,46.993102),(16.441404,46.99522),(16.467449,46.995427),(16.486363,46.998554),(16.481919,47.00938),(16.467553,47.018423),(16.45329,47.021679),(16.424661,47.024082),(16.437167,47.031782),(16.481919,47.04421),(16.493184,47.049145),(16.497215,47.054622),(16.493701,47.059816),(16.481919,47.063898),(16.461765,47.068498),(16.454323,47.081701),(16.460835,47.0963),(16.481919,47.10524),(16.50476,47.125833),(16.509514,47.137537),(16.497318,47.149681),(16.480885,47.150767),(16.447089,47.139708),(16.433653,47.145754),(16.433963,47.151283),(16.442128,47.168336),(16.441818,47.177121),(16.4351,47.183581),(16.426728,47.184124),(16.41877,47.183659),(16.412776,47.187173),(16.409262,47.203683),(16.424661,47.225594),(16.421354,47.243035),(16.421354,47.243061),(16.421354,47.243138),(16.452463,47.254584),(16.466622,47.263421),(16.473237,47.276805),(16.469206,47.293238),(16.43882,47.336569),(16.436133,47.338559),(16.431689,47.339721),(16.427142,47.341375),(16.424351,47.345199),(16.424971,47.351116),(16.429312,47.353803),(16.434273,47.35556),(16.436443,47.358506),(16.433963,47.39685),(16.444091,47.40951),(16.456597,47.411836),(16.46993,47.405531),(16.481919,47.392302),(16.589406,47.425633),(16.626973,47.445549),(16.640875,47.452919),(16.636845,47.4932),(16.648213,47.501546),(16.677359,47.509866),(16.688004,47.52263),(16.689141,47.53803),(16.68139,47.550561),(16.66754,47.560096),(16.65059,47.566555),(16.656172,47.585934),(16.647697,47.606139),(16.63023,47.622004),(16.608422,47.628773),(16.575453,47.624949),(16.509617,47.64314),(16.481919,47.638954),(16.425901,47.654276),(16.407815,47.66133),(16.4166,47.668823),(16.431792,47.685463),(16.43913,47.690475),(16.444918,47.68554),(16.449879,47.682414),(16.45453,47.681768),(16.461145,47.684532),(16.47303,47.691767),(16.512924,47.706004),(16.521399,47.711533),(16.526877,47.720137),(16.52512,47.733315),(16.531115,47.742978),(16.567805,47.754192),(16.609766,47.750627),(16.689865,47.729568),(16.702474,47.7236),(16.707848,47.714608),(16.711569,47.704066),(16.719217,47.693731),(16.730379,47.685902),(16.741128,47.681458),(16.797455,47.675463),(16.80624,47.676884),(16.817299,47.684248),(16.836936,47.705358),(16.850165,47.712929),(16.864738,47.686729),(16.902668,47.682026),(16.98194,47.695436),(17.054804,47.702025),(17.075371,47.708484),(17.064002,47.71329),(17.055527,47.720913),(17.050566,47.730989),(17.048706,47.763649),(17.041988,47.783906),(17.040644,47.801114),(17.05563,47.812354),(17.049119,47.818684),(17.039507,47.837365),(17.031652,47.841345),(17.010672,47.847882),(17.004367,47.852377),(17.004057,47.863281),(17.016563,47.867699),(17.051186,47.872893),(17.067619,47.881626),(17.077541,47.891729),(17.083329,47.904829),(17.087463,47.922632),(17.085396,47.924621),(17.080125,47.925758),(17.075164,47.927773),(17.07413,47.932114),(17.076818,47.934956),(17.086119,47.93922),(17.088083,47.940899),(17.090874,47.949477),(17.095731,47.95573),(17.096145,47.961931),(17.085603,47.970148),(17.148338,48.005443),(17.184821,48.020274),(17.220892,48.015055),(17.262316,48.007283),(17.272671,48.00534),(17.337887,47.998725),(17.36941,47.981207),(17.472039,47.888809),(17.481858,47.882711),(17.492193,47.879818),(17.517308,47.876252),(17.526609,47.872118),(17.560406,47.837986),(17.572601,47.829536),(17.582937,47.829795),(17.592962,47.833102),(17.604227,47.834239),(17.61911,47.829226),(17.639884,47.819201),(17.658384,47.807316),(17.666239,47.797032),(17.676678,47.789177),(17.719245,47.773669),(17.741997,47.76538),(17.825713,47.750006),(17.883532,47.752521),(18.11262,47.762486),(18.23592,47.753882),(18.273024,47.756259),(18.347851,47.776775),(18.552593,47.792846),(18.597448,47.79065),(18.633829,47.779824),(18.663698,47.775896),(18.692843,47.777963),(18.717234,47.788118),(18.750307,47.81362),(18.767671,47.822302),(18.790305,47.826332),(18.814916,47.832194),(18.816453,47.83256),(18.778006,47.851447),(18.748757,47.870723),(18.742246,47.889455),(18.744726,47.910513),(18.754751,47.951803),(18.751444,47.963353),(18.744519,47.967357),(18.743176,47.971052),(18.756198,47.981827),(18.765293,47.985393),(18.784724,47.987615),(18.794232,47.993144),(18.821001,48.030454),(18.838467,48.040015),(18.933595,48.054349),(18.981818,48.061615),(18.996494,48.066214),(19.019017,48.065497),(19.038662,48.064871),(19.098503,48.070736),(19.222526,48.060582),(19.233482,48.06208),(19.29322,48.087764),(19.428199,48.085852),(19.481735,48.111328),(19.483286,48.116496),(19.483803,48.121767),(19.483286,48.127193),(19.481735,48.13267),(19.481425,48.133342),(19.481219,48.133962),(19.481425,48.134427),(19.481735,48.134892),(19.493621,48.150705),(19.503026,48.189411),(19.513982,48.203958),(19.531241,48.21065),(19.623226,48.227006),(19.633871,48.226773),(19.643896,48.224809),(19.655265,48.21835),(19.676969,48.200392),(19.686994,48.196904),(19.73309,48.202899),(19.756551,48.200315),(19.774327,48.185897),(19.774844,48.176079),(19.76916,48.167449),(19.766679,48.159),(19.776084,48.149517),(19.785593,48.14869),(19.821663,48.157914),(19.846261,48.152669),(19.884295,48.129621),(19.905069,48.124299),(19.928633,48.130087),(19.973902,48.158379),(19.99695,48.167914),(20.034983,48.175872),(20.038303,48.177233),(20.078082,48.193545),(20.096995,48.198429),(20.105263,48.202795),(20.112601,48.211735),(20.118079,48.229719),(20.122006,48.236747),(20.134512,48.246669),(20.14309,48.247805),(20.153322,48.245273),(20.170892,48.244033),(20.187636,48.248994),(20.217815,48.267598),(20.22908,48.270905),(20.249027,48.264187),(20.260293,48.255893),(20.272385,48.252456),(20.295226,48.260415),(20.324268,48.279948),(20.349279,48.305476),(20.370157,48.334338),(20.409017,48.413713),(20.420593,48.429241),(20.435579,48.442393),(20.465968,48.46379),(20.468239,48.465389),(20.481674,48.478747),(20.482501,48.482261),(20.482915,48.485827),(20.482811,48.489367),(20.482191,48.492881),(20.480227,48.510218),(20.480538,48.518538),(20.481674,48.526083),(20.51051,48.533783),(20.572522,48.536573),(20.784085,48.569052),(20.800311,48.569233),(20.815814,48.563807),(20.845477,48.545823),(20.859946,48.543317),(20.891365,48.541095),(20.945832,48.518978),(20.981489,48.516859)] +Isle of Man [(-4.612131,54.056952),(-4.620758,54.069648),(-4.631256,54.070624),(-4.643219,54.066596),(-4.656402,54.063788),(-4.67101,54.067043),(-4.689687,54.081529),(-4.704498,54.084866),(-4.725982,54.079006),(-4.745595,54.067369),(-4.766225,54.059231),(-4.790151,54.063788),(-4.790151,54.071234),(-4.78482,54.073065),(-4.781321,54.074774),(-4.777089,54.076239),(-4.769683,54.07746),(-4.770863,54.096829),(-4.737172,54.124905),(-4.728139,54.142564),(-4.727651,54.172593),(-4.723785,54.185452),(-4.714467,54.200344),(-4.71109,54.209906),(-4.71227,54.21662),(-4.710276,54.220649),(-4.68814,54.223782),(-4.663971,54.233547),(-4.643056,54.249416),(-4.612457,54.265448),(-4.598378,54.276597),(-4.554596,54.339179),(-4.530995,54.366116),(-4.495351,54.385891),(-4.442006,54.404364),(-4.404449,54.409654),(-4.385732,54.415717),(-4.367787,54.419013),(-4.351308,54.413804),(-4.357086,54.3994),(-4.377553,54.361884),(-4.3756,54.348334),(-4.370229,54.340888),(-4.363759,54.324286),(-4.358225,54.317613),(-4.350494,54.314765),(-4.332183,54.313422),(-4.324696,54.310207),(-4.319407,54.304592),(-4.313222,54.2956),(-4.31192,54.287177),(-4.320953,54.283515),(-4.326731,54.280341),(-4.34081,54.263007),(-4.348256,54.259508),(-4.35436,54.251532),(-4.359771,54.242255),(-4.365631,54.235053),(-4.371816,54.231269),(-4.399159,54.222073),(-4.390777,54.194729),(-4.412587,54.18008),(-4.446889,54.169135),(-4.475494,54.153144),(-4.474599,54.140815),(-4.529286,54.119086),(-4.543772,54.108466),(-4.549794,54.100653),(-4.563832,54.096829),(-4.579579,54.094428),(-4.590932,54.091051),(-4.598948,54.083889),(-4.612131,54.056952)] +Iraq [(42.89674,37.324906),(42.937048,37.320152),(42.979629,37.331831),(43.005158,37.347256),(43.043501,37.360253),(43.083706,37.368831),(43.114815,37.371131),(43.131971,37.367255),(43.263385,37.310695),(43.270309,37.30868),(43.278629,37.30775),(43.287518,37.309145),(43.296871,37.316741),(43.305656,37.319971),(43.324156,37.322219),(43.336145,37.32023),(43.362505,37.303908),(43.376039,37.295528),(43.41676,37.279173),(43.463269,37.248684),(43.479599,37.243361),(43.492415,37.244756),(43.517116,37.252301),(43.529518,37.253903),(43.542437,37.252301),(43.550602,37.248735),(43.568896,37.237702),(43.594217,37.22946),(43.618298,37.226979),(43.720824,37.232612),(43.746921,37.230648),(43.770641,37.225843),(43.780562,37.220365),(43.80206,37.20357),(43.809398,37.199694),(43.822007,37.202381),(43.83999,37.217109),(43.89363,37.224912),(43.924171,37.253076),(43.953782,37.287467),(43.990369,37.312504),(44.035586,37.31824),(44.069025,37.313727),(44.088037,37.31116),(44.184465,37.279173),(44.206893,37.26752),(44.223171,37.254058),(44.235005,37.236772),(44.243532,37.213828),(44.248544,37.191917),(44.249629,37.179437),(44.248337,37.16967),(44.240121,37.157966),(44.230199,37.154322),(44.218779,37.152617),(44.205963,37.146623),(44.18922,37.129208),(44.180641,37.108925),(44.180021,37.087608),(44.187463,37.066938),(44.22777,36.994125),(44.234281,36.983661),(44.243273,36.97777),(44.284821,36.969166),(44.297223,36.969941),(44.306628,36.977227),(44.315879,36.99397),(44.315982,36.99397),(44.316137,36.994022),(44.316137,36.994125),(44.33164,37.015468),(44.335154,37.031152),(44.343112,37.042443),(44.428068,37.064767),(44.454423,37.076343),(44.479228,37.092001),(44.503412,37.116624),(44.539379,37.143677),(44.57824,37.166415),(44.610279,37.178352),(44.628934,37.179024),(44.733786,37.167242),(44.753836,37.159154),(44.766135,37.14192),(44.752544,37.113136),(44.752699,37.103318),(44.760658,37.085644),(44.766549,37.078952),(44.773628,37.076343),(44.781121,37.074482),(44.788356,37.070245),(44.792232,37.063734),(44.797296,37.048489),(44.801895,37.043528),(44.811197,37.041926),(44.830938,37.046835),(44.840601,37.047197),(44.847577,37.044045),(44.858946,37.034123),(44.880754,37.024925),(44.887368,37.015933),(44.885715,37.005081),(44.874759,36.994022),(44.869178,36.967357),(44.874863,36.949658),(44.884061,36.933354),(44.888815,36.910926),(44.883441,36.886845),(44.869643,36.868965),(44.834141,36.834032),(44.823393,36.809331),(44.831248,36.791916),(44.851195,36.781219),(44.87724,36.776464),(44.908245,36.77786),(44.922715,36.775896),(44.935221,36.767111),(44.944419,36.758274),(44.954754,36.752331),(44.966433,36.749334),(44.979456,36.749024),(44.996199,36.741686),(45.010978,36.725563),(45.035266,36.689596),(45.045911,36.668047),(45.04431,36.64934),(45.024879,36.613167),(45.014182,36.579009),(45.013252,36.557925),(45.010255,36.556013),(44.997852,36.552085),(44.993408,36.549656),(44.991393,36.53374),(45.005914,36.518702),(45.009525,36.516196),(45.025344,36.505215),(45.03816,36.494001),(45.03909,36.479842),(45.045498,36.471625),(45.054076,36.464959),(45.062086,36.455347),(45.066892,36.442376),(45.068546,36.432506),(45.072266,36.423411),(45.083739,36.412817),(45.110817,36.402534),(45.139963,36.404394),(45.19598,36.422429),(45.221301,36.42093),(45.238871,36.402999),(45.24962,36.377936),(45.254478,36.354785),(45.25701,36.311687),(45.263934,36.294272),(45.282693,36.274893),(45.258508,36.262232),(45.264193,36.250192),(45.282796,36.238409),(45.297369,36.22673),(45.30202,36.207558),(45.299539,36.161411),(45.304604,36.140379),(45.33561,36.10772),(45.348322,36.087514),(45.344188,36.067464),(45.331889,36.051599),(45.31959,36.031032),(45.313699,36.010413),(45.32021,35.99429),(45.32021,35.994135),(45.32021,35.994083),(45.320313,35.994031),(45.32052,35.99398),(45.33809,35.979304),(45.359587,35.976875),(45.381808,35.982973),(45.401549,35.99398),(45.4016,35.994031),(45.401859,35.994031),(45.401962,35.994083),(45.402169,35.994238),(45.419946,35.998269),(45.453122,36.011653),(45.47927,36.012015),(45.501424,36.005435),(45.53999,35.99398),(45.576939,35.96623),(45.589858,35.959615),(45.617039,35.955429),(45.646857,35.933208),(45.69321,35.879878),(45.718739,35.828305),(45.731038,35.815128),(45.749021,35.810994),(45.786745,35.820244),(45.797907,35.818383),(45.814185,35.80934),(45.834752,35.810528),(45.854079,35.818332),(45.878315,35.83523),(45.888496,35.834868),(45.898779,35.832181),(45.909115,35.831302),(45.941257,35.840346),(46.004923,35.837969),(46.024973,35.843291),(46.0443,35.852283),(46.060423,35.857244),(46.07696,35.856986),(46.107759,35.847425),(46.115045,35.846444),(46.119851,35.842878),(46.124812,35.822466),(46.129101,35.815541),(46.135199,35.810012),(46.143364,35.804534),(46.163518,35.797506),(46.184963,35.798178),(46.227441,35.805723),(46.246407,35.811407),(46.263512,35.821122),(46.281392,35.828305),(46.302992,35.826548),(46.319632,35.816885),(46.327074,35.8035),(46.325058,35.787843),(46.313379,35.771513),(46.297515,35.759886),(46.267129,35.744124),(46.253486,35.727743),(46.23788,35.715547),(46.217003,35.713583),(46.177729,35.715392),(46.127603,35.693688),(46.107035,35.689812),(46.037065,35.691569),(46.016498,35.68573),(46.003786,35.674258),(45.995879,35.658393),(45.992365,35.640875),(45.992314,35.62439),(46.002029,35.585943),(45.999238,35.572145),(45.968698,35.579742),(45.963892,35.579742),(45.959344,35.578708),(45.968026,35.558503),(45.97924,35.539486),(45.983115,35.5353),(45.984562,35.531062),(45.983219,35.52698),(45.97924,35.523001),(45.971333,35.51804),(45.966062,35.511477),(45.963582,35.503415),(45.963995,35.494165),(45.977017,35.46533),(46.040993,35.381562),(46.096287,35.341151),(46.120161,35.318517),(46.127396,35.289062),(46.125285,35.284989),(46.120058,35.274902),(46.107655,35.262758),(46.098767,35.250046),(46.101454,35.234285),(46.115407,35.226326),(46.154164,35.226636),(46.169254,35.216249),(46.165481,35.189946),(46.143829,35.159612),(46.130393,35.131397),(46.151064,35.111605),(46.143106,35.099512),(46.132357,35.094758),(46.119954,35.092743),(46.09453,35.085818),(46.07665,35.089694),(46.066573,35.088815),(46.039753,35.075535),(46.025077,35.064269),(46.009212,35.06091),(45.97924,35.071555),(45.966372,35.070729),(45.956037,35.074243),(45.934953,35.085456),(45.920173,35.089642),(45.913197,35.087317),(45.899399,35.06861),(45.898366,35.063907),(45.901156,35.051608),(45.899089,35.046906),(45.893095,35.044374),(45.879039,35.043237),(45.872476,35.041428),(45.861882,35.032798),(45.857025,35.021274),(45.856818,35.008045),(45.859712,34.994403),(45.859712,34.994248),(45.868962,34.968358),(45.866327,34.949547),(45.857852,34.931306),(45.850203,34.906811),(45.835011,34.890171),(45.808036,34.897871),(45.796214,34.903043),(45.77827,34.910893),(45.755119,34.909963),(45.748504,34.89074),(45.750468,34.865367),(45.745404,34.840975),(45.717705,34.825111),(45.689231,34.82263),(45.676571,34.818289),(45.666752,34.80692),(45.6636,34.794932),(45.665925,34.774726),(45.662825,34.763254),(45.635023,34.736951),(45.627375,34.720828),(45.642258,34.706875),(45.650526,34.702999),(45.659517,34.697211),(45.666856,34.689977),(45.67037,34.681812),(45.67347,34.671166),(45.678379,34.66512),(45.683495,34.660211),(45.687629,34.653235),(45.690782,34.634321),(45.691247,34.615511),(45.694451,34.598561),(45.705613,34.58559),(45.708558,34.579079),(45.7083,34.568382),(45.705613,34.557737),(45.70153,34.551277),(45.695588,34.550244),(45.673573,34.556652),(45.604844,34.561147),(45.573941,34.567297),(45.539628,34.582231),(45.500664,34.591688),(45.49653,34.564248),(45.50485,34.523785),(45.503455,34.494175),(45.4987,34.486242),(45.493016,34.479008),(45.486505,34.472729),(45.47927,34.467251),(45.426767,34.45751),(45.417052,34.444359),(45.447954,34.36209),(45.46077,34.340463),(45.47927,34.329146),(45.499217,34.342401),(45.521541,34.342504),(45.542212,34.331601),(45.55756,34.311964),(45.563038,34.289278),(45.561022,34.264602),(45.54769,34.216491),(45.542729,34.207474),(45.528673,34.18856),(45.526657,34.17931),(45.531463,34.167916),(45.538801,34.159234),(45.544537,34.15063),(45.544537,34.139494),(45.534357,34.128202),(45.493946,34.100685),(45.47927,34.087636),(45.454879,34.06986),(45.443613,34.047664),(45.43519,34.022136),(45.419946,33.99436),(45.419946,33.994257),(45.419739,33.994257),(45.411471,33.987151),(45.401755,33.981622),(45.380361,33.97356),(45.401032,33.949453),(45.423718,33.938782),(45.449711,33.937387),(45.47927,33.941185),(45.481751,33.940875),(45.483921,33.940048),(45.485781,33.938653),(45.574768,33.803933),(45.588204,33.791504),(45.603604,33.78073),(45.616729,33.768689),(45.623912,33.752075),(45.628202,33.731844),(45.635126,33.714171),(45.645151,33.697918),(45.658794,33.681692),(45.673987,33.669031),(45.721116,33.640764),(45.72463,33.633036),(45.727989,33.625649),(45.72773,33.590096),(45.734552,33.583119),(45.752018,33.586762),(45.768451,33.595909),(45.797545,33.619319),(45.815787,33.625804),(45.864363,33.626424),(45.885964,33.63092),(45.882036,33.600198),(45.89971,33.58516),(45.920897,33.572991),(45.927925,33.550873),(45.915626,33.535809),(45.868187,33.511573),(45.852581,33.494365),(45.869737,33.482118),(45.899399,33.476304),(45.929682,33.479508),(45.948182,33.494262),(45.953143,33.496587),(45.958156,33.497388),(45.963272,33.496561),(45.964487,33.495991),(45.968232,33.494236),(45.971385,33.492763),(45.974434,33.490799),(46.008023,33.455659),(46.019392,33.438399),(46.027454,33.419512),(46.030503,33.399203),(46.031071,33.382511),(46.036239,33.367939),(46.069725,33.34086),(46.109516,33.293705),(46.141349,33.272105),(46.155301,33.260219),(46.164189,33.243347),(46.164396,33.233063),(46.15835,33.213865),(46.157678,33.205675),(46.162122,33.196373),(46.173698,33.190223),(46.174318,33.18118),(46.167187,33.168338),(46.153441,33.154256),(46.126466,33.131777),(46.105382,33.118393),(46.089155,33.11568),(46.072412,33.116765),(46.050398,33.115112),(46.030296,33.105681),(46.029314,33.093511),(46.043267,33.08346),(46.087192,33.079222),(46.106002,33.072504),(46.12042,33.061678),(46.126156,33.047984),(46.119489,33.031008),(46.104658,33.018063),(46.088018,33.00672),(46.075719,32.994499),(46.075719,32.994344),(46.09701,32.95432),(46.15556,32.948352),(46.273433,32.959488),(46.379629,32.931764),(46.479312,32.891792),(46.507321,32.868021),(46.600613,32.822541),(46.604421,32.820685),(46.650361,32.789369),(46.715887,32.756012),(46.757332,32.716195),(47.058398,32.494478),(47.058605,32.494478),(47.058657,32.4944),(47.090593,32.474556),(47.12103,32.461043),(47.152553,32.455178),(47.187796,32.458382),(47.20547,32.46404),(47.251255,32.48546),(47.265311,32.484685),(47.321948,32.468226),(47.343342,32.458692),(47.356106,32.446186),(47.36732,32.430761),(47.384115,32.41257),(47.410832,32.395285),(47.416413,32.387973),(47.417963,32.376423),(47.414346,32.36986),(47.408765,32.364331),(47.39998,32.345779),(47.395949,32.34198),(47.395794,32.33702),(47.40246,32.323506),(47.407059,32.31777),(47.436877,32.293689),(47.441579,32.288185),(47.445352,32.28263),(47.463025,32.26183),(47.469433,32.25612),(47.479148,32.252063),(47.484522,32.239351),(47.504004,32.226742),(47.509224,32.213797),(47.507673,32.199844),(47.502351,32.190129),(47.496408,32.181344),(47.492481,32.170492),(47.490413,32.15654),(47.491344,32.148633),(47.498165,32.144137),(47.513823,32.140313),(47.52669,32.133389),(47.534752,32.123157),(47.54364,32.114578),(47.55873,32.112976),(47.578057,32.106155),(47.580232,32.103495),(47.595007,32.085433),(47.617796,32.04187),(47.633144,32.026935),(47.668077,32.012414),(47.677947,31.994689),(47.677947,31.994534),(47.68265,31.976912),(47.71841,31.922342),(47.725231,31.914332),(47.743318,31.904255),(47.750966,31.898209),(47.756547,31.889166),(47.761715,31.871647),(47.76528,31.864103),(47.781352,31.848858),(47.820781,31.823588),(47.834475,31.805708),(47.837266,31.784469),(47.831323,31.761835),(47.678929,31.407851),(47.676443,31.236517),(47.672935,30.994698),(48.001545,30.994647),(48.012242,30.989066),(48.015446,30.97625),(48.012035,30.494574),(48.012035,30.494522),(48.013586,30.463878),(48.119419,30.450804),(48.130581,30.447497),(48.140916,30.441916),(48.15766,30.426309),(48.170475,30.406672),(48.179467,30.384865),(48.187684,30.340836),(48.192076,30.331276),(48.200086,30.323938),(48.211196,30.319649),(48.222979,30.318099),(48.235071,30.318512),(48.271658,30.323835),(48.284267,30.323318),(48.296359,30.319753),(48.305713,30.312828),(48.326021,30.283476),(48.358164,30.251798),(48.397025,30.220999),(48.403588,30.212524),(48.408704,30.202344),(48.410616,30.191543),(48.408032,30.180898),(48.400745,30.172268),(48.391134,30.164775),(48.383279,30.156455),(48.381108,30.145345),(48.383072,30.13842),(48.395578,30.115217),(48.415525,30.095632),(48.421209,30.085348),(48.423948,30.083643),(48.44219,30.03393),(48.444257,30.020908),(48.453145,30.001426),(48.457796,29.994863),(48.464307,29.989127),(48.478157,29.979618),(48.49304,29.971763),(48.523994,29.964115),(48.531025,29.961351),(48.531016,29.96133),(48.530772,29.960761),(48.530772,29.956204),(48.554942,29.956488),(48.559255,29.946601),(48.546886,29.934719),(48.520518,29.9289),(48.411876,29.938422),(48.33546,29.961412),(48.299571,29.984524),(48.264659,29.993964),(48.209239,30.024482),(48.165782,30.037543),(48.119151,30.044989),(48.076345,30.04564),(48.038259,30.036851),(47.969005,30.004055),(47.961925,30.030341),(47.958507,30.060614),(47.951671,30.088324),(47.934825,30.107082),(47.947113,30.07453),(47.948497,30.062323),(47.946056,30.049384),(47.941742,30.037258),(47.940929,30.026516),(47.948497,30.017646),(47.948009,29.994045),(47.731432,30.088552),(47.674175,30.098216),(47.415793,30.098216),(47.358225,30.092118),(47.197098,30.03424),(47.144698,30.003338),(47.110488,29.960911),(47.025429,29.772137),(46.988842,29.712658),(46.983674,29.698292),(46.97985,29.668061),(46.97737,29.657984),(46.957836,29.620441),(46.883112,29.512515),(46.85345,29.44456),(46.838567,29.424975),(46.774488,29.363532),(46.711856,29.271393),(46.561468,29.124167),(46.532436,29.095745),(46.488614,29.08758),(46.444896,29.079415),(46.427322,29.076143),(46.401178,29.071276),(46.357459,29.063137),(46.252143,29.071457),(46.17592,29.077477),(46.099697,29.083575),(46.02363,29.089595),(45.947355,29.095641),(45.844932,29.103754),(45.742406,29.111868),(45.63988,29.120032),(45.537406,29.12812),(45.434932,29.136207),(45.332406,29.144372),(45.229983,29.152459),(45.127457,29.160624),(45.047824,29.166903),(44.968293,29.173259),(44.888712,29.179512),(44.808923,29.185894),(44.717456,29.193103),(44.710893,29.195273),(44.70464,29.197495),(44.698232,29.199718),(44.691825,29.201836),(44.614878,29.256071),(44.519742,29.323328),(44.424296,29.390533),(44.328953,29.45779),(44.233661,29.524995),(44.119146,29.605817),(44.004631,29.686613),(43.890065,29.767383),(43.824013,29.81398),(43.775498,29.848205),(43.660983,29.929027),(43.546365,30.009797),(43.431746,30.090568),(43.317231,30.171338),(43.229071,30.233505),(43.140963,30.295671),(43.052907,30.357786),(42.964747,30.420005),(42.859017,30.494522),(42.858913,30.494574),(42.85881,30.494626),(42.858707,30.494677),(42.783413,30.551045),(42.763932,30.565629),(42.669157,30.636684),(42.574486,30.707636),(42.479712,30.778639),(42.395169,30.841581),(42.31073,30.904523),(42.22629,30.967465),(42.141644,31.030407),(42.075395,31.079861),(41.986202,31.125285),(41.898558,31.169985),(41.810708,31.214685),(41.723065,31.259385),(41.635422,31.304034),(41.547572,31.348734),(41.459825,31.393434),(41.372182,31.438134),(41.284539,31.482834),(41.196689,31.527586),(41.109046,31.572286),(41.021299,31.616934),(40.933553,31.661634),(40.845909,31.706335),(40.758163,31.751086),(40.670313,31.795683),(40.58267,31.840435),(40.479834,31.892835),(40.424126,31.920533),(40.37028,31.938465),(40.029318,31.994379),(40.029112,31.994431),(40.029008,31.994482),(40.028802,31.994482),(39.9486,32.00611),(39.750989,32.034893),(39.553275,32.063729),(39.355561,32.092564),(39.157744,32.121348),(39.154953,32.120573),(39.152163,32.119746),(39.149269,32.118919),(39.146375,32.118144),(39.146168,32.125844),(39.266471,32.212867),(39.291999,32.244519),(39.271122,32.311956),(39.256342,32.342678),(39.235775,32.352858),(39.046329,32.308494),(39.036201,32.313352),(39.028759,32.328338),(38.979977,32.472102),(38.978633,32.47373),(38.97822,32.47497),(38.978633,32.475693),(38.979977,32.476055),(39.057181,32.496596),(38.990002,32.705576),(38.94277,32.852337),(38.897191,32.994344),(38.862568,33.10072),(38.82102,33.229032),(38.774511,33.371685),(38.885099,33.427108),(38.995686,33.482479),(39.106274,33.537928),(39.216862,33.593325),(39.327449,33.648722),(39.438037,33.704094),(39.548624,33.759491),(39.659212,33.81481),(39.769696,33.870233),(39.880387,33.925605),(39.990871,33.980976),(40.101459,34.036373),(40.173111,34.072283),(40.212046,34.091796),(40.322634,34.147167),(40.433221,34.202539),(40.543809,34.257988),(40.690467,34.331497),(40.936033,34.386068),(40.965282,34.401855),(40.98802,34.42852),(41.023986,34.494175),(41.023986,34.49433),(41.195656,34.768473),(41.204234,34.793123),(41.206508,34.819323),(41.198033,34.994041),(41.192326,35.158904),(41.191521,35.182143),(41.20134,35.243018),(41.243095,35.366525),(41.25188,35.46409),(41.261078,35.494165),(41.261181,35.494165),(41.261285,35.494165),(41.261285,35.49432),(41.308458,35.552248),(41.34221,35.593694),(41.358023,35.623925),(41.363501,35.655241),(41.359263,35.792752),(41.354509,35.825566),(41.343657,35.857657),(41.266349,35.994238),(41.266349,35.994342),(41.266246,35.99429),(41.240614,36.043021),(41.236687,36.060332),(41.236583,36.077024),(41.268829,36.327965),(41.276994,36.354785),(41.365258,36.493898),(41.365258,36.494001),(41.365361,36.494053),(41.365361,36.494156),(41.385411,36.516377),(41.414867,36.527384),(41.479773,36.536117),(41.789935,36.589292),(41.817323,36.599731),(41.843781,36.617869),(41.978554,36.733625),(42.178438,36.90532),(42.281584,36.99397),(42.281894,36.99397),(42.281894,36.994022),(42.281894,36.994125),(42.34587,37.042908),(42.376806,37.062001),(42.377186,37.062235),(42.376875,37.076756),(42.371191,37.087944),(42.363646,37.09815),(42.357238,37.109984),(42.401887,37.114144),(42.459144,37.129311),(42.545237,37.140887),(42.561257,37.146623),(42.564668,37.152049),(42.576967,37.17923),(42.702334,37.325346),(42.706158,37.333226),(42.707398,37.340151),(42.709465,37.347179),(42.715666,37.355292),(42.722177,37.358909),(42.77158,37.374903),(42.780468,37.375498),(42.792457,37.374335),(42.801139,37.36909),(42.80548,37.351856),(42.814058,37.346817),(42.89674,37.324906)] +Israel [(35.803633,33.248463),(35.807664,33.201721),(35.830195,33.189991),(35.833399,33.161129),(35.822443,33.14157),(35.811488,33.126765),(35.811488,33.111908),(35.848902,33.098678),(35.845801,33.085423),(35.85903,32.99021),(35.864611,32.97773),(35.888073,32.944941),(35.874017,32.922333),(35.866885,32.920782),(35.849729,32.895823),(35.83805,32.866031),(35.841874,32.853577),(35.834226,32.827946),(35.784203,32.777949),(35.75759,32.744347),(35.757435,32.744282),(35.740175,32.740535),(35.685191,32.711234),(35.652015,32.686171),(35.635995,32.679143),(35.612334,32.681535),(35.612224,32.681546),(35.593827,32.670358),(35.578737,32.653434),(35.569849,32.646768),(35.562718,32.64421),(35.560547,32.640903),(35.560031,32.632686),(35.564061,32.625477),(35.572536,32.62124),(35.572536,32.615013),(35.565612,32.615013),(35.565612,32.607546),(35.571296,32.598554),(35.574397,32.572767),(35.579978,32.560391),(35.575844,32.554965),(35.574397,32.554396),(35.57388,32.556748),(35.572536,32.560391),(35.570159,32.556825),(35.565612,32.546102),(35.55941,32.55295),(35.562821,32.532021),(35.565612,32.525587),(35.551969,32.525587),(35.551969,32.518817),(35.55724,32.519334),(35.561374,32.519179),(35.568505,32.510265),(35.570573,32.506027),(35.579978,32.497733),(35.579978,32.49148),(35.570986,32.489207),(35.564991,32.48391),(35.561271,32.477089),(35.55941,32.470396),(35.563131,32.468174),(35.565405,32.466314),(35.568092,32.46497),(35.572536,32.464195),(35.572536,32.456728),(35.566232,32.453111),(35.55941,32.450527),(35.565612,32.443706),(35.551969,32.436212),(35.554139,32.434455),(35.556207,32.434791),(35.55786,32.43412),(35.55941,32.429443),(35.551969,32.429443),(35.551969,32.423242),(35.55817,32.417997),(35.5591,32.413966),(35.554863,32.411175),(35.545148,32.409573),(35.549592,32.39854),(35.551969,32.395285),(35.556827,32.390918),(35.560961,32.384717),(35.480139,32.402416),(35.456678,32.40761),(35.432803,32.408256),(35.406862,32.414793),(35.401384,32.440011),(35.401797,32.470965),(35.392909,32.494478),(35.363143,32.51011),(35.333378,32.513081),(35.270436,32.510471),(35.252246,32.515949),(35.22372,32.535896),(35.210359,32.541868),(35.208631,32.54264),(35.190751,32.54171),(35.176798,32.532692),(35.151683,32.507914),(35.120678,32.491325),(35.090705,32.479233),(35.06435,32.463136),(35.044713,32.43412),(35.03273,32.3822),(35.028797,32.365157),(35.021562,32.34459),(35.017841,32.342213),(35.004509,32.338053),(35.000685,32.335728),(34.996551,32.323041),(34.993037,32.29157),(34.989936,32.27847),(35.002442,32.275137),(35.009366,32.267644),(35.011123,32.257102),(35.007609,32.24439),(35.000271,32.232013),(34.961411,32.201576),(34.948078,32.186874),(34.946115,32.177262),(34.962341,32.146359),(34.967302,32.129461),(34.979911,32.035203),(34.980428,32.016548),(34.978671,31.994379),(34.978671,31.993707),(34.978981,31.993087),(34.979601,31.99257),(34.980324,31.992157),(34.981151,31.98885),(34.981461,31.985232),(34.981151,31.981615),(34.980324,31.978204),(34.976087,31.948232),(34.995827,31.909165),(35.007713,31.875678),(34.980324,31.862604),(34.953246,31.854439),(34.947326,31.840925),(34.945391,31.836507),(34.954796,31.819764),(34.987766,31.814803),(35.003372,31.814648),(35.010503,31.815889),(35.020425,31.82116),(35.038099,31.837386),(35.04554,31.841417),(35.059699,31.839401),(35.111893,31.818059),(35.181449,31.804106),(35.198399,31.795166),(35.206254,31.782764),(35.208011,31.766124),(35.206564,31.744627),(35.202843,31.738942),(35.198296,31.737702),(35.193128,31.739873),(35.187443,31.744472),(35.125742,31.733103),(35.106725,31.724938),(35.088845,31.712587),(35.054015,31.682202),(34.973606,31.63037),(34.955313,31.61187),(34.953176,31.60832),(34.93733,31.582001),(34.932885,31.554923),(34.932472,31.526966),(34.926788,31.494409),(34.881726,31.429866),(34.867153,31.396431),(34.878832,31.362841),(34.900949,31.348475),(34.927408,31.34491),(34.9549,31.34863),(34.980324,31.356175),(35.040166,31.363203),(35.164913,31.362273),(35.223307,31.381031),(35.332344,31.458804),(35.390118,31.487071),(35.458125,31.491929),(35.458538,31.491619),(35.457128,31.433524),(35.456884,31.423509),(35.452854,31.400823),(35.435077,31.360619),(35.416473,31.331835),(35.423915,31.324601),(35.422261,31.303),(35.408205,31.282019),(35.3957,31.25768),(35.401177,31.230291),(35.410686,31.204608),(35.421331,31.184506),(35.436214,31.159546),(35.443242,31.132209),(35.438488,31.103736),(35.391565,31.023947),(35.385158,30.994647),(35.385261,30.963279),(35.374099,30.945141),(35.34711,30.92271),(35.334928,30.912585),(35.322216,30.88995),(35.319528,30.867316),(35.320045,30.84494),(35.316635,30.822823),(35.310847,30.813314),(35.293897,30.800188),(35.286145,30.792333),(35.279531,30.780241),(35.27612,30.768976),(35.271573,30.743706),(35.263882,30.719967),(35.263821,30.71978),(35.205324,30.617099),(35.162122,30.494677),(35.157368,30.470854),(35.140005,30.430185),(35.140005,30.406155),(35.144965,30.395872),(35.159332,30.375615),(35.162122,30.361404),(35.159952,30.347503),(35.154474,30.336754),(35.147756,30.32647),(35.141762,30.313965),(35.132356,30.261875),(35.125225,30.244667),(35.124812,30.21609),(35.145276,30.154905),(35.145276,30.123382),(35.129049,30.089741),(35.086261,30.034034),(35.074686,29.994604),(35.074065,29.982564),(35.070345,29.973727),(35.065384,29.965976),(35.061456,29.957346),(35.054118,29.923394),(35.053188,29.862623),(35.048951,29.842314),(35.002545,29.733096),(34.995104,29.708162),(34.989833,29.651964),(34.980324,29.627004),(34.966992,29.608116),(34.95986,29.586206),(34.95558,29.558987),(34.955577,29.558987),(34.951345,29.54564),(34.944998,29.536851),(34.927745,29.518012),(34.91977,29.507392),(34.915782,29.50023),(34.914073,29.493801),(34.910818,29.489936),(34.903005,29.489691),(34.893728,29.490546),(34.886729,29.490058),(34.878108,29.504298),(34.855267,29.545717),(34.848239,29.569643),(34.8501,29.63876),(34.824365,29.7417),(34.785194,29.835699),(34.741373,29.940241),(34.735068,29.994553),(34.735585,30.000702),(34.734965,30.006697),(34.733208,30.012588),(34.730417,30.018169),(34.69166,30.114545),(34.632645,30.26203),(34.599469,30.344506),(34.58841,30.35882),(34.53384,30.400213),(34.526915,30.409618),(34.524745,30.421142),(34.526502,30.438712),(34.53601,30.468581),(34.536217,30.482172),(34.526295,30.494522),(34.526295,30.494574),(34.510379,30.513332),(34.504384,30.530334),(34.502214,30.571675),(34.480407,30.651205),(34.418808,30.7913),(34.367855,30.907417),(34.329511,30.994492),(34.297989,31.078776),(34.258611,31.184144),(34.248351,31.211449),(34.264399,31.224193),(34.315869,31.256905),(34.350905,31.289254),(34.353799,31.306359),(34.345531,31.340724),(34.345841,31.357725),(34.367339,31.392814),(34.480407,31.485624),(34.495496,31.494409),(34.495703,31.494409),(34.528259,31.520144),(34.530429,31.541383),(34.511412,31.561589),(34.481204,31.583141),(34.481212,31.583157),(34.489513,31.600409),(34.513927,31.627143),(34.602712,31.757758),(34.60963,31.76553),(34.665945,31.873887),(34.693207,31.926459),(34.711925,31.951606),(34.743337,32.039862),(34.743988,32.044623),(34.742686,32.055609),(34.743337,32.06037),(34.757009,32.066596),(34.837657,32.280707),(34.87322,32.430325),(34.904145,32.560614),(34.909841,32.570258),(34.915863,32.614895),(34.920909,32.628241),(34.919119,32.642971),(34.942068,32.724514),(34.94752,32.814154),(34.955577,32.834377),(34.97047,32.841376),(34.983165,32.838772),(35.003429,32.827541),(35.018728,32.825019),(35.02768,32.826606),(35.062755,32.858344),(35.067068,32.866848),(35.075531,32.893093),(35.0796,32.905829),(35.07781,32.917873),(35.06544,32.923082),(35.071544,32.937934),(35.078461,32.998847),(35.09197,33.031195),(35.096202,33.05036),(35.092133,33.067694),(35.096446,33.071357),(35.101817,33.077623),(35.106456,33.080756),(35.09962,33.087592),(35.104259,33.088528),(35.105235,33.089016),(35.185273,33.083977),(35.189614,33.085527),(35.200673,33.092736),(35.207184,33.094803),(35.213178,33.094441),(35.227338,33.091366),(35.234469,33.090927),(35.271469,33.101185),(35.283665,33.101185),(35.288825,33.099201),(35.29462,33.096973),(35.305783,33.089377),(35.315704,33.079222),(35.322629,33.067363),(35.331931,33.057156),(35.34516,33.05558),(35.401591,33.067931),(35.449443,33.085217),(35.480139,33.087387),(35.4851,33.102606),(35.503703,33.130615),(35.512282,33.147409),(35.517656,33.172886),(35.520033,33.222185),(35.527784,33.244251),(35.53688,33.257868),(35.542771,33.271536),(35.549489,33.281019),(35.561167,33.28213),(35.566955,33.276187),(35.585042,33.252209),(35.597754,33.244354),(35.597858,33.24438),(35.598064,33.244251),(35.603852,33.240091),(35.603892,33.240323),(35.604576,33.244251),(35.604576,33.244303),(35.604576,33.244354),(35.601475,33.262725),(35.610363,33.27027),(35.624716,33.272924),(35.640542,33.275851),(35.66049,33.289261),(35.698523,33.32267),(35.716197,33.326727),(35.729426,33.327812),(35.743689,33.331171),(35.757538,33.336313),(35.769423,33.342643),(35.785753,33.357887),(35.8057,33.391348),(35.8211,33.406722),(35.822443,33.401373),(35.816966,33.395198),(35.815415,33.378868),(35.812315,33.373365),(35.809938,33.360032),(35.793505,33.349929),(35.785753,33.342875),(35.763842,33.334401),(35.802083,33.31249),(35.768597,33.272699),(35.775625,33.264896),(35.803633,33.248463)] +Jamaica [(-76.263743,18.012356),(-76.256785,17.996324),(-76.248769,17.977851),(-76.234039,17.953925),(-76.21524,17.934963),(-76.187978,17.915473),(-76.198394,17.907416),(-76.250071,17.894965),(-76.286488,17.875881),(-76.307362,17.870103),(-76.325185,17.874498),(-76.318227,17.879299),(-76.315419,17.882717),(-76.311513,17.894965),(-76.329579,17.888658),(-76.345611,17.865871),(-76.363026,17.860826),(-76.378529,17.865058),(-76.396555,17.872992),(-76.414906,17.877509),(-76.444936,17.866767),(-76.523549,17.860256),(-76.57901,17.868313),(-76.587066,17.867987),(-76.594594,17.866604),(-76.602773,17.867621),(-76.613149,17.874498),(-76.617665,17.883531),(-76.6197,17.895087),(-76.622711,17.905015),(-76.630523,17.909247),(-76.63858,17.911607),(-76.643951,17.917222),(-76.64859,17.923896),(-76.654775,17.929145),(-76.684804,17.936021),(-76.692291,17.940009),(-76.707672,17.94595),(-76.728424,17.94477),(-76.764638,17.936591),(-76.7801,17.934801),(-76.832265,17.936591),(-76.832265,17.943427),(-76.722401,17.949612),(-76.729319,17.955959),(-76.734364,17.960598),(-76.747467,17.963446),(-76.777659,17.963853),(-76.798164,17.96342),(-76.819056,17.975273),(-76.836829,17.986359),(-76.849967,17.992276),(-76.853069,17.981968),(-76.857761,17.971398),(-76.870173,17.95805),(-76.874005,17.950349),(-76.887156,17.951856),(-76.891037,17.944502),(-76.894944,17.921681),(-76.912828,17.861287),(-76.926096,17.843329),(-76.942128,17.833564),(-76.955312,17.833441),(-76.964019,17.837226),(-76.972076,17.842434),(-76.983062,17.846584),(-77.038319,17.846584),(-77.038319,17.85399),(-77.017201,17.860826),(-77.027984,17.869818),(-77.041493,17.887152),(-77.051991,17.894965),(-77.064198,17.899482),(-77.093007,17.902493),(-77.119109,17.893803),(-77.141652,17.881134),(-77.158079,17.849875),(-77.161977,17.840766),(-77.154408,17.813056),(-77.161692,17.810289),(-77.174387,17.802924),(-77.181711,17.799994),(-77.179107,17.794745),(-77.177358,17.784613),(-77.174916,17.778266),(-77.185618,17.782904),(-77.19636,17.783393),(-77.206776,17.779853),(-77.216461,17.772121),(-77.198883,17.761786),(-77.180328,17.75788),(-77.160878,17.759426),(-77.140736,17.765286),(-77.130605,17.727688),(-77.133656,17.710435),(-77.158111,17.703192),(-77.178944,17.704169),(-77.197581,17.708197),(-77.216054,17.716702),(-77.302887,17.790839),(-77.320872,17.812445),(-77.395619,17.853949),(-77.417714,17.861721),(-77.441029,17.864651),(-77.459462,17.857408),(-77.480621,17.843736),(-77.50182,17.841946),(-77.545481,17.85399),(-77.588368,17.860989),(-77.723866,17.853583),(-77.730702,17.854804),(-77.751536,17.868313),(-77.786733,17.884955),(-77.795562,17.891547),(-77.799916,17.899115),(-77.810292,17.92475),(-77.812367,17.932847),(-77.816151,17.939195),(-77.834055,17.945299),(-77.83967,17.949612),(-77.841135,17.970608),(-77.839345,17.995836),(-77.84557,18.017035),(-77.871002,18.025946),(-77.940338,18.026516),(-77.956288,18.032172),(-77.97997,18.084459),(-77.987864,18.095364),(-77.996449,18.10102),(-78.006418,18.105862),(-78.014394,18.107856),(-78.020579,18.113105),(-78.02538,18.12519),(-78.031484,18.148871),(-78.050282,18.185126),(-78.075185,18.198432),(-78.148793,18.196682),(-78.193756,18.203925),(-78.210194,18.204088),(-78.219594,18.195868),(-78.227284,18.19184),(-78.234039,18.193183),(-78.258656,18.202623),(-78.261138,18.204088),(-78.275136,18.206244),(-78.305898,18.215644),(-78.32315,18.217719),(-78.340728,18.221869),(-78.357737,18.232733),(-78.370269,18.248114),(-78.374664,18.26557),(-78.36913,18.273871),(-78.354319,18.28384),(-78.34732,18.292222),(-78.34439,18.305365),(-78.345815,18.335517),(-78.343902,18.344062),(-78.336293,18.355902),(-78.335439,18.36343),(-78.331939,18.367377),(-78.316396,18.368598),(-78.30663,18.374661),(-78.298695,18.386379),(-78.288401,18.394355),(-78.271637,18.389065),(-78.261301,18.417385),(-78.230621,18.444241),(-78.194976,18.455471),(-78.16926,18.436835),(-78.154408,18.453518),(-78.138539,18.453843),(-78.119985,18.447333),(-78.097239,18.443061),(-78.032541,18.450629),(-78.010976,18.450507),(-78.000152,18.446682),(-77.992421,18.443996),(-77.981353,18.441352),(-77.96996,18.443061),(-77.959828,18.449897),(-77.958852,18.456448),(-77.959137,18.464097),(-77.952952,18.474433),(-77.930287,18.502021),(-77.919993,18.511176),(-77.902333,18.518785),(-77.861887,18.525092),(-77.81607,18.523424),(-77.735544,18.5067),(-77.66454,18.491929),(-77.56725,18.49018),(-77.524281,18.480211),(-77.454986,18.475328),(-77.428863,18.469224),(-77.408274,18.457343),(-77.376536,18.465155),(-77.325307,18.465033),(-77.272613,18.459377),(-77.236318,18.450507),(-77.231842,18.446031),(-77.228139,18.433661),(-77.223297,18.429389),(-77.217437,18.429348),(-77.212026,18.431789),(-77.208852,18.434963),(-77.209625,18.436835),(-77.164947,18.429389),(-77.159413,18.426215),(-77.142568,18.412095),(-77.137359,18.408922),(-77.104726,18.407864),(-77.070343,18.413357),(-77.051991,18.416327),(-77.040028,18.413479),(-77.019154,18.40412),(-77.007314,18.402086),(-76.94815,18.404486),(-76.936615,18.410295),(-76.920338,18.412195),(-76.907118,18.411205),(-76.894919,18.409251),(-76.887827,18.400552),(-76.890916,18.389947),(-76.890948,18.376441),(-76.879783,18.366769),(-76.844211,18.345447),(-76.812754,18.32801),(-76.807622,18.318308),(-76.798329,18.29206),(-76.792388,18.283393),(-76.782826,18.277818),(-76.764638,18.273017),(-76.71288,18.269192),(-76.695709,18.26557),(-76.68102,18.258124),(-76.661977,18.239814),(-76.647328,18.23078),(-76.63036,18.225735),(-76.597158,18.227748),(-76.57977,18.21603),(-76.574208,18.214667),(-76.569203,18.21011),(-76.563059,18.205959),(-76.554799,18.204088),(-76.479726,18.204088),(-76.474477,18.201077),(-76.466624,18.186754),(-76.463002,18.182359),(-76.389394,18.169176),(-76.351145,18.155992),(-76.346262,18.135199),(-76.31786,18.10928),(-76.295806,18.079169),(-76.263743,18.012356)] +Jersey [(-2.082672,49.26024),(-2.06786,49.250678),(-2.02066,49.235256),(-2.021962,49.225491),(-2.017323,49.221381),(-2.011871,49.215277),(-2.00829,49.21247),(-2.016998,49.207221),(-2.020985,49.200751),(-2.022043,49.19245),(-2.021962,49.181383),(-2.024526,49.171332),(-2.031158,49.171454),(-2.040028,49.175727),(-2.049224,49.17829),(-2.079986,49.178697),(-2.096995,49.183661),(-2.120229,49.199164),(-2.128896,49.20307),(-2.137929,49.205634),(-2.144846,49.205634),(-2.152943,49.199937),(-2.160634,49.190741),(-2.168691,49.17829),(-2.177154,49.180162),(-2.189687,49.189114),(-2.200103,49.191962),(-2.202952,49.190416),(-2.223378,49.184719),(-2.233632,49.184516),(-2.226471,49.206),(-2.233225,49.228502),(-2.242014,49.247952),(-2.241119,49.26024),(-2.22936,49.263007),(-2.215199,49.26024),(-2.196278,49.253404),(-2.182729,49.254055),(-2.172353,49.256252),(-2.162709,49.260403),(-2.151682,49.267035),(-2.143788,49.261868),(-2.121978,49.258287),(-2.110666,49.253404),(-2.103871,49.258205),(-2.097564,49.25967),(-2.082672,49.26024)] +Jordan [(39.046329,32.308494),(39.235775,32.352858),(39.256342,32.342678),(39.271122,32.311956),(39.291999,32.244519),(39.266471,32.212867),(39.146168,32.125844),(39.146375,32.118144),(39.136246,32.115353),(39.116816,32.102899),(38.998064,32.006936),(38.96344,31.994482),(38.96344,31.994327),(38.963337,31.994379),(38.849752,31.966319),(38.624856,31.91087),(38.400167,31.855369),(38.175375,31.799921),(37.986522,31.753358),(37.950479,31.744472),(37.761412,31.69612),(37.702742,31.681116),(37.455005,31.617709),(37.207269,31.554354),(36.997912,31.500814),(36.959532,31.490999),(37.089653,31.370076),(37.219774,31.249101),(37.221722,31.247292),(37.349895,31.12823),(37.480017,31.007256),(37.483117,31.004103),(37.486321,31.0009),(37.489422,30.997696),(37.492626,30.994492),(37.602283,30.883232),(37.712044,30.772025),(37.821908,30.660869),(37.931565,30.549661),(37.981071,30.499483),(37.981381,30.498811),(37.980968,30.498398),(37.980038,30.498088),(37.97332,30.494522),(37.900146,30.459072),(37.779327,30.400419),(37.670703,30.347606),(37.647552,30.330863),(37.634529,30.312776),(37.605177,30.250713),(37.56921,30.174955),(37.536137,30.105295),(37.491696,30.011193),(37.470198,29.994553),(37.352376,29.973314),(37.218534,29.949129),(37.075804,29.923291),(36.931936,29.897246),(36.84295,29.881226),(36.756237,29.865517),(36.728745,29.853528),(36.70487,29.831152),(36.649576,29.7494),(36.603584,29.681471),(36.541263,29.589409),(36.477081,29.494609),(36.399979,29.438902),(36.283707,29.35485),(36.177977,29.278369),(36.069457,29.200028),(36.043825,29.190881),(36.016437,29.189951),(35.912464,29.205686),(35.797225,29.223075),(35.740251,29.231731),(35.622042,29.249689),(35.473628,29.272065),(35.334618,29.293148),(35.179072,29.316661),(35.060319,29.334696),(34.949385,29.351686),(34.949392,29.351711),(34.962413,29.359768),(34.969005,29.450832),(34.976085,29.477037),(34.997813,29.517971),(34.996837,29.533881),(34.976085,29.552151),(34.962413,29.552151),(34.961599,29.555406),(34.961599,29.558092),(34.960216,29.559516),(34.95558,29.558987),(34.95986,29.586206),(34.966992,29.608116),(34.980324,29.627004),(34.989833,29.651964),(34.995104,29.708162),(35.002545,29.733096),(35.048951,29.842314),(35.053188,29.862623),(35.054118,29.923394),(35.061456,29.957346),(35.065384,29.965976),(35.070345,29.973727),(35.074065,29.982564),(35.074686,29.994604),(35.086261,30.034034),(35.129049,30.089741),(35.145276,30.123382),(35.145276,30.154905),(35.124812,30.21609),(35.125225,30.244667),(35.132356,30.261875),(35.141762,30.313965),(35.147756,30.32647),(35.154474,30.336754),(35.159952,30.347503),(35.162122,30.361404),(35.159332,30.375615),(35.144965,30.395872),(35.140005,30.406155),(35.140005,30.430185),(35.157368,30.470854),(35.162122,30.494677),(35.205324,30.617099),(35.263821,30.71978),(35.263882,30.719967),(35.271573,30.743706),(35.27612,30.768976),(35.279531,30.780241),(35.286145,30.792333),(35.293897,30.800188),(35.310847,30.813314),(35.316635,30.822823),(35.320045,30.84494),(35.319528,30.867316),(35.322216,30.88995),(35.334928,30.912585),(35.34711,30.92271),(35.374099,30.945141),(35.385261,30.963279),(35.385158,30.994647),(35.391565,31.023947),(35.438488,31.103736),(35.443242,31.132209),(35.436214,31.159546),(35.421331,31.184506),(35.410686,31.204608),(35.401177,31.230291),(35.3957,31.25768),(35.408205,31.282019),(35.422261,31.303),(35.423915,31.324601),(35.416473,31.331835),(35.435077,31.360619),(35.452854,31.400823),(35.456884,31.423509),(35.457128,31.433524),(35.458538,31.491619),(35.458125,31.491929),(35.458745,31.491567),(35.459158,31.491877),(35.459055,31.492808),(35.458745,31.494409),(35.464222,31.568565),(35.480139,31.641119),(35.502479,31.68536),(35.527578,31.735067),(35.55941,31.765349),(35.538326,31.819299),(35.538326,31.826741),(35.549075,31.839195),(35.524684,31.919241),(35.527474,31.927355),(35.533676,31.9303),(35.5406,31.932006),(35.545148,31.936605),(35.545871,31.944563),(35.53998,31.955622),(35.538326,31.963942),(35.537706,31.977584),(35.535536,31.988229),(35.524684,32.011691),(35.522824,32.057838),(35.528301,32.075098),(35.545148,32.086828),(35.534606,32.09923),(35.535226,32.110806),(35.551969,32.135197),(35.546698,32.141605),(35.546698,32.147031),(35.551246,32.151527),(35.55941,32.155093),(35.55941,32.162534),(35.555173,32.174394),(35.559562,32.190371),(35.572536,32.237594),(35.55941,32.237594),(35.561064,32.243149),(35.563751,32.246818),(35.567575,32.249506),(35.572536,32.251908),(35.564578,32.263587),(35.560857,32.28263),(35.561167,32.301699),(35.565612,32.313352),(35.556517,32.328209),(35.557343,32.358207),(35.551969,32.367948),(35.551969,32.374821),(35.55941,32.374821),(35.55941,32.367948),(35.565612,32.367948),(35.563958,32.377043),(35.560961,32.384717),(35.556827,32.390918),(35.551969,32.395285),(35.549592,32.39854),(35.545148,32.409573),(35.554863,32.411175),(35.5591,32.413966),(35.55817,32.417997),(35.551969,32.423242),(35.551969,32.429443),(35.55941,32.429443),(35.55786,32.43412),(35.556207,32.434791),(35.554139,32.434455),(35.551969,32.436212),(35.565612,32.443706),(35.55941,32.450527),(35.566232,32.453111),(35.572536,32.456728),(35.572536,32.464195),(35.568092,32.46497),(35.565405,32.466314),(35.563131,32.468174),(35.55941,32.470396),(35.561271,32.477089),(35.564991,32.48391),(35.570986,32.489207),(35.579978,32.49148),(35.579978,32.497733),(35.570573,32.506027),(35.568505,32.510265),(35.561374,32.519179),(35.55724,32.519334),(35.551969,32.518817),(35.551969,32.525587),(35.565612,32.525587),(35.562821,32.532021),(35.55941,32.55295),(35.565612,32.546102),(35.570159,32.556825),(35.572536,32.560391),(35.57388,32.556748),(35.574397,32.554396),(35.575844,32.554965),(35.579978,32.560391),(35.574397,32.572767),(35.571296,32.598554),(35.565612,32.607546),(35.565612,32.615013),(35.572536,32.615013),(35.572536,32.62124),(35.564061,32.625477),(35.560031,32.632686),(35.560547,32.640903),(35.562718,32.64421),(35.569849,32.646768),(35.578737,32.653434),(35.593827,32.670358),(35.612224,32.681546),(35.612334,32.681535),(35.635995,32.679143),(35.652015,32.686171),(35.685191,32.711234),(35.740175,32.740535),(35.757435,32.744282),(35.75759,32.744347),(35.763842,32.746969),(35.769734,32.748054),(35.774901,32.747279),(35.779139,32.744514),(35.779139,32.744462),(35.779035,32.744359),(35.779035,32.744282),(35.788234,32.734411),(35.895721,32.713276),(35.905229,32.708573),(35.922489,32.693768),(35.92745,32.692373),(35.940369,32.692502),(35.944193,32.690771),(35.945743,32.684104),(35.9444,32.677619),(35.941196,32.673536),(35.937475,32.674002),(35.94657,32.664441),(35.955355,32.657439),(35.965794,32.654365),(35.980263,32.656612),(36.003621,32.655088),(36.008272,32.643719),(36.005275,32.626692),(36.005998,32.607907),(36.015403,32.591164),(36.060465,32.533261),(36.066046,32.521608),(36.066253,32.517319),(36.06987,32.516595),(36.081906,32.516265),(36.096225,32.515872),(36.133226,32.520109),(36.13953,32.519541),(36.149865,32.51613),(36.15586,32.5152),(36.160821,32.517215),(36.17219,32.525923),(36.177357,32.527318),(36.188209,32.52228),(36.220765,32.494581),(36.285258,32.456935),(36.373108,32.386422),(36.387887,32.379317),(36.407627,32.374227),(36.463955,32.369395),(36.480181,32.360791),(36.516684,32.357014),(36.653504,32.342859),(36.689574,32.319656),(36.706937,32.328338),(36.728641,32.327795),(36.792513,32.313533),(36.806569,32.313042),(36.819385,32.316788),(36.980099,32.410038),(37.133165,32.494478),(37.133165,32.494529),(37.133371,32.494529),(37.133371,32.494581),(37.244062,32.554396),(37.415214,32.64713),(37.494606,32.690056),(37.586677,32.739837),(37.758036,32.832519),(37.929395,32.92533),(38.056726,32.994292),(38.056726,32.994344),(38.230875,33.086302),(38.315742,33.13118),(38.529565,33.244251),(38.774511,33.371685),(38.82102,33.229032),(38.862568,33.10072),(38.897191,32.994344),(38.94277,32.852337),(38.990002,32.705576),(39.057181,32.496596),(38.979977,32.476055),(38.978633,32.475693),(38.97822,32.47497),(38.978633,32.47373),(38.979977,32.472102),(39.028759,32.328338),(39.036201,32.313352),(39.046329,32.308494)] +Baykonur Cosmodrome [(63.383914,45.565824),(63.324279,45.567969),(63.26635,45.574222),(63.210488,45.584376),(63.156899,45.598251),(63.105946,45.615615),(63.057835,45.636285),(63.012929,45.660005),(62.971484,45.686644),(62.933864,45.715945),(62.900274,45.7477),(62.871025,45.781703),(62.846479,45.817773),(62.826893,45.855703),(62.812527,45.895184),(62.803639,45.936164),(62.800642,45.978332),(62.803639,46.0205),(62.812527,46.061427),(62.826893,46.100986),(62.846479,46.13889),(62.871025,46.17496),(62.900274,46.208964),(62.933864,46.240719),(62.971484,46.270019),(63.012929,46.296658),(63.057835,46.320378),(63.105946,46.341048),(63.156899,46.358412),(63.210488,46.372261),(63.26635,46.382441),(63.324279,46.388694),(63.383914,46.390839),(63.443548,46.388694),(63.501477,46.382441),(63.557391,46.372261),(63.610928,46.358412),(63.661881,46.341048),(63.70994,46.320378),(63.754899,46.296658),(63.796343,46.270019),(63.833964,46.240719),(63.867553,46.208964),(63.896699,46.17496),(63.921297,46.13889),(63.940934,46.100986),(63.9553,46.061427),(63.964085,46.0205),(63.967134,45.978332),(63.964085,45.936164),(63.9553,45.895184),(63.940934,45.855703),(63.921297,45.817773),(63.896699,45.781703),(63.867553,45.7477),(63.833964,45.715945),(63.796343,45.686644),(63.754899,45.660005),(63.70994,45.636285),(63.661881,45.615615),(63.610928,45.598251),(63.557391,45.584376),(63.501477,45.574222),(63.443548,45.567969),(63.383914,45.565824)] +Siachen Glacier [(76.976417,35.578656),(77.017552,35.584599),(77.039049,35.585013),(77.058169,35.580103),(77.071089,35.571008),(77.092276,35.547805),(77.105298,35.537987),(77.141265,35.525378),(77.177542,35.523156),(77.250819,35.530701),(77.281102,35.528013),(77.305389,35.517833),(77.352002,35.486052),(77.383731,35.471996),(77.412773,35.469412),(77.476438,35.477164),(77.512199,35.478456),(77.519608,35.477439),(77.660613,35.458095),(77.689655,35.462694),(77.716734,35.475407),(77.74743,35.49432),(77.760349,35.498093),(77.773578,35.498971),(77.800346,35.495406),(77.424659,35.302924),(77.048971,35.110442),(76.913161,35.378277),(76.777351,35.646112),(76.782837,35.645732),(76.824592,35.647799),(76.842989,35.641288),(76.856941,35.628576),(76.880506,35.60067),(76.896422,35.589612),(76.915026,35.583152),(76.9358,35.579638),(76.976417,35.578656)] +Kosovo [(20.8647,43.217337),(20.8616,43.217518),(20.851471,43.219818),(20.839999,43.212092),(20.840619,43.206976),(20.839069,43.192455),(20.836071,43.179433),(20.832041,43.178606),(20.838552,43.170467),(20.912494,43.138805),(20.993431,43.104148),(21.005157,43.099128),(21.025827,43.093366),(21.092593,43.090678),(21.10851,43.081558),(21.124012,43.058277),(21.139309,43.005826),(21.147887,42.992622),(21.165354,42.985103),(21.17941,42.990581),(21.193052,42.997893),(21.209795,42.995878),(21.225298,42.973554),(21.226745,42.942522),(21.23243,42.910896),(21.260542,42.886556),(21.2716,42.884283),(21.294958,42.884386),(21.306327,42.882448),(21.316972,42.877616),(21.336403,42.865473),(21.346738,42.860847),(21.378777,42.855292),(21.398931,42.854569),(21.40844,42.846998),(21.408419,42.841743),(21.408336,42.820747),(21.404099,42.803978),(21.39056,42.770414),(21.387149,42.754962),(21.383945,42.749976),(21.379191,42.747004),(21.378674,42.744136),(21.388699,42.739046),(21.405546,42.7353),(21.4178,42.73557),(21.441823,42.736101),(21.542488,42.725817),(21.565226,42.720184),(21.580522,42.710211),(21.612665,42.680393),(21.629408,42.672203),(21.644084,42.672306),(21.687389,42.686827),(21.708886,42.687189),(21.738652,42.68215),(21.74425,42.679425),(21.764387,42.669619),(21.772758,42.647501),(21.767074,42.638716),(21.756532,42.633626),(21.744543,42.629647),(21.734725,42.624247),(21.735551,42.621276),(21.730074,42.601018),(21.728833,42.598305),(21.726973,42.596393),(21.720152,42.593887),(21.718291,42.591019),(21.719738,42.586678),(21.726766,42.577945),(21.727697,42.574147),(21.717671,42.551151),(21.667855,42.490095),(21.627858,42.460381),(21.618969,42.449245),(21.616902,42.433923),(21.621863,42.402167),(21.617419,42.386639),(21.596645,42.372092),(21.537321,42.35863),(21.51603,42.341939),(21.514893,42.317832),(21.553857,42.273984),(21.564066,42.246289),(21.561815,42.247164),(21.519854,42.239025),(21.499287,42.238663),(21.48151,42.247784),(21.471973,42.23913),(21.467557,42.235123),(21.457222,42.237035),(21.44792,42.244141),(21.436345,42.24688),(21.419912,42.240058),(21.421462,42.231351),(21.428697,42.222566),(21.429834,42.215848),(21.419085,42.215021),(21.384255,42.224943),(21.366788,42.223858),(21.360602,42.220114),(21.353766,42.215977),(21.294958,42.148979),(21.293718,42.140168),(21.295785,42.134794),(21.298782,42.129419),(21.300332,42.120893),(21.301263,42.10061),(21.300796,42.098425),(21.299299,42.091411),(21.28886,42.089706),(21.245727,42.096167),(21.237804,42.097354),(21.229298,42.103822),(21.225402,42.106785),(21.216203,42.121151),(21.199873,42.14115),(21.164423,42.16704),(21.12639,42.188925),(21.112954,42.194402),(21.106236,42.195798),(21.098484,42.195953),(21.074403,42.184455),(21.04094,42.15997),(21.029238,42.151408),(21.003916,42.141951),(20.975145,42.134658),(20.90417,42.116668),(20.810543,42.092936),(20.784912,42.082032),(20.765378,42.064333),(20.755353,42.042784),(20.743054,41.993484),(20.741814,41.970773),(20.751439,41.940338),(20.754423,41.930904),(20.751052,41.910218),(20.750495,41.906797),(20.739953,41.888039),(20.723313,41.866619),(20.714398,41.859163),(20.702953,41.849591),(20.681456,41.84401),(20.671844,41.849307),(20.652827,41.86928),(20.643422,41.873647),(20.637014,41.870365),(20.626162,41.855198),(20.61872,41.850522),(20.602391,41.849876),(20.590298,41.854733),(20.567147,41.873182),(20.567767,41.88052),(20.562703,41.892845),(20.562496,41.900105),(20.567251,41.912172),(20.573348,41.917675),(20.580583,41.921732),(20.588748,41.929586),(20.59929,41.94788),(20.59929,41.960567),(20.594329,41.973718),(20.589678,41.993639),(20.558259,42.055109),(20.552161,42.07379),(20.551954,42.105803),(20.549371,42.123476),(20.538622,42.150116),(20.500795,42.211223),(20.481674,42.230705),(20.473665,42.237123),(20.456973,42.250497),(20.333363,42.317883),(20.317964,42.319821),(20.249647,42.318607),(20.237762,42.319924),(20.229597,42.32672),(20.220915,42.343101),(20.219468,42.350207),(20.221225,42.36372),(20.218848,42.371446),(20.21306,42.377518),(20.197454,42.38744),(20.192803,42.393693),(20.194043,42.4001),(20.204379,42.411831),(20.204689,42.420099),(20.199728,42.427799),(20.186292,42.437437),(20.180814,42.443095),(20.152702,42.493402),(20.152702,42.493428),(20.152599,42.493609),(20.152599,42.493712),(20.152392,42.493712),(20.135546,42.509629),(20.085626,42.530015),(20.064956,42.546758),(20.077048,42.55991),(20.078185,42.572906),(20.075394,42.586962),(20.075704,42.603085),(20.079218,42.61125),(20.090587,42.627348),(20.10392,42.653108),(20.101956,42.656674),(20.094205,42.666983),(20.037006,42.707363),(20.03612,42.707989),(20.024751,42.723414),(20.026508,42.743206),(20.034673,42.751423),(20.055638,42.763866),(20.065059,42.769458),(20.076325,42.773437),(20.112085,42.766538),(20.149498,42.749872),(20.183398,42.742508),(20.208409,42.763282),(20.20996,42.772972),(20.208409,42.782093),(20.209236,42.791704),(20.217608,42.802737),(20.226083,42.806768),(20.264427,42.817258),(20.345352,42.827439),(20.428034,42.840642),(20.4763,42.855525),(20.498831,42.877875),(20.494367,42.887467),(20.488909,42.899191),(20.466688,42.909501),(20.450979,42.922032),(20.459454,42.950015),(20.476403,42.966371),(20.493457,42.970195),(20.51113,42.970195),(20.530457,42.975156),(20.538415,42.980659),(20.543893,42.987248),(20.553401,43.002596),(20.562393,43.009495),(20.572832,43.00934),(20.584304,43.006911),(20.596396,43.007092),(20.617273,43.02213),(20.643835,43.052257),(20.664919,43.085407),(20.669157,43.109799),(20.661818,43.115948),(20.65169,43.11631),(20.640941,43.115276),(20.632053,43.117266),(20.626058,43.123725),(20.620581,43.133337),(20.612106,43.154938),(20.600117,43.173826),(20.597533,43.184962),(20.604044,43.197959),(20.612312,43.202274),(20.644869,43.203307),(20.666986,43.209663),(20.745328,43.252865),(20.769512,43.260849),(20.79442,43.263071),(20.809717,43.25961),(20.819432,43.257412),(20.838449,43.245863),(20.848474,43.238137),(20.855088,43.231445),(20.8647,43.217337)] +Laos [(101.867921,22.378842),(101.877275,22.391864),(101.881512,22.412173),(101.891641,22.429691),(101.909366,22.435893),(101.952877,22.436874),(101.97422,22.445143),(101.994994,22.447416),(102.014579,22.446073),(102.075919,22.43243),(102.085531,22.429123),(102.095349,22.423129),(102.099948,22.41486),(102.10062,22.405765),(102.107345,22.397549),(102.118655,22.397549),(102.125425,22.383648),(102.131368,22.373726),(102.141393,22.342152),(102.144183,22.338586),(102.152865,22.332488),(102.156121,22.328096),(102.156121,22.32267),(102.152813,22.310836),(102.154364,22.304686),(102.168885,22.289648),(102.186196,22.278383),(102.200562,22.265464),(102.20697,22.245413),(102.226246,22.228412),(102.286449,22.200041),(102.358072,22.134722),(102.38944,22.117101),(102.398793,22.108884),(102.405408,22.098291),(102.415226,22.073486),(102.422151,22.06222),(102.442615,22.047441),(102.467626,22.034005),(102.482871,22.021396),(102.474086,22.00889),(102.471244,22.005996),(102.469073,22.002844),(102.467316,21.999227),(102.466386,21.995351),(102.478065,21.957576),(102.515892,21.939179),(102.56023,21.925433),(102.59103,21.901352),(102.625136,21.828643),(102.634593,21.787767),(102.629787,21.729114),(102.631906,21.706273),(102.636815,21.683639),(102.643326,21.668033),(102.650664,21.657801),(102.653455,21.656302),(102.657434,21.658421),(102.710299,21.659299),(102.721151,21.661676),(102.752157,21.6809),(102.774688,21.707875),(102.786676,21.739914),(102.789157,21.820323),(102.806727,21.836084),(102.826467,21.821305),(102.834942,21.775623),(102.831893,21.73578),(102.835149,21.716453),(102.84719,21.704464),(102.864501,21.705653),(102.937003,21.735057),(102.942636,21.738984),(102.947804,21.737124),(102.95602,21.723946),(102.959896,21.713043),(102.961756,21.701519),(102.960826,21.632841),(102.964133,21.608605),(102.974107,21.586694),(102.974934,21.583903),(102.975295,21.581009),(102.974934,21.578167),(102.974107,21.575325),(102.954108,21.55729),(102.916591,21.513572),(102.89499,21.495278),(102.84967,21.425412),(102.86476,21.432181),(102.884758,21.444067),(102.904189,21.452697),(102.918038,21.450113),(102.916798,21.438641),(102.883828,21.38836),(102.879642,21.367896),(102.878816,21.322162),(102.875198,21.305316),(102.863003,21.293792),(102.829155,21.285885),(102.812773,21.273896),(102.801301,21.254828),(102.809156,21.25059),(102.828173,21.252451),(102.850187,21.251676),(102.865121,21.246198),(102.878144,21.23762),(102.887859,21.226923),(102.892975,21.215089),(102.891786,21.205994),(102.883001,21.186098),(102.883001,21.176435),(102.889099,21.166409),(102.89592,21.164549),(102.904189,21.164187),(102.914421,21.1584),(102.925634,21.141656),(102.925885,21.14064),(102.935298,21.102382),(102.942171,21.084864),(102.946822,21.075872),(102.951576,21.068999),(102.959482,21.065795),(102.974107,21.067656),(102.99917,21.057372),(103.014518,21.040526),(103.0371,20.995464),(103.06821,20.931282),(103.08671,20.901981),(103.115287,20.868391),(103.130015,20.854904),(103.136371,20.85046),(103.146965,20.846016),(103.165051,20.84369),(103.175232,20.84121),(103.183655,20.837076),(103.197091,20.827825),(103.206909,20.82457),(103.218588,20.824363),(103.225829,20.826413),(103.238122,20.829892),(103.247113,20.830719),(103.263392,20.826378),(103.319822,20.797853),(103.347676,20.789068),(103.358321,20.787725),(103.363799,20.787621),(103.389115,20.794288),(103.390877,20.794753),(103.411238,20.805605),(103.418266,20.811806),(103.421315,20.81811),(103.426586,20.820694),(103.440435,20.815733),(103.452579,20.804313),(103.470872,20.770878),(103.481621,20.757907),(103.489373,20.752481),(103.497331,20.748347),(103.505961,20.74597),(103.516089,20.745505),(103.516089,20.745557),(103.516141,20.745505),(103.516141,20.74535),(103.577946,20.732896),(103.597376,20.722354),(103.63603,20.682821),(103.657941,20.664735),(103.661145,20.660756),(103.665383,20.658275),(103.676338,20.656518),(103.685433,20.657655),(103.697629,20.661531),(103.708481,20.66675),(103.714268,20.671711),(103.713752,20.679824),(103.703623,20.699254),(103.702383,20.708711),(103.70724,20.721837),(103.713442,20.725764),(103.72202,20.72685),(103.734371,20.730932),(103.754576,20.742921),(103.758607,20.749742),(103.755196,20.759406),(103.753026,20.77987),(103.756746,20.795993),(103.76517,20.81625),(103.775557,20.834905),(103.785324,20.845964),(103.796434,20.84953),(103.816691,20.846894),(103.82682,20.847669),(103.83576,20.852268),(103.850488,20.864774),(103.858601,20.86958),(103.932136,20.891801),(103.952187,20.900276),(103.962315,20.902705),(103.973994,20.902343),(104.010581,20.908079),(104.056676,20.958825),(104.092282,20.961202),(104.099155,20.957688),(104.114244,20.947043),(104.122616,20.943167),(104.132072,20.941669),(104.154758,20.941255),(104.165404,20.939757),(104.193877,20.929886),(104.201267,20.925442),(104.207107,20.917639),(104.217545,20.89702),(104.221059,20.892008),(104.228036,20.892318),(104.250566,20.89826),(104.260023,20.898932),(104.269067,20.896193),(104.278937,20.891542),(104.287877,20.885755),(104.295267,20.879812),(104.307204,20.864619),(104.323224,20.833872),(104.336349,20.81904),(104.344669,20.813666),(104.360327,20.808085),(104.367975,20.803124),(104.37335,20.795734),(104.38167,20.778371),(104.389059,20.770981),(104.409316,20.765194),(104.432157,20.765762),(104.452621,20.763592),(104.466161,20.749639),(104.475669,20.71822),(104.492309,20.702097),(104.543882,20.678739),(104.600726,20.660549),(104.615195,20.646493),(104.614071,20.642616),(104.607237,20.619053),(104.542642,20.535699),(104.520731,20.519265),(104.495823,20.511927),(104.469675,20.516165),(104.444973,20.534613),(104.423786,20.495443),(104.423682,20.495443),(104.366425,20.458494),(104.35981,20.439735),(104.39154,20.420667),(104.432364,20.411055),(104.575508,20.414052),(104.589357,20.406818),(104.612301,20.376742),(104.628425,20.365812),(104.666407,20.351782),(104.680928,20.340982),(104.684648,20.333049),(104.687697,20.321706),(104.689299,20.310002),(104.688628,20.301036),(104.681858,20.287471),(104.674106,20.2853),(104.665838,20.285714),(104.657363,20.279616),(104.653539,20.266464),(104.651989,20.246104),(104.653023,20.225795),(104.657053,20.212695),(104.69085,20.196546),(104.733586,20.204763),(104.778803,20.219025),(104.819162,20.220989),(104.907994,20.175333),(104.908976,20.167814),(104.903446,20.157091),(104.904893,20.134638),(104.918381,20.115724),(104.95688,20.091798),(104.964425,20.076088),(104.961169,20.072109),(104.947475,20.069525),(104.943961,20.067097),(104.943651,20.060947),(104.946441,20.052188),(104.948302,20.033662),(104.951454,20.021518),(104.953211,20.009271),(104.94949,19.995499),(104.945688,19.992373),(104.935693,19.984156),(104.922463,19.982244),(104.892905,19.9855),(104.873836,19.982657),(104.86903,19.977748),(104.86717,19.969144),(104.85792,19.955217),(104.835337,19.938887),(104.780663,19.908088),(104.761801,19.885506),(104.755549,19.867006),(104.760716,19.86145),(104.790275,19.859667),(104.80924,19.853673),(104.81663,19.848092),(104.816888,19.838997),(104.81508,19.822409),(104.805003,19.790886),(104.785211,19.776933),(104.760716,19.766521),(104.736738,19.745669),(104.717773,19.740192),(104.704182,19.738693),(104.691676,19.735463),(104.675967,19.724689),(104.663048,19.711227),(104.65478,19.697972),(104.62305,19.61808),(104.614265,19.607435),(104.604963,19.606479),(104.587807,19.615961),(104.579229,19.618028),(104.570237,19.61529),(104.554837,19.605445),(104.546156,19.601931),(104.522798,19.599373),(104.505848,19.60281),(104.449107,19.635159),(104.423786,19.645779),(104.415414,19.650817),(104.401255,19.664434),(104.391746,19.676836),(104.380068,19.685285),(104.360017,19.687456),(104.341879,19.683012),(104.295267,19.654874),(104.277025,19.68389),(104.242143,19.695181),(104.228966,19.706008),(104.200203,19.698586),(104.158169,19.68774),(104.13631,19.687456),(104.131246,19.682443),(104.124476,19.675906),(104.11719,19.660997),(104.109231,19.654874),(104.088716,19.651902),(104.069699,19.658026),(104.021743,19.681435),(104.010271,19.684562),(104.000969,19.680738),(103.995182,19.664899),(103.997662,19.652522),(104.017351,19.600407),(104.028926,19.586041),(104.06019,19.568161),(104.071559,19.559143),(104.077967,19.542891),(104.079259,19.525709),(104.082515,19.509301),(104.093987,19.495633),(104.093987,19.495581),(104.094142,19.495529),(104.094142,19.495478),(104.089956,19.48367),(104.081274,19.479303),(104.070526,19.477029),(104.060501,19.471293),(104.054041,19.46057),(104.049907,19.437471),(104.046548,19.427497),(104.038796,19.41339),(104.03828,19.412925),(104.035127,19.416671),(104.0204,19.414992),(103.99668,19.40693),(103.973994,19.395665),(103.952807,19.390962),(103.941025,19.38135),(103.921284,19.352773),(103.905885,19.341792),(103.870021,19.326883),(103.85674,19.317194),(103.84842,19.299908),(103.858549,19.295335),(103.876739,19.2958),(103.892655,19.293888),(103.905885,19.270039),(103.910949,19.263011),(103.917977,19.258154),(103.943143,19.245596),(103.972754,19.225288),(103.973994,19.225288),(103.995182,19.23384),(104.016162,19.234874),(104.036729,19.230249),(104.14773,19.182887),(104.187831,19.156584),(104.198115,19.146946),(104.201732,19.127051),(104.201836,19.109171),(104.210621,19.100747),(104.239559,19.108886),(104.259603,19.10413),(104.25992,19.104055),(104.274338,19.093461),(104.287257,19.08049),(104.302863,19.068656),(104.321983,19.060466),(104.33914,19.055195),(104.35516,19.047882),(104.372006,19.033568),(104.400738,18.992279),(104.413244,18.983106),(104.431072,18.979334),(104.46213,18.982408),(104.48094,18.977706),(104.497683,18.967991),(104.509879,18.956363),(104.544295,18.906806),(104.556078,18.89647),(104.589667,18.879107),(104.603982,18.868694),(104.631215,18.842365),(104.646201,18.832547),(104.65633,18.829704),(104.675657,18.828206),(104.685579,18.824769),(104.69085,18.819318),(104.702529,18.802471),(104.71028,18.796089),(104.721959,18.792007),(104.762887,18.786451),(104.801644,18.775134),(104.81539,18.773661),(104.872906,18.777976),(104.899364,18.770612),(104.909234,18.745679),(104.919725,18.735576),(104.937243,18.731158),(104.95688,18.731674),(104.97383,18.736067),(104.99016,18.733018),(105.040337,18.705009),(105.064574,18.696638),(105.076976,18.697516),(105.088655,18.700565),(105.100282,18.702064),(105.112684,18.698343),(105.141106,18.653074),(105.162862,18.638993),(105.169477,18.630569),(105.169477,18.618327),(105.169477,18.61486),(105.162087,18.598194),(105.152062,18.596799),(105.140331,18.600468),(105.128136,18.598918),(105.113615,18.580831),(105.100489,18.551169),(105.085244,18.495771),(105.079973,18.454353),(105.090774,18.426525),(105.113976,18.405131),(105.145447,18.383168),(105.162862,18.366012),(105.162242,18.353894),(105.155989,18.340639),(105.156661,18.319839),(105.166169,18.306791),(105.214745,18.277852),(105.220481,18.270798),(105.229266,18.255321),(105.235933,18.249456),(105.246475,18.246381),(105.25692,18.247464),(105.283113,18.250179),(105.288023,18.253409),(105.292518,18.252737),(105.299288,18.24204),(105.300838,18.23093),(105.294379,18.206952),(105.29505,18.195609),(105.305592,18.181062),(105.321871,18.170081),(105.340112,18.162639),(105.355925,18.158738),(105.363315,18.155224),(105.365537,18.151038),(105.368328,18.149953),(105.377474,18.155689),(105.381557,18.162768),(105.386104,18.184938),(105.391995,18.194214),(105.410031,18.201888),(105.431373,18.200544),(105.451423,18.192715),(105.46672,18.180959),(105.472817,18.171993),(105.480879,18.144811),(105.481189,18.138713),(105.479122,18.133494),(105.476848,18.129644),(105.476021,18.127318),(105.480621,18.123649),(105.491989,18.121066),(105.496072,18.118146),(105.512505,18.082825),(105.52067,18.0759),(105.538136,18.066728),(105.546508,18.058951),(105.551882,18.047943),(105.555551,18.025154),(105.559324,18.015336),(105.566145,18.008256),(105.589813,17.99575),(105.589813,17.995595),(105.603431,17.969184),(105.606039,17.964124),(105.594154,17.888108),(105.605212,17.85426),(105.64397,17.820102),(105.669808,17.773076),(105.692029,17.744086),(105.701227,17.727601),(105.713836,17.689464),(105.723086,17.673496),(105.735282,17.664039),(105.787424,17.642077),(105.819876,17.621561),(105.846025,17.597997),(105.911137,17.516813),(105.932169,17.495729),(105.932324,17.495729),(106.019296,17.394495),(106.185435,17.257397),(106.207295,17.246287),(106.221816,17.244892),(106.233391,17.251971),(106.247912,17.266234),(106.252356,17.274554),(106.254785,17.283184),(106.259953,17.28923),(106.272614,17.28985),(106.284551,17.284786),(106.28667,17.276569),(106.285688,17.265976),(106.287961,17.25378),(106.293129,17.246907),(106.306978,17.232954),(106.310544,17.227115),(106.309769,17.217917),(106.301656,17.202),(106.300829,17.191562),(106.306358,17.176524),(106.336537,17.128568),(106.384648,17.085367),(106.394932,17.068003),(106.394363,17.062215),(106.387904,17.051673),(106.387129,17.047178),(106.40402,17.014642),(106.408833,17.005371),(106.411365,16.995811),(106.411365,16.995708),(106.420253,16.98868),(106.437203,16.980463),(106.45653,16.97359),(106.473738,16.970697),(106.496838,16.963927),(106.524536,16.989248),(106.533425,16.97266),(106.53355,16.950638),(106.535078,16.683531),(106.540659,16.659139),(106.549754,16.637797),(106.57244,16.613561),(106.591405,16.60245),(106.611559,16.594595),(106.624943,16.59351),(106.640188,16.586637),(106.644322,16.57532),(106.639671,16.521783),(106.64117,16.510363),(106.655174,16.47083),(106.670677,16.444424),(106.692898,16.427887),(106.722664,16.432486),(106.72256,16.421634),(106.725713,16.417139),(106.732482,16.417552),(106.742404,16.421531),(106.751511,16.428268),(106.752533,16.429024),(106.754393,16.436569),(106.7546,16.444269),(106.759147,16.452485),(106.786122,16.469125),(106.797336,16.47946),(106.801418,16.4961),(106.822864,16.530982),(106.846687,16.530052),(106.86405,16.504058),(106.866841,16.463854),(106.862603,16.430574),(106.861363,16.427887),(106.858211,16.424632),(106.855885,16.420343),(106.855885,16.414658),(106.859865,16.411816),(106.866531,16.414038),(106.872835,16.417345),(106.876298,16.418017),(106.888442,16.390887),(106.897743,16.378536),(106.915003,16.364739),(106.939498,16.351716),(106.946009,16.346135),(106.95066,16.336317),(106.954071,16.313837),(106.956551,16.307068),(106.9673,16.299885),(106.980219,16.298334),(107.014325,16.29942),(107.053393,16.295234),(107.06798,16.290809),(107.070601,16.290015),(107.089101,16.281075),(107.108273,16.267484),(107.116851,16.254616),(107.127497,16.200976),(107.133336,16.188212),(107.13599,16.184784),(107.142018,16.176998),(107.154369,16.166043),(107.169665,16.156896),(107.183204,16.153227),(107.197157,16.151005),(107.212815,16.146664),(107.238808,16.129818),(107.275912,16.084032),(107.298959,16.064189),(107.326864,16.056075),(107.355907,16.059279),(107.41151,16.073077),(107.431044,16.073697),(107.435643,16.068839),(107.433421,16.057367),(107.433292,16.055461),(107.432129,16.038299),(107.436729,16.026878),(107.44355,16.01892),(107.444738,16.00998),(107.432698,15.995924),(107.418022,15.983573),(107.390633,15.935824),(107.375544,15.919081),(107.361074,15.912312),(107.322937,15.905852),(107.305057,15.899134),(107.235656,15.855519),(107.227232,15.853297),(107.218086,15.854796),(107.208835,15.859136),(107.198604,15.862082),(107.186253,15.859395),(107.175246,15.848543),(107.150183,15.794283),(107.148787,15.773457),(107.16026,15.758729),(107.215295,15.727517),(107.225682,15.71682),(107.230023,15.702402),(107.23457,15.660931),(107.239118,15.645119),(107.24873,15.631088),(107.265421,15.61866),(107.303558,15.599747),(107.316426,15.58874),(107.369342,15.496058),(107.381641,15.488539),(107.388669,15.492518),(107.394974,15.501484),(107.405051,15.508589),(107.412234,15.508796),(107.432129,15.503887),(107.437969,15.505592),(107.442981,15.509209),(107.447891,15.508124),(107.453368,15.495954),(107.453368,15.495903),(107.456469,15.488332),(107.46081,15.484379),(107.466546,15.484353),(107.473781,15.488255),(107.487475,15.481408),(107.490162,15.461512),(107.489645,15.437922),(107.493934,15.420042),(107.512641,15.409422),(107.555584,15.415753),(107.573154,15.411231),(107.57636,15.403054),(107.577702,15.39963),(107.579872,15.361234),(107.58659,15.343354),(107.598476,15.330616),(107.643073,15.297853),(107.657594,15.282427),(107.664105,15.268552),(107.664363,15.253153),(107.656818,15.205688),(107.653976,15.199564),(107.647465,15.197652),(107.642607,15.202458),(107.636716,15.205068),(107.62726,15.196515),(107.623591,15.187239),(107.621317,15.154528),(107.615787,15.135511),(107.6054,15.120603),(107.599199,15.114789),(107.584988,15.104299),(107.580492,15.096754),(107.580802,15.086936),(107.590001,15.0689),(107.589071,15.058178),(107.578012,15.047248),(107.562612,15.045801),(107.535224,15.0504),(107.518997,15.04885),(107.502386,15.044037),(107.473781,15.03575),(107.455074,15.034122),(107.445565,15.025389),(107.444687,15.011824),(107.451405,14.995933),(107.449906,14.981102),(107.453937,14.967873),(107.461947,14.956814),(107.473781,14.948236),(107.48949,14.940304),(107.549642,14.895268),(107.558168,14.886715),(107.555326,14.876199),(107.540598,14.856846),(107.498844,14.81765),(107.490885,14.80424),(107.494296,14.788763),(107.504321,14.773182),(107.509282,14.758635),(107.498068,14.745949),(107.504425,14.736285),(107.514657,14.728224),(107.522253,14.718689),(107.520393,14.704582),(107.506905,14.693445),(107.473781,14.646265),(107.458226,14.638798),(107.451766,14.632183),(107.443808,14.609549),(107.440449,14.603916),(107.433266,14.59433),(107.430321,14.586243),(107.429752,14.578336),(107.430941,14.569887),(107.430941,14.561386),(107.42784,14.553712),(107.414921,14.543429),(107.403449,14.543894),(107.380143,14.554048),(107.361384,14.557924),(107.351566,14.561619),(107.332704,14.578233),(107.305677,14.597224),(107.28728,14.598516),(107.272191,14.585364),(107.254517,14.560973),(107.249453,14.556632),(107.237878,14.549811),(107.233899,14.544927),(107.2324,14.538313),(107.230281,14.518262),(107.219739,14.497979),(107.211213,14.493458),(107.195968,14.495964),(107.195813,14.495964),(107.195606,14.496067),(107.195503,14.496119),(107.180568,14.496171),(107.172455,14.484259),(107.166823,14.467154),(107.158709,14.451522),(107.131424,14.427544),(107.10078,14.407623),(107.078559,14.400776),(107.067862,14.406124),(107.059336,14.418036),(107.042954,14.430722),(107.030345,14.436097),(107.027245,14.43527),(107.026573,14.430231),(106.997376,14.395143),(106.977945,14.365429),(106.973656,14.363026),(106.961099,14.360391),(106.950143,14.334863),(106.94973,14.328661),(106.946113,14.32352),(106.933607,14.320161),(106.923478,14.321918),(106.904771,14.333312),(106.895676,14.33631),(106.885083,14.335534),(106.879295,14.332692),(106.874592,14.328351),(106.835835,14.307061),(106.820849,14.307577),(106.806896,14.312926),(106.792995,14.322589),(106.766692,14.348324),(106.731655,14.396719),(106.723904,14.411602),(106.719253,14.417881),(106.711502,14.425839),(106.707161,14.429301),(106.6344,14.450902),(106.622049,14.457594),(106.605358,14.466637),(106.585669,14.495964),(106.575386,14.50201),(106.552441,14.506945),(106.54376,14.512113),(106.540246,14.521673),(106.534975,14.553247),(106.530996,14.56596),(106.518438,14.585002),(106.512496,14.590351),(106.49105,14.570998),(106.483763,14.567484),(106.477149,14.56689),(106.47224,14.564073),(106.470586,14.554255),(106.470948,14.544643),(106.47317,14.537486),(106.477511,14.532602),(106.484849,14.530019),(106.484849,14.523817),(106.469449,14.524696),(106.456685,14.5279),(106.445781,14.529088),(106.43648,14.523817),(106.434309,14.519606),(106.432655,14.512423),(106.433586,14.505705),(106.445161,14.499478),(106.44082,14.492631),(106.433482,14.486636),(106.429503,14.485964),(106.41922,14.466457),(106.393795,14.456173),(106.339999,14.448988),(106.333437,14.448111),(106.320156,14.444494),(106.306462,14.445476),(106.296746,14.447879),(106.235975,14.484362),(106.230084,14.49046),(106.220782,14.473485),(106.210654,14.421395),(106.203936,14.399897),(106.189156,14.378891),(106.17324,14.369667),(106.15412,14.367548),(106.119031,14.369512),(106.095002,14.373646),(106.079447,14.372716),(106.068647,14.373439),(106.063531,14.372922),(106.060585,14.36884),(106.058105,14.353104),(106.055418,14.348428),(106.038158,14.347652),(105.994129,14.362406),(105.973975,14.365843),(105.969428,14.354861),(105.967826,14.343363),(105.96917,14.33202),(105.973975,14.321298),(105.993406,14.30595),(106.004516,14.289982),(106.007979,14.270758),(106.004051,14.245927),(106.012474,14.225774),(106.026272,14.213035),(106.060585,14.191848),(106.076191,14.174511),(106.10172,14.11516),(106.115259,14.100303),(106.131279,14.086997),(106.144559,14.072398),(106.149469,14.053562),(106.142079,14.03501),(106.126421,14.022013),(106.108489,14.01036),(106.094071,13.996175),(106.081979,13.980957),(106.08384,13.934008),(106.069163,13.916542),(106.049216,13.915457),(105.997437,13.928298),(105.973975,13.92928),(105.949171,13.919591),(105.924573,13.91711),(105.899665,13.922614),(105.895581,13.924799),(105.873051,13.936851),(105.787113,14.010154),(105.770164,14.0347),(105.758898,14.062476),(105.744015,14.086945),(105.716007,14.101543),(105.705155,14.102009),(105.683657,14.098856),(105.669343,14.100407),(105.653272,14.107047),(105.643143,14.113455),(105.632911,14.114023),(105.617253,14.10299),(105.609863,14.120741),(105.594567,14.136348),(105.576532,14.144022),(105.561391,14.138156),(105.555551,14.146089),(105.548937,14.153117),(105.541237,14.159189),(105.533175,14.16433),(105.50527,14.145055),(105.490491,14.136916),(105.473851,14.132523),(105.45008,14.11715),(105.422175,14.107874),(105.392461,14.10374),(105.36409,14.10405),(105.347864,14.106065),(105.337787,14.109993),(105.329467,14.117563),(105.303939,14.152393),(105.296601,14.156837),(105.282183,14.161256),(105.27531,14.164821),(105.256913,14.182443),(105.197434,14.270293),(105.187977,14.291015),(105.184256,14.314166),(105.184308,14.34574),(105.198209,14.345224),(105.250454,14.357187),(105.268592,14.36437),(105.275724,14.372095),(105.287712,14.393283),(105.29474,14.399071),(105.304662,14.398192),(105.322232,14.386384),(105.3351,14.385712),(105.340836,14.390105),(105.359646,14.408269),(105.367656,14.414548),(105.379231,14.418242),(105.40569,14.423048),(105.415973,14.428164),(105.420314,14.435218),(105.428892,14.458163),(105.433853,14.467929),(105.440365,14.475345),(105.463671,14.495964),(105.495452,14.537124),(105.507544,14.564048),(105.510128,14.593581),(105.495762,14.659881),(105.497364,14.690422),(105.505115,14.736363),(105.50155,14.745949),(105.490697,14.763803),(105.489147,14.786334),(105.49385,14.808994),(105.50155,14.827339),(105.5062,14.830414),(105.52005,14.833463),(105.524391,14.837235),(105.52408,14.842532),(105.516949,14.856536),(105.515864,14.871677),(105.517776,14.877672),(105.52191,14.878705),(105.53762,14.878034),(105.543046,14.880101),(105.550642,14.902296),(105.534157,14.934025),(105.543924,14.953094),(105.58356,14.977588),(105.593068,14.990792),(105.566455,14.995933),(105.566352,14.995933),(105.566145,14.995933),(105.566145,14.995985),(105.553536,15.005338),(105.524287,15.045956),(105.52284,15.050039),(105.52315,15.061175),(105.520877,15.066136),(105.516536,15.067143),(105.503565,15.064896),(105.498294,15.066136),(105.473851,15.09063),(105.45194,15.094765),(105.44362,15.111353),(105.443775,15.133806),(105.447703,15.155303),(105.454421,15.175535),(105.463102,15.189436),(105.503927,15.231061),(105.531574,15.252894),(105.560254,15.270929),(105.563975,15.272531),(105.564801,15.299455),(105.561494,15.320901),(105.558032,15.325138),(105.53855,15.321521),(105.519378,15.321056),(105.499017,15.324673),(105.483308,15.334517),(105.477468,15.352811),(105.486253,15.374902),(105.5062,15.387589),(105.552813,15.402033),(105.588366,15.423788),(105.592243,15.427546),(105.604282,15.439214),(105.61038,15.457171),(105.612034,15.499468),(105.616271,15.521276),(105.640869,15.583313),(105.650998,15.634602),(105.640921,15.68199),(105.612912,15.72147),(105.568522,15.749376),(105.525424,15.763483),(105.50341,15.766171),(105.462379,15.762812),(105.447961,15.764879),(105.435662,15.771648),(105.423001,15.783896),(105.412046,15.79976),(105.372565,15.882132),(105.360628,15.919391),(105.362488,15.95479),(105.386518,15.980783),(105.407395,15.988896),(105.418144,15.994735),(105.423932,16.002125),(105.423232,16.00504),(105.422071,16.009877),(105.414475,16.015199),(105.404915,16.018817),(105.288539,16.047394),(105.247405,16.049151),(105.237225,16.050804),(105.106979,16.095853),(105.079301,16.105426),(105.058114,16.121188),(105.042456,16.141445),(105.032586,16.165268),(105.028865,16.191468),(105.029744,16.236013),(105.026385,16.257665),(105.015481,16.276734),(105.007419,16.283555),(104.988028,16.293963),(104.979307,16.298645),(104.971504,16.304329),(104.952074,16.324431),(104.944064,16.330839),(104.917296,16.345567),(104.908046,16.35337),(104.901586,16.362465),(104.897039,16.372749),(104.887737,16.403909),(104.879469,16.421841),(104.868927,16.438429),(104.855491,16.454087),(104.838851,16.46773),(104.78273,16.497082),(104.76516,16.511345),(104.754515,16.528915),(104.749502,16.549327),(104.748417,16.571909),(104.753016,16.614801),(104.763713,16.656762),(104.777563,16.694021),(104.77901,16.704873),(104.778338,16.715828),(104.756789,16.798459),(104.756324,16.809879),(104.75791,16.818895),(104.758442,16.82192),(104.765212,16.844658),(104.767072,16.85613),(104.766401,16.86817),(104.762887,16.879074),(104.753016,16.899848),(104.749657,16.910804),(104.74634,16.943532),(104.740356,17.002581),(104.745317,17.024802),(104.809912,17.171666),(104.81446,17.194042),(104.818335,17.240241),(104.816423,17.300082),(104.819989,17.348916),(104.819317,17.36106),(104.816423,17.372791),(104.792704,17.423485),(104.788932,17.428963),(104.781645,17.435268),(104.764644,17.444414),(104.756789,17.449944),(104.749657,17.45816),(104.734258,17.486892),(104.714517,17.515263),(104.702632,17.527303),(104.65509,17.556087),(104.636383,17.562443),(104.481198,17.640423),(104.452001,17.665951),(104.422287,17.699799),(104.417843,17.707602),(104.411642,17.727395),(104.408903,17.733699),(104.404872,17.739952),(104.3903,17.75716),(104.367769,17.800568),(104.352627,17.819327),(104.287567,17.856741),(104.281982,17.861488),(104.278265,17.864647),(104.270307,17.874001),(104.264312,17.884646),(104.255114,17.91498),(104.210879,18.008618),(104.203329,18.018644),(104.198115,18.025568),(104.13569,18.079673),(104.122357,18.095279),(104.110937,18.114554),(104.068407,18.215401),(104.018643,18.299117),(104.000039,18.318444),(103.975441,18.330665),(103.951257,18.332991),(103.929294,18.32759),(103.910019,18.315317),(103.893689,18.297256),(103.889503,18.291159),(103.885938,18.286999),(103.881287,18.284415),(103.873949,18.283226),(103.857774,18.286482),(103.848989,18.296352),(103.842219,18.309116),(103.832091,18.320666),(103.81726,18.330355),(103.801395,18.338262),(103.7846,18.343894),(103.767185,18.346685),(103.709101,18.349708),(103.695562,18.353222),(103.638614,18.377949),(103.629932,18.38322),(103.621354,18.390765),(103.607143,18.400403),(103.5488,18.415415),(103.523169,18.417688),(103.497744,18.423734),(103.489114,18.424432),(103.4748,18.422158),(103.469942,18.421977),(103.451545,18.425311),(103.396768,18.441408),(103.38664,18.441459),(103.306851,18.425672),(103.282564,18.41557),(103.260756,18.400196),(103.244065,18.380068),(103.233988,18.35578),(103.233678,18.349269),(103.235331,18.345264),(103.238018,18.341569),(103.240189,18.335988),(103.248664,18.332629),(103.290418,18.305137),(103.296516,18.296895),(103.295379,18.287774),(103.286336,18.280332),(103.27352,18.276069),(103.236727,18.269997),(103.214919,18.262297),(103.185205,18.25775),(103.17673,18.254856),(103.168204,18.249766),(103.1573,18.237027),(103.150892,18.221499),(103.145104,18.188012),(103.138593,18.166722),(103.126656,18.151865),(103.110068,18.141814),(103.089087,18.134786),(103.089404,18.135223),(103.090087,18.136165),(103.090586,18.136853),(103.092756,18.141194),(103.092133,18.140882),(103.087703,18.138667),(103.07994,18.134786),(103.07131,18.125561),(103.066349,18.112255),(103.064799,18.094039),(103.073067,18.035515),(103.06821,18.025774),(103.058288,18.019263),(103.049399,18.005),(103.037927,17.990686),(103.020461,17.984226),(103.003821,17.988567),(102.972918,18.007739),(102.954935,18.012132),(102.938605,18.008928),(102.852719,17.972031),(102.838043,17.963763),(102.831893,17.953117),(102.774067,17.922731),(102.737377,17.890434),(102.722184,17.881804),(102.686734,17.873535),(102.672988,17.865371),(102.667614,17.850074),(102.67335,17.831781),(102.68291,17.817363),(102.68291,17.810077),(102.660793,17.812867),(102.609426,17.837),(102.595267,17.840824),(102.595577,17.850074),(102.61232,17.91529),(102.599608,17.955184),(102.567517,17.970842),(102.482044,17.971152),(102.445509,17.977767),(102.412229,17.9942),(102.385151,18.016059),(102.366392,18.038797),(102.336523,18.03704),(102.306706,18.051457),(102.25658,18.094039),(102.233119,18.124166),(102.225574,18.128197),(102.221801,18.131608),(102.191571,18.152071),(102.182114,18.169228),(102.178393,18.185971),(102.171934,18.200286),(102.153537,18.210104),(102.107385,18.212377),(102.078503,18.213799),(102.071268,18.208502),(102.055527,18.192345),(101.904301,18.037117),(101.883786,18.030839),(101.845184,18.052129),(101.806064,18.062387),(101.796659,18.073575),(101.790407,18.073575),(101.773922,18.058563),(101.765757,18.040321),(101.75692,17.997817),(101.732581,17.932033),(101.729067,17.912189),(101.636204,17.894826),(101.619874,17.884646),(101.611141,17.865526),(101.600392,17.854364),(101.577551,17.868109),(101.577551,17.852917),(101.575071,17.839791),(101.570523,17.828887),(101.564012,17.820309),(101.545505,17.813672),(101.53404,17.80956),(101.556261,17.792145),(101.53652,17.779123),(101.502724,17.765377),(101.482983,17.745791),(101.479004,17.737988),(101.474198,17.730598),(101.470426,17.722589),(101.468307,17.720367),(101.459109,17.739487),(101.457352,17.745791),(101.45606,17.750184),(101.453476,17.751011),(101.449807,17.749254),(101.44526,17.745791),(101.43203,17.733596),(101.416993,17.732355),(101.401851,17.733751),(101.388002,17.729307),(101.381904,17.720728),(101.388364,17.717783),(101.398751,17.717163),(101.404022,17.715561),(101.403092,17.709463),(101.401593,17.706672),(101.383765,17.684916),(101.37746,17.682643),(101.369864,17.683159),(101.357306,17.679025),(101.247029,17.592157),(101.228632,17.568489),(101.20853,17.531282),(101.202174,17.523169),(101.190288,17.518725),(101.176956,17.5164),(101.166724,17.510612),(101.164243,17.495781),(101.164243,17.495729),(101.14719,17.472475),(101.141816,17.467152),(101.132307,17.461674),(101.128897,17.461158),(101.124659,17.463948),(101.09603,17.475265),(101.066161,17.492215),(101.049315,17.495729),(101.035466,17.512627),(101.019032,17.526632),(101.000842,17.538207),(100.981515,17.547612),(100.937738,17.555486),(100.901934,17.561927),(100.886017,17.57376),(100.885656,17.595878),(100.899453,17.616962),(100.932939,17.654531),(100.953817,17.699799),(100.955878,17.707532),(100.96069,17.725586),(100.958726,17.745791),(100.956401,17.75592),(100.958571,17.764136),(100.964876,17.770596),(100.974281,17.775505),(100.975211,17.777624),(100.975521,17.779794),(100.975211,17.781913),(100.974281,17.78398),(100.967718,17.791008),(100.965186,17.797623),(100.967046,17.803824),(100.974281,17.80925),(100.994796,17.817725),(101.000274,17.830489),(100.997122,17.864595),(101.000842,17.884801),(101.008284,17.89524),(101.039806,17.912034),(101.066161,17.933997),(101.081974,17.958336),(101.094893,17.984381),(101.112308,18.011305),(101.125434,18.02133),(101.157525,18.04045),(101.165173,18.053421),(101.162073,18.067451),(101.144968,18.104736),(101.141609,18.123959),(101.14564,18.141943),(101.160523,18.179512),(101.162796,18.195299),(101.159282,18.204058),(101.152771,18.209071),(101.145536,18.212998),(101.139645,18.218708),(101.131739,18.238862),(101.12838,18.245735),(101.127966,18.280952),(101.130137,18.291159),(101.135408,18.298393),(101.152409,18.316377),(101.155407,18.322888),(101.145536,18.336246),(101.082284,18.364203),(101.074089,18.371613),(101.05102,18.39247),(101.037016,18.410454),(101.030298,18.427791),(101.035621,18.447841),(101.064714,18.476419),(101.071949,18.495668),(101.073809,18.505771),(101.077892,18.510422),(101.142074,18.544296),(101.155355,18.556724),(101.159127,18.567705),(101.158145,18.589978),(101.160884,18.599796),(101.167757,18.606359),(101.185327,18.612534),(101.194112,18.616798),(101.221914,18.642042),(101.23473,18.658449),(101.240104,18.673642),(101.234782,18.68948),(101.211269,18.711908),(101.205843,18.730072),(101.209202,18.746325),(101.223981,18.778545),(101.228632,18.795624),(101.223309,18.855491),(101.224911,18.874766),(101.232921,18.892724),(101.257261,18.919492),(101.267286,18.934453),(101.277001,18.96706),(101.283926,18.981478),(101.326404,19.020546),(101.317877,19.05013),(101.291161,19.078992),(101.247442,19.115785),(101.235712,19.12811),(101.229149,19.143587),(101.226772,19.167152),(101.229872,19.225804),(101.209512,19.309417),(101.209253,19.315592),(101.210907,19.320631),(101.211269,19.326367),(101.207755,19.334687),(101.201967,19.338666),(101.185017,19.341999),(101.178454,19.346624),(101.172356,19.376389),(101.177782,19.417214),(101.192872,19.452793),(101.2153,19.466358),(101.238244,19.472301),(101.251731,19.494444),(101.256951,19.522789),(101.254884,19.547154),(101.25106,19.560306),(101.246202,19.570279),(101.238244,19.578186),(101.225015,19.585214),(101.207961,19.589555),(101.197316,19.586868),(101.188324,19.580744),(101.176852,19.574749),(101.152668,19.568367),(101.124659,19.565112),(101.095824,19.567282),(101.068228,19.577127),(101.024303,19.602861),(101.002548,19.610613),(100.974281,19.613481),(100.885656,19.612447),(100.879816,19.613584),(100.874597,19.612912),(100.865037,19.607151),(100.861213,19.602603),(100.849017,19.582527),(100.808451,19.536535),(100.762614,19.495478),(100.753002,19.48243),(100.745509,19.485013),(100.738171,19.495039),(100.729231,19.50465),(100.714762,19.512454),(100.633268,19.542167),(100.607016,19.540927),(100.585984,19.525967),(100.574758,19.508347),(100.566657,19.495633),(100.549294,19.494548),(100.520613,19.502609),(100.491829,19.514469),(100.474259,19.524985),(100.46196,19.537103),(100.458963,19.551831),(100.458963,19.568057),(100.455553,19.584671),(100.447491,19.597771),(100.427079,19.621801),(100.418862,19.634358),(100.41292,19.651566),(100.410491,19.684252),(100.407235,19.699936),(100.400466,19.71164),(100.390048,19.724387),(100.383826,19.732001),(100.379175,19.745669),(100.383516,19.763859),(100.407659,19.794257),(100.420516,19.810446),(100.43142,19.838273),(100.438448,19.847213),(100.446251,19.852123),(100.46563,19.859771),(100.474259,19.865352),(100.483975,19.8807),(100.487954,19.896978),(100.492656,19.931653),(100.518546,19.995421),(100.518546,19.995499),(100.543351,20.06658),(100.550586,20.106526),(100.548674,20.158021),(100.546503,20.167917),(100.541956,20.166729),(100.536685,20.153474),(100.529243,20.149727),(100.51281,20.155282),(100.496377,20.164868),(100.488936,20.173343),(100.485628,20.178769),(100.468782,20.18572),(100.46103,20.190707),(100.45731,20.196391),(100.452142,20.21024),(100.447336,20.218044),(100.421601,20.250186),(100.364395,20.368965),(100.344345,20.389971),(100.306518,20.399686),(100.270241,20.391831),(100.240372,20.372814),(100.220683,20.348992),(100.209159,20.312999),(100.207196,20.311139),(100.201718,20.310312),(100.179497,20.302483),(100.176397,20.300622),(100.167095,20.292613),(100.167715,20.253623),(100.152522,20.239153),(100.134642,20.239102),(100.116607,20.248016),(100.102964,20.263596),(100.09728,20.283233),(100.099295,20.317805),(100.097642,20.334936),(100.097073,20.348371),(100.099812,20.362221),(100.111129,20.37483),(100.120948,20.388782),(100.125237,20.406404),(100.127407,20.42785),(100.136657,20.459217),(100.149266,20.548101),(100.160067,20.582672),(100.172934,20.609079),(100.172934,20.622102),(100.180169,20.638173),(100.202338,20.667939),(100.207196,20.680754),(100.21133,20.697394),(100.221613,20.70959),(100.248744,20.731966),(100.27453,20.76199),(100.290188,20.775012),(100.329669,20.786019),(100.341968,20.799507),(100.351115,20.81532),(100.364809,20.828187),(100.383671,20.831701),(100.470849,20.818265),(100.513379,20.807),(100.536685,20.807672),(100.569034,20.8178),(100.598903,20.833458),(100.607776,20.839881),(100.626602,20.853509),(100.65213,20.876608),(100.65213,20.882757),(100.623088,20.888545),(100.534204,20.873921),(100.515704,20.886478),(100.517823,20.906322),(100.527073,20.94694),(100.529243,20.968437),(100.533274,20.97345),(100.551981,20.985335),(100.557252,20.992001),(100.555753,20.999856),(100.543454,21.0274),(100.561851,21.0351),(100.606758,21.043936),(100.625516,21.054117),(100.637557,21.069671),(100.689388,21.15933),(100.721066,21.280666),(100.722565,21.292707),(100.721996,21.303662),(100.725407,21.311672),(100.738378,21.314772),(100.747731,21.314256),(100.756671,21.312447),(100.764991,21.309191),(100.772588,21.30423),(100.791966,21.297357),(100.8146,21.3002),(100.851342,21.314772),(100.862453,21.323299),(100.896043,21.355752),(100.909943,21.360093),(101.003426,21.405981),(101.143159,21.513417),(101.157112,21.519669),(101.161143,21.534707),(101.159024,21.552691),(101.174527,21.551657),(101.186567,21.535327),(101.187756,21.505872),(101.168274,21.424533),(101.171426,21.403398),(101.179126,21.398178),(101.207961,21.383502),(101.226462,21.370893),(101.230802,21.371772),(101.233128,21.37172),(101.234782,21.363658),(101.222844,21.335081),(101.207445,21.314824),(101.209512,21.308675),(101.2184,21.299941),(101.220364,21.296272),(101.219072,21.282475),(101.208995,21.245526),(101.220364,21.233692),(101.234782,21.206252),(101.244342,21.192868),(101.259741,21.179484),(101.275296,21.174109),(101.292711,21.176073),(101.313898,21.184755),(101.362267,21.215812),(101.381491,21.222478),(101.495127,21.242839),(101.517607,21.242632),(101.539104,21.23886),(101.5729,21.228163),(101.57967,21.227594),(101.583959,21.22439),(101.588197,21.213332),(101.586646,21.204237),(101.580962,21.194728),(101.577241,21.185168),(101.581789,21.175659),(101.596517,21.173386),(101.635946,21.189457),(101.655118,21.189199),(101.670155,21.177055),(101.688294,21.145842),(101.704262,21.135093),(101.717905,21.134473),(101.73749,21.137574),(101.75599,21.143258),(101.766739,21.150648),(101.768453,21.16045),(101.770201,21.17044),(101.763586,21.184651),(101.760072,21.195968),(101.77356,21.207389),(101.796039,21.202945),(101.805238,21.204495),(101.813299,21.209559),(101.819294,21.215967),(101.82149,21.221071),(101.822808,21.224132),(101.823738,21.234467),(101.820224,21.247283),(101.812266,21.258135),(101.801155,21.267075),(101.788546,21.274206),(101.736508,21.292293),(101.722504,21.30423),(101.715114,21.321129),(101.715579,21.338182),(101.725553,21.375389),(101.729687,21.474246),(101.744259,21.495588),(101.748239,21.514502),(101.734751,21.554396),(101.736198,21.570881),(101.750926,21.579666),(101.772682,21.582508),(101.793559,21.588244),(101.806168,21.605969),(101.803842,21.625916),(101.789528,21.634029),(101.770821,21.638835),(101.755938,21.648654),(101.752321,21.659144),(101.755628,21.680021),(101.754801,21.689788),(101.749117,21.698057),(101.732787,21.711441),(101.72855,21.717539),(101.727981,21.73268),(101.73165,21.750508),(101.751546,21.80637),(101.751081,21.816137),(101.726173,21.837273),(101.721263,21.844353),(101.708706,21.869571),(101.685865,21.898613),(101.683075,21.907139),(101.682454,21.914839),(101.680594,21.922642),(101.673669,21.931376),(101.638116,21.940884),(101.616309,21.953648),(101.6068,21.967601),(101.600392,22.007495),(101.592176,22.028114),(101.564942,22.069507),(101.555434,22.090332),(101.55502,22.112398),(101.561842,22.130072),(101.566958,22.149347),(101.561532,22.176115),(101.549026,22.19353),(101.518227,22.228205),(101.515746,22.245362),(101.531714,22.263397),(101.540654,22.271458),(101.55099,22.276678),(101.563702,22.276781),(101.575743,22.273112),(101.58799,22.271355),(101.601219,22.276988),(101.606128,22.284842),(101.619874,22.326442),(101.62251,22.342358),(101.623698,22.346647),(101.641113,22.363287),(101.643697,22.364683),(101.645713,22.384526),(101.644162,22.404008),(101.645092,22.424214),(101.654549,22.446125),(101.668657,22.462299),(101.689121,22.478887),(101.71315,22.491548),(101.741779,22.496044),(101.750616,22.496044),(101.75506,22.495527),(101.784877,22.472221),(101.817795,22.406334),(101.8426,22.383338),(101.867921,22.378842)] +Lebanon [(36.391194,34.622487),(36.415999,34.622901),(36.440184,34.62936),(36.436256,34.597838),(36.429125,34.593187),(36.418479,34.600318),(36.4037,34.603832),(36.388921,34.596236),(36.386853,34.584247),(36.388094,34.569519),(36.383546,34.553809),(36.364012,34.541097),(36.336624,34.52885),(36.319881,34.514122),(36.329851,34.498603),(36.332697,34.494175),(36.335384,34.493477),(36.338174,34.493296),(36.340965,34.493477),(36.343652,34.494175),(36.363082,34.499032),(36.392331,34.500143),(36.41972,34.498335),(36.433466,34.49433),(36.433466,34.494175),(36.439873,34.477457),(36.449795,34.464538),(36.463231,34.455237),(36.480181,34.449139),(36.494651,34.434256),(36.501885,34.430303),(36.509223,34.432421),(36.52514,34.422939),(36.530617,34.41418),(36.52979,34.403095),(36.526276,34.386688),(36.523589,34.379789),(36.519972,34.375061),(36.516768,34.369867),(36.515941,34.36165),(36.518628,34.353641),(36.523589,34.345889),(36.54519,34.320723),(36.555835,34.311085),(36.562967,34.308501),(36.570305,34.308966),(36.576816,34.307674),(36.581984,34.299897),(36.579917,34.286901),(36.570305,34.275868),(36.56276,34.262949),(36.567514,34.244138),(36.574026,34.229746),(36.59821,34.209851),(36.603554,34.200101),(36.604101,34.199102),(36.575886,34.173264),(36.552735,34.140992),(36.507983,34.109185),(36.488449,34.088644),(36.482662,34.07451),(36.480698,34.062754),(36.47522,34.053504),(36.45889,34.046708),(36.445144,34.04614),(36.423647,34.052806),(36.412175,34.053633),(36.391091,34.044719),(36.357811,34.009553),(36.31802,33.980511),(36.302311,33.964388),(36.288565,33.946508),(36.267171,33.910386),(36.268928,33.906769),(36.275336,33.897209),(36.28164,33.891111),(36.311096,33.87199),(36.35037,33.866409),(36.36763,33.857547),(36.369594,33.837006),(36.357501,33.823776),(36.338278,33.821193),(36.300554,33.828686),(36.249187,33.849744),(36.231824,33.852534),(36.216631,33.847754),(36.202679,33.838297),(36.186556,33.83021),(36.165678,33.829797),(36.157617,33.83406),(36.144904,33.847418),(36.13829,33.850622),(36.102426,33.832277),(36.085063,33.82605),(36.06646,33.821994),(36.05044,33.816438),(36.040518,33.805612),(36.027082,33.784296),(35.994009,33.760705),(35.980263,33.743549),(35.974165,33.732154),(35.955872,33.718124),(35.948431,33.70921),(35.946984,33.700838),(35.949878,33.6827),(35.94719,33.673088),(35.942436,33.669212),(35.929414,33.665078),(35.925383,33.661667),(35.921559,33.640299),(35.934788,33.6334),(35.956906,33.629938),(35.980263,33.619008),(35.994526,33.615701),(36.012923,33.608027),(36.029666,33.59764),(36.038451,33.586349),(36.035247,33.567797),(36.019847,33.55263),(35.99928,33.541261),(35.980263,33.533949),(35.956802,33.534207),(35.933238,33.527825),(35.921869,33.51457),(35.935408,33.494262),(35.919492,33.462351),(35.888486,33.440415),(35.870089,33.431242),(35.845116,33.418742),(35.8211,33.406722),(35.8057,33.391348),(35.785753,33.357887),(35.769423,33.342643),(35.757538,33.336313),(35.743689,33.331171),(35.729426,33.327812),(35.716197,33.326727),(35.698523,33.32267),(35.66049,33.289261),(35.640542,33.275851),(35.624716,33.272924),(35.610363,33.27027),(35.601475,33.262725),(35.604576,33.244354),(35.604576,33.244303),(35.604576,33.244251),(35.603892,33.240323),(35.603852,33.240091),(35.598064,33.244251),(35.597858,33.24438),(35.597754,33.244354),(35.585042,33.252209),(35.566955,33.276187),(35.561167,33.28213),(35.549489,33.281019),(35.542771,33.271536),(35.53688,33.257868),(35.527784,33.244251),(35.520033,33.222185),(35.517656,33.172886),(35.512282,33.147409),(35.503703,33.130615),(35.4851,33.102606),(35.480139,33.087387),(35.449443,33.085217),(35.401591,33.067931),(35.34516,33.05558),(35.331931,33.057156),(35.322629,33.067363),(35.315704,33.079222),(35.305783,33.089377),(35.29462,33.096973),(35.288825,33.099201),(35.283665,33.101185),(35.271469,33.101185),(35.234469,33.090927),(35.227338,33.091366),(35.213178,33.094441),(35.207184,33.094803),(35.200673,33.092736),(35.189614,33.085527),(35.185273,33.083977),(35.105235,33.089016),(35.105235,33.090644),(35.106456,33.095038),(35.101899,33.094468),(35.100434,33.095689),(35.100434,33.098212),(35.09962,33.101264),(35.105805,33.112454),(35.114757,33.123725),(35.125499,33.132514),(35.147634,33.140326),(35.154796,33.150295),(35.160981,33.161689),(35.167817,33.170152),(35.161794,33.176947),(35.167817,33.177883),(35.171072,33.176581),(35.174653,33.170152),(35.204763,33.224799),(35.209158,33.254625),(35.188324,33.280015),(35.209727,33.293402),(35.224783,33.311998),(35.243663,33.355699),(35.246104,33.368883),(35.246755,33.395819),(35.250499,33.409735),(35.268728,33.432603),(35.275076,33.444973),(35.271007,33.457506),(35.323009,33.490912),(35.349132,33.513861),(35.360362,33.543443),(35.362478,33.556342),(35.400645,33.643134),(35.394379,33.64997),(35.409923,33.661282),(35.421641,33.702338),(35.438487,33.711371),(35.437836,33.723375),(35.477306,33.8039),(35.481293,33.823676),(35.483002,33.86518),(35.483246,33.872463),(35.479991,33.884263),(35.473806,33.893866),(35.47047,33.902086),(35.475841,33.90998),(35.486583,33.912991),(35.499766,33.9112),(35.511241,33.90705),(35.517345,33.902533),(35.524181,33.902533),(35.533865,33.90705),(35.548106,33.906195),(35.557465,33.905666),(35.572032,33.90998),(35.57838,33.916693),(35.587901,33.936591),(35.59311,33.94477),(35.593435,33.94892),(35.59197,33.950426),(35.585704,33.950914),(35.594249,33.959296),(35.606293,33.983222),(35.613536,33.99315),(35.620128,33.995103),(35.636729,33.995307),(35.64088,33.999416),(35.640391,34.008531),(35.635753,34.013251),(35.630382,34.016099),(35.627208,34.019843),(35.626964,34.044257),(35.643321,34.08808),(35.647716,34.119127),(35.644542,34.130845),(35.630382,34.152818),(35.627208,34.166938),(35.627208,34.201117),(35.630382,34.208441),(35.644542,34.216986),(35.647716,34.222154),(35.648285,34.253607),(35.653005,34.284857),(35.665212,34.311347),(35.688731,34.328315),(35.705821,34.316596),(35.722179,34.33747),(35.737315,34.369208),(35.750743,34.389797),(35.806163,34.414984),(35.823578,34.434516),(35.805431,34.458686),(35.805431,34.464911),(35.823985,34.460842),(35.903331,34.477973),(35.956798,34.520087),(35.972911,34.529771),(35.983165,34.538642),(35.98878,34.55272),(35.989594,34.599677),(35.986827,34.620795),(35.980642,34.638495),(35.9699,34.649848),(35.9699,34.649849),(35.98264,34.650238),(35.991425,34.648222),(35.998763,34.64538),(36.01623,34.633649),(36.037934,34.62843),(36.060775,34.627913),(36.087234,34.631014),(36.11214,34.629532),(36.15586,34.626931),(36.160201,34.628068),(36.17219,34.634063),(36.178287,34.635303),(36.183352,34.633494),(36.195134,34.626208),(36.201232,34.624451),(36.26159,34.627242),(36.271512,34.630962),(36.28071,34.639127),(36.284431,34.648326),(36.284844,34.667911),(36.288151,34.675559),(36.308925,34.687548),(36.323808,34.679486),(36.347373,34.64414),(36.367526,34.629205),(36.391194,34.622487)] +Liberia [(-9.722115,8.435636),(-9.718188,8.438272),(-9.717981,8.452689),(-9.7155,8.473334),(-9.703253,8.487261),(-9.683513,8.487054),(-9.663514,8.477856),(-9.650543,8.464807),(-9.645117,8.443413),(-9.653385,8.43145),(-9.666511,8.422381),(-9.675916,8.409643),(-9.67726,8.39153),(-9.668372,8.38874),(-9.653385,8.392099),(-9.636125,8.392564),(-9.628064,8.391634),(-9.619537,8.392719),(-9.612148,8.396336),(-9.607342,8.402925),(-9.600159,8.410883),(-9.592045,8.405095),(-9.579178,8.387293),(-9.529052,8.366312),(-9.511482,8.353781),(-9.504351,8.346158),(-9.499131,8.343471),(-9.511482,8.336133),(-9.515616,8.334376),(-9.522282,8.330681),(-9.528483,8.32572),(-9.539387,8.314584),(-9.530189,8.30598),(-9.525124,8.295438),(-9.521249,8.284405),(-9.515616,8.274406),(-9.510758,8.270065),(-9.509156,8.265595),(-9.51081,8.261047),(-9.515616,8.256603),(-9.525435,8.24079),(-9.531894,8.212316),(-9.530137,8.185496),(-9.515616,8.174877),(-9.491328,8.169968),(-9.481406,8.164697),(-9.478099,8.152785),(-9.478047,8.141287),(-9.459805,8.068785),(-9.461873,8.058424),(-9.472776,8.040363),(-9.474223,8.028813),(-9.462183,8.043464),(-9.451537,8.051758),(-9.440944,8.050569),(-9.429265,8.036901),(-9.424149,8.026178),(-9.42234,8.015791),(-9.424562,8.005817),(-9.431745,7.996567),(-9.433093,7.993468),(-9.446008,7.950058),(-9.448437,7.907839),(-9.43867,7.866239),(-9.415674,7.824433),(-9.389681,7.791464),(-9.380999,7.77441),(-9.355471,7.741906),(-9.366374,7.716171),(-9.376245,7.680566),(-9.374694,7.646925),(-9.353507,7.62243),(-9.364411,7.614265),(-9.372989,7.601346),(-9.378777,7.586256),(-9.38366,7.55954),(-9.390817,7.548223),(-9.408697,7.527449),(-9.404925,7.513599),(-9.4134,7.492257),(-9.436086,7.458564),(-9.456705,7.443061),(-9.466213,7.433449),(-9.470244,7.420995),(-9.470864,7.407353),(-9.4735,7.39557),(-9.479701,7.38539),(-9.490708,7.376037),(-9.487099,7.373204),(-9.486626,7.372833),(-9.478357,7.376915),(-9.449263,7.405079),(-9.438101,7.421564),(-9.418723,7.387767),(-9.407354,7.378052),(-9.392264,7.39986),(-9.386477,7.401668),(-9.381412,7.404975),(-9.379242,7.415828),(-9.375159,7.41929),(-9.365961,7.421099),(-9.349218,7.421564),(-9.335007,7.419652),(-9.327772,7.417068),(-9.319401,7.411952),(-9.312424,7.403322),(-9.3055,7.383478),(-9.299505,7.376605),(-9.283796,7.374073),(-9.249715,7.383065),(-9.234341,7.381308),(-9.219872,7.360999),(-9.206281,7.298367),(-9.181476,7.275681),(-9.17543,7.274596),(-9.15308,7.275474),(-9.147473,7.271392),(-9.146905,7.25408),(-9.139153,7.247879),(-9.11962,7.237957),(-9.116054,7.224676),(-9.125407,7.190208),(-9.113935,7.200388),(-9.106085,7.202975),(-9.100448,7.204833),(-9.086392,7.20721),(-9.073111,7.211344),(-9.059261,7.221369),(-9.046652,7.232738),(-9.032855,7.240283),(-9.015698,7.238887),(-9.007637,7.243487),(-8.985467,7.25005),(-8.981023,7.250566),(-8.977716,7.266224),(-8.973117,7.267671),(-8.962575,7.262969),(-8.9572,7.286481),(-8.944385,7.278678),(-8.925419,7.248603),(-8.91219,7.250153),(-8.868885,7.266638),(-8.857827,7.273046),(-8.851367,7.292889),(-8.855915,7.311855),(-8.863304,7.32989),(-8.865371,7.346891),(-8.860617,7.35764),(-8.851626,7.371489),(-8.83341,7.393865),(-8.82403,7.399808),(-8.807701,7.40451),(-8.799226,7.41221),(-8.795453,7.421099),(-8.793955,7.441511),(-8.790389,7.450812),(-8.784394,7.455722),(-8.756489,7.472413),(-8.739539,7.490552),(-8.729617,7.50869),(-8.725742,7.528534),(-8.726827,7.55184),(-8.729514,7.556387),(-8.73401,7.557679),(-8.738041,7.559488),(-8.739178,7.565689),(-8.737369,7.571425),(-8.731478,7.581761),(-8.730031,7.587445),(-8.727576,7.622017),(-8.720677,7.642739),(-8.694477,7.674416),(-8.686571,7.694364),(-8.567405,7.688214),(-8.57278,7.650749),(-8.566527,7.623412),(-8.54782,7.600777),(-8.515625,7.577161),(-8.485446,7.557989),(-8.44364,7.537112),(-8.425605,7.50192),(-8.405141,7.431279),(-8.393049,7.334334),(-8.387675,7.314955),(-8.38106,7.303018),(-8.364007,7.278885),(-8.357547,7.265708),(-8.349692,7.234702),(-8.34499,7.226795),(-8.333001,7.211861),(-8.32897,7.204006),(-8.328453,7.197391),(-8.330572,7.184731),(-8.329745,7.178323),(-8.326231,7.17207),(-8.311503,7.15729),(-8.305354,7.146903),(-8.302615,7.137602),(-8.30122,7.11321),(-8.284115,7.017867),(-8.286647,6.993786),(-8.29414,6.984381),(-8.314552,6.968568),(-8.319978,6.95999),(-8.321219,6.942265),(-8.319978,6.925832),(-8.320909,6.910174),(-8.333673,6.882578),(-8.328763,6.875085),(-8.320599,6.869659),(-8.315715,6.86382),(-8.314966,6.850281),(-8.316619,6.836276),(-8.324991,6.806252),(-8.337497,6.777262),(-8.351759,6.755351),(-8.441646,6.65531),(-8.461313,6.633421),(-8.533557,6.576344),(-8.547148,6.56004),(-8.549473,6.560143),(-8.566113,6.550919),(-8.567198,6.550609),(-8.566113,6.549059),(-8.570609,6.535132),(-8.572728,6.530843),(-8.577327,6.528026),(-8.589368,6.526063),(-8.594122,6.523892),(-8.61872,6.492835),(-8.601847,6.49175),(-8.592106,6.489683),(-8.568077,6.490406),(-8.556501,6.487021),(-8.545339,6.477203),(-8.515625,6.437593),(-8.497229,6.431366),(-8.484775,6.441572),(-8.47692,6.460149),(-8.472372,6.47865),(-8.467515,6.487073),(-8.46121,6.482887),(-8.449635,6.467927),(-8.418267,6.451209),(-8.405089,6.436327),(-8.406485,6.430539),(-8.413874,6.424183),(-8.419042,6.407646),(-8.417233,6.398189),(-8.408242,6.379922),(-8.405968,6.372248),(-8.410981,6.363179),(-8.420153,6.358088),(-8.423693,6.351991),(-8.411807,6.340028),(-8.401059,6.35044),(-8.388811,6.355091),(-8.376564,6.35473),(-8.36597,6.350079),(-8.352948,6.36106),(-8.342613,6.356952),(-8.332949,6.34597),(-8.322356,6.336462),(-8.317498,6.336979),(-8.314191,6.341526),(-8.310005,6.344627),(-8.302718,6.340648),(-8.297706,6.332586),(-8.296569,6.324395),(-8.296569,6.317497),(-8.29507,6.313363),(-8.285975,6.310055),(-8.208486,6.292537),(-8.196575,6.288144),(-8.185723,6.28184),(-8.179057,6.276853),(-8.170582,6.274011),(-8.154355,6.274218),(-8.140609,6.277577),(-8.118285,6.289901),(-8.106606,6.294681),(-8.060098,6.301141),(-8.033019,6.301761),(-8.015708,6.297782),(-7.999378,6.286697),(-7.934886,6.271427),(-7.929511,6.270755),(-7.925222,6.272512),(-7.920545,6.273804),(-7.91437,6.271737),(-7.912665,6.26843),(-7.910029,6.256777),(-7.906567,6.251997),(-7.862125,6.216392),(-7.846622,6.197478),(-7.844142,6.183965),(-7.857371,6.145388),(-7.862022,6.124382),(-7.864502,6.101696),(-7.861815,6.08149),(-7.850911,6.067564),(-7.850498,6.07224),(-7.840886,6.077356),(-7.82838,6.080715),(-7.819389,6.080095),(-7.809674,6.071207),(-7.805695,6.062034),(-7.802439,6.039245),(-7.799235,6.035679),(-7.793861,6.034077),(-7.788745,6.031493),(-7.786471,6.025111),(-7.78859,6.019789),(-7.797736,6.01475),(-7.799958,6.010151),(-7.800682,5.981729),(-7.799648,5.974468),(-7.786626,5.958165),(-7.747145,5.937597),(-7.73495,5.925634),(-7.717173,5.900752),(-7.70322,5.907883),(-7.691541,5.927727),(-7.680483,5.94093),(-7.674023,5.935737),(-7.663119,5.923102),(-7.64834,5.911294),(-7.630615,5.908607),(-7.629116,5.904938),(-7.608497,5.893698),(-7.605758,5.89313),(-7.584158,5.883699),(-7.579093,5.877188),(-7.587207,5.866775),(-7.579507,5.860341),(-7.566278,5.843727),(-7.559146,5.839851),(-7.547571,5.845432),(-7.535194,5.855845),(-7.527779,5.858842),(-7.531086,5.842022),(-7.515583,5.839231),(-7.508813,5.826183),(-7.503904,5.812101),(-7.494396,5.806184),(-7.486644,5.813806),(-7.481683,5.830214),(-7.478583,5.859876),(-7.446543,5.845949),(-7.442047,5.811274),(-7.448559,5.769055),(-7.449489,5.732364),(-7.43104,5.653971),(-7.417963,5.627757),(-7.396676,5.585087),(-7.384118,5.568964),(-7.405099,5.5724),(-7.41192,5.560359),(-7.407114,5.541394),(-7.393627,5.523979),(-7.41347,5.522816),(-7.419982,5.523127),(-7.409852,5.513417),(-7.408148,5.511784),(-7.41347,5.503489),(-7.425149,5.494162),(-7.432384,5.479563),(-7.431712,5.441917),(-7.436208,5.431323),(-7.450212,5.438713),(-7.449954,5.422771),(-7.446027,5.404917),(-7.439102,5.387812),(-7.429697,5.374298),(-7.414866,5.365978),(-7.404375,5.367994),(-7.396934,5.366444),(-7.391456,5.347685),(-7.388821,5.328384),(-7.389751,5.317144),(-7.39559,5.306783),(-7.407683,5.289859),(-7.410111,5.283167),(-7.41378,5.266708),(-7.418793,5.260455),(-7.428508,5.25614),(-7.430834,5.25999),(-7.430885,5.267535),(-7.434089,5.274072),(-7.435175,5.279291),(-7.43011,5.284252),(-7.428508,5.288154),(-7.439929,5.290169),(-7.442409,5.287379),(-7.468247,5.273452),(-7.475689,5.264228),(-7.479926,5.255158),(-7.490468,5.222189),(-7.482252,5.17506),(-7.483027,5.158239),(-7.488918,5.140669),(-7.515841,5.091809),(-7.529923,5.09739),(-7.546847,5.0977),(-7.563229,5.090156),(-7.575786,5.072069),(-7.578163,5.054731),(-7.57036,4.99688),(-7.570205,4.99688),(-7.5716,4.975382),(-7.564624,4.961585),(-7.555322,4.948433),(-7.549586,4.929054),(-7.549534,4.913887),(-7.553462,4.914249),(-7.561782,4.920166),(-7.574959,4.921561),(-7.6055,4.897428),(-7.605965,4.887997),(-7.598834,4.857095),(-7.600229,4.845804),(-7.605862,4.825133),(-7.605997,4.817363),(-7.606017,4.816193),(-7.601004,4.804643),(-7.593408,4.797434),(-7.585553,4.791543),(-7.579558,4.784283),(-7.576871,4.775291),(-7.572479,4.723356),(-7.576871,4.509338),(-7.575424,4.500347),(-7.572737,4.491122),(-7.570929,4.48071),(-7.572841,4.455388),(-7.565709,4.435208),(-7.564314,4.425829),(-7.567415,4.415933),(-7.577853,4.397278),(-7.579197,4.387149),(-7.573771,4.375393),(-7.540666,4.352845),(-7.541005,4.352769),(-7.593251,4.347235),(-7.608225,4.349433),(-7.631663,4.35928),(-7.644439,4.361518),(-7.712717,4.361518),(-7.721018,4.364691),(-7.725413,4.371772),(-7.728627,4.378811),(-7.733225,4.382025),(-7.749501,4.383246),(-7.788726,4.398912),(-7.801015,4.406317),(-7.812327,4.416083),(-7.818267,4.427191),(-7.823801,4.440741),(-7.832875,4.452216),(-7.862904,4.461371),(-7.88683,4.48017),(-7.89802,4.484442),(-7.91454,4.486518),(-7.924428,4.491685),(-7.9322,4.498358),(-7.942006,4.504869),(-7.959869,4.51203),(-8.003163,4.523505),(-8.037506,4.528754),(-8.100331,4.55329),(-8.222035,4.568061),(-8.257314,4.579983),(-8.300201,4.627265),(-8.316029,4.635199),(-8.335357,4.638821),(-8.438547,4.676174),(-8.549957,4.754869),(-8.607533,4.786933),(-8.74706,4.837714),(-8.778147,4.854315),(-8.848297,4.91356),(-8.874338,4.930121),(-8.9051,4.944322),(-8.915517,4.946275),(-8.936106,4.95539),(-8.966786,4.96011),(-8.991322,4.967515),(-9.014801,4.978461),(-9.031972,4.991441),(-9.028717,4.993638),(-9.028066,4.994289),(-9.027821,4.995429),(-9.025787,4.998928),(-9.069651,5.010972),(-9.10497,5.031562),(-9.162262,5.080878),(-9.17809,5.09101),(-9.212758,5.107408),(-9.243967,5.130561),(-9.261952,5.137274),(-9.278717,5.145738),(-9.291982,5.163479),(-9.278961,5.163479),(-9.292144,5.181627),(-9.312245,5.192613),(-9.334462,5.200995),(-9.354075,5.211168),(-9.470815,5.320461),(-9.477935,5.335354),(-9.488515,5.371649),(-9.497467,5.38939),(-9.508046,5.399604),(-9.524281,5.410793),(-9.541819,5.419827),(-9.556508,5.423489),(-9.559397,5.425035),(-9.587636,5.430732),(-9.593658,5.430325),(-9.59496,5.440009),(-9.583079,5.454901),(-9.580719,5.464504),(-9.596995,5.488349),(-9.696767,5.546373),(-9.842112,5.685452),(-9.979644,5.798082),(-10.015207,5.838121),(-10.022613,5.844224),(-10.039947,5.854315),(-10.046213,5.861721),(-10.049062,5.871772),(-10.044789,5.884467),(-10.046213,5.89643),(-10.055531,5.91177),(-10.071278,5.924791),(-10.089101,5.933987),(-10.104237,5.937445),(-10.11498,5.943305),(-10.185699,5.999091),(-10.226552,6.043606),(-10.279897,6.076972),(-10.298166,6.084906),(-10.336008,6.092231),(-10.353668,6.102362),(-10.364125,6.115668),(-10.36148,6.129218),(-10.352284,6.123521),(-10.344472,6.122707),(-10.338124,6.126776),(-10.333567,6.136054),(-10.353627,6.140611),(-10.367991,6.151801),(-10.380605,6.165351),(-10.395619,6.176988),(-10.428131,6.197008),(-10.444692,6.203843),(-10.463938,6.204983),(-10.463938,6.197496),(-10.41218,6.171047),(-10.389394,6.152167),(-10.381947,6.129218),(-10.397125,6.147854),(-10.424875,6.164618),(-10.456695,6.177476),(-10.659413,6.227484),(-10.788319,6.292955),(-10.807851,6.310858),(-10.800364,6.327826),(-10.795562,6.319648),(-10.790354,6.31391),(-10.78307,6.310004),(-10.772369,6.307359),(-10.789052,6.334947),(-10.792348,6.359036),(-10.782338,6.381415),(-10.759389,6.404202),(-10.773671,6.404202),(-10.784088,6.401272),(-10.792348,6.396226),(-10.800364,6.389879),(-10.82433,6.43773),(-10.85733,6.472846),(-10.895904,6.49901),(-11.053619,6.584174),(-11.233062,6.648098),(-11.353179,6.701158),(-11.374867,6.726874),(-11.375722,6.766669),(-11.369944,6.788886),(-11.368642,6.798245),(-11.368276,6.811347),(-11.381947,6.836819),(-11.38561,6.841783),(-11.404408,6.847073),(-11.424224,6.85932),(-11.44107,6.873277),(-11.450795,6.883368),(-11.476186,6.91942),(-11.444491,6.933945),(-11.436739,6.938544),(-11.438858,6.963865),(-11.434672,6.980815),(-11.407283,6.99637),(-11.397723,7.012803),(-11.391522,7.031768),(-11.3893,7.046703),(-11.392917,7.066857),(-11.389714,7.073523),(-11.367906,7.075952),(-11.360465,7.078639),(-11.355142,7.084065),(-11.353127,7.092798),(-11.356434,7.105356),(-11.370593,7.128403),(-11.373229,7.138842),(-11.370128,7.142614),(-11.352041,7.159254),(-11.317211,7.213566),(-11.30021,7.21708),(-11.217889,7.25408),(-11.209259,7.262194),(-11.144213,7.345193),(-11.126319,7.368027),(-10.977904,7.484919),(-10.937028,7.50776),(-10.898994,7.516493),(-10.885713,7.522178),(-10.874603,7.530859),(-10.864025,7.543684),(-10.730581,7.705474),(-10.692598,7.737565),(-10.645418,7.763041),(-10.638131,7.765522),(-10.615187,7.769036),(-10.617668,8.010778),(-10.616221,8.022509),(-10.612138,8.031862),(-10.603147,8.039226),(-10.577825,8.053153),(-10.56718,8.063204),(-10.543977,8.10607),(-10.529249,8.124286),(-10.505736,8.135835),(-10.485738,8.138858),(-10.405071,8.139272),(-10.384555,8.142114),(-10.364918,8.148212),(-10.34554,8.159348),(-10.320942,8.183119),(-10.318151,8.201645),(-10.326006,8.221541),(-10.333292,8.249756),(-10.331277,8.272287),(-10.313655,8.310347),(-10.282908,8.432949),(-10.282236,8.484625),(-10.271332,8.484109),(-10.260842,8.485917),(-10.240275,8.493746),(-10.23242,8.477055),(-10.215625,8.486589),(-10.181829,8.519584),(-10.164879,8.524649),(-10.147981,8.524287),(-10.091085,8.510102),(-10.076099,8.501498),(-10.069277,8.486873),(-10.079354,8.439951),(-10.075013,8.426644),(-10.061681,8.422174),(-10.04039,8.425663),(-10.000186,8.449305),(-9.961119,8.479561),(-9.944169,8.488346),(-9.928149,8.493436),(-9.911354,8.495658),(-9.891872,8.495917),(-9.886911,8.49664),(-9.872804,8.500361),(-9.868153,8.498087),(-9.863502,8.49354),(-9.858644,8.487054),(-9.849704,8.48969),(-9.831617,8.499017),(-9.806813,8.506252),(-9.805469,8.512789),(-9.808828,8.520463),(-9.808854,8.528473),(-9.802007,8.53718),(-9.794824,8.544544),(-9.790018,8.553071),(-9.790586,8.565396),(-9.773585,8.563018),(-9.763043,8.54997),(-9.757307,8.53271),(-9.750899,8.485866),(-9.7463,8.468063),(-9.735913,8.450493),(-9.722115,8.435636)] +Libya [(19.291677,30.287055),(19.338552,30.298814),(19.418956,30.333238),(19.530528,30.396796),(19.551036,30.404934),(19.596039,30.412014),(19.616384,30.421373),(19.748871,30.510932),(19.914317,30.682929),(19.958181,30.749701),(19.982188,30.778632),(20.018728,30.803778),(20.036469,30.819078),(20.099864,30.935004),(20.146658,31.045559),(20.152354,31.088202),(20.146658,31.216783),(20.128103,31.242987),(20.103282,31.308743),(20.082205,31.336615),(20.038341,31.375881),(20.022227,31.396796),(19.954845,31.559475),(19.948904,31.60102),(19.948009,31.645087),(19.944347,31.661444),(19.926931,31.699164),(19.920665,31.717719),(19.917247,31.759223),(19.919688,31.804674),(19.934337,31.888414),(19.948009,31.925971),(19.945811,31.935981),(19.941742,31.946926),(19.940115,31.95775),(19.944591,31.967515),(19.957205,31.982733),(20.048025,32.146064),(20.071544,32.176418),(20.261729,32.339545),(20.277192,32.360826),(20.32545,32.409817),(20.345714,32.419908),(20.385509,32.434638),(20.403331,32.447333),(20.416759,32.459459),(20.562673,32.557847),(20.79656,32.643012),(20.934093,32.722602),(21.050955,32.772284),(21.09669,32.781073),(21.286794,32.771145),(21.331879,32.774644),(21.414806,32.793402),(21.4546,32.812567),(21.608653,32.930732),(21.62322,32.936754),(21.671723,32.939887),(21.716319,32.950385),(21.743663,32.930854),(21.787446,32.915961),(21.836111,32.906562),(21.877452,32.903225),(22.096202,32.923082),(22.101329,32.926418),(22.111827,32.940904),(22.11671,32.944159),(22.138845,32.947577),(22.149587,32.947943),(22.161388,32.944159),(22.169444,32.938218),(22.171072,32.932929),(22.171072,32.926256),(22.175059,32.916246),(22.206798,32.888129),(22.247325,32.880845),(22.33961,32.882148),(22.379161,32.870347),(22.477306,32.807074),(22.496755,32.797309),(22.513845,32.790961),(22.532237,32.787543),(22.578868,32.784613),(22.812511,32.724514),(22.86671,32.694159),(22.884532,32.689765),(22.895844,32.688178),(22.92921,32.676703),(22.942638,32.675035),(22.976899,32.676703),(22.999685,32.670559),(23.041352,32.652533),(23.086436,32.64647),(23.10613,32.639838),(23.118663,32.62934),(23.120942,32.61522),(23.115245,32.604926),(23.097911,32.586656),(23.094412,32.577379),(23.103852,32.516343),(23.113292,32.5008),(23.128673,32.488471),(23.148936,32.478095),(23.140961,32.458564),(23.128429,32.395494),(23.108653,32.40233),(23.112153,32.411933),(23.109874,32.420315),(23.103363,32.428168),(23.094412,32.436469),(23.079112,32.354438),(23.080577,32.334052),(23.095551,32.323554),(23.156505,32.303534),(23.178966,32.299954),(23.195079,32.291653),(23.214529,32.272406),(23.230805,32.250637),(23.2435,32.220608),(23.257335,32.213772),(23.273204,32.209703),(23.285411,32.203762),(23.293224,32.192328),(23.302501,32.170722),(23.312185,32.162746),(23.310395,32.179267),(23.299083,32.224189),(23.31837,32.217841),(23.36199,32.217108),(23.37086,32.214016),(23.398936,32.194037),(23.405284,32.19066),(23.531098,32.181383),(23.669688,32.183254),(23.840343,32.149115),(23.998709,32.093899),(23.975271,32.074205),(23.970714,32.066596),(23.97877,32.062242),(24.004893,32.052924),(24.067882,32.011176),(24.090668,32.005764),(24.280935,32.007554),(24.546072,31.991441),(24.636241,32.014879),(24.658539,32.028632),(24.670258,32.032416),(24.710623,32.02558),(24.718598,32.027533),(24.726329,32.031317),(24.733735,32.033149),(24.741873,32.028998),(24.74586,32.02619),(24.758067,32.019965),(24.771983,32.01675),(24.791759,32.007758),(24.824392,32.002997),(24.865408,31.989325),(24.9817,31.967922),(25.017914,31.949042),(25.033376,31.916327),(25.024425,31.876614),(25.022227,31.854682),(25.029552,31.8369),(25.063731,31.804104),(25.116873,31.737982),(25.122081,31.720852),(25.136729,31.692572),(25.156261,31.663072),(25.152517,31.659817),(25.15089,31.65648),(25.088422,31.613524),(25.060413,31.579366),(25.023723,31.494409),(24.861252,31.38036),(24.848953,31.34863),(24.848643,31.312043),(24.858565,31.227914),(24.859495,31.145955),(24.882646,31.039088),(24.889571,31.018831),(24.924607,30.956768),(24.93763,30.905763),(24.981245,30.825406),(24.994887,30.785099),(24.988583,30.750579),(24.973597,30.716266),(24.961194,30.676268),(24.950652,30.621233),(24.92037,30.552348),(24.917063,30.532453),(24.907658,30.498656),(24.888124,30.464343),(24.829729,30.387552),(24.799447,30.360835),(24.772369,30.331018),(24.76286,30.317065),(24.746117,30.282752),(24.704672,30.217898),(24.688653,30.182758),(24.688343,30.144156),(24.697334,30.122607),(24.72555,30.078372),(24.811643,29.89089),(24.81619,29.868411),(24.81495,29.848567),(24.798207,29.796425),(24.804925,29.7548),(24.856188,29.679482),(24.870657,29.638347),(24.870554,29.614007),(24.861562,29.541557),(24.863836,29.502903),(24.873758,29.468332),(24.956647,29.292683),(24.97432,29.23894),(24.981245,29.181372),(24.981245,29.057917),(24.981245,28.890176),(24.981245,28.491544),(24.981245,28.096701),(24.981245,28.018549),(24.981245,27.666503),(24.981245,27.627824),(24.981245,27.475456),(24.981245,27.138035),(24.981245,27.049239),(24.981245,26.859964),(24.981245,26.664523),(24.981245,26.372707),(24.981245,26.080838),(24.981245,25.78897),(24.981245,25.497256),(24.981245,25.205439),(24.981245,24.913571),(24.981245,24.621728),(24.981245,24.329963),(24.981245,24.038146),(24.981245,23.746278),(24.981245,23.454435),(24.981245,23.16267),(24.981245,22.870801),(24.981245,22.578985),(24.981245,22.287168),(24.981245,21.995351),(24.981245,21.870811),(24.981141,21.746167),(24.981141,21.621575),(24.981141,21.497035),(24.981141,21.372443),(24.981038,21.247851),(24.980935,21.123311),(24.980935,20.998719),(24.980935,20.874128),(24.980831,20.749536),(24.980831,20.624944),(24.980831,20.500352),(24.980728,20.405319),(24.980625,20.310234),(24.980625,20.215098),(24.980521,20.120013),(24.980521,20.008391),(24.980521,20.002062),(24.979591,20.000512),(24.978661,19.999013),(24.977731,19.997463),(24.976801,19.995964),(24.974527,19.995654),(24.972356,19.995421),(24.970186,19.995189),(24.968016,19.994956),(24.867247,19.994956),(24.721312,19.995034),(24.599149,19.99506),(24.474609,19.995189),(24.34087,19.995292),(24.227906,19.995318),(24.142433,19.995421),(23.981306,19.995421),(23.981306,19.870597),(23.981306,19.745824),(23.981306,19.621026),(23.981306,19.496124),(23.857799,19.557179),(23.734292,19.618132),(23.610786,19.67911),(23.487279,19.740166),(23.363772,19.80117),(23.240162,19.862096),(23.116759,19.923152),(22.993149,19.984104),(22.869642,20.045108),(22.746136,20.106061),(22.622629,20.167091),(22.499122,20.228095),(22.375616,20.289124),(22.252109,20.350077),(22.128602,20.411055),(22.005096,20.472033),(21.881486,20.533063),(21.758082,20.59399),(21.634472,20.654968),(21.510966,20.716049),(21.387459,20.777027),(21.263952,20.838006),(21.140342,20.899036),(21.016939,20.959962),(20.893329,21.02094),(20.769926,21.08197),(20.646419,21.142897),(20.522809,21.203926),(20.399406,21.265008),(20.275796,21.325935),(20.152289,21.386913),(20.028782,21.447943),(19.905276,21.508869),(19.781665,21.569899),(19.658262,21.630877),(19.534652,21.691855),(19.411145,21.752885),(19.287639,21.813915),(19.185837,21.864177),(19.164132,21.874893),(19.040729,21.935871),(18.917119,21.99685),(18.793612,22.05788),(18.670105,22.118806),(18.546599,22.179836),(18.422989,22.240866),(18.299585,22.301844),(18.175975,22.362822),(18.052469,22.423852),(17.928962,22.484779),(17.805455,22.545757),(17.681949,22.606787),(17.558442,22.667765),(17.434832,22.728795),(17.311429,22.789799),(17.187922,22.850751),(17.064312,22.911755),(16.940909,22.972733),(16.817299,23.03366),(16.693792,23.094664),(16.570285,23.15572),(16.446779,23.216724),(16.323169,23.277728),(16.199765,23.338706),(16.076155,23.399632),(15.985101,23.44472),(15.964637,23.442214),(15.920196,23.422034),(15.862525,23.395937),(15.804854,23.369789),(15.747183,23.343641),(15.689616,23.317518),(15.631945,23.291344),(15.574274,23.265196),(15.516499,23.239048),(15.458829,23.212899),(15.401158,23.186751),(15.343487,23.160577),(15.285816,23.134455),(15.228145,23.108358),(15.170371,23.082261),(15.112907,23.056113),(15.055236,23.029965),(14.997461,23.003817),(14.979909,22.995664),(14.979271,22.995368),(14.979168,22.995316),(14.808016,22.908887),(14.63707,22.822536),(14.466021,22.736184),(14.294869,22.649833),(14.23172,22.617949),(14.216217,22.616295),(14.201644,22.62322),(14.156169,22.660737),(14.031009,22.763702),(13.906055,22.866616),(13.780895,22.969633),(13.655786,23.072624),(13.599562,23.119029),(13.482257,23.179672),(13.380661,23.202383),(13.292398,23.222098),(13.204134,23.241709),(13.115871,23.261449),(13.027607,23.281138),(12.939447,23.300827),(12.851184,23.32049),(12.763024,23.340179),(12.674657,23.359893),(12.586497,23.379582),(12.498337,23.399245),(12.409971,23.418882),(12.321811,23.438622),(12.233651,23.458285),(12.145284,23.477948),(12.057021,23.497611),(11.968861,23.517351),(11.89238,23.660056),(11.822306,23.790642),(11.71014,24.000137),(11.708618,24.00298),(11.636478,24.137649),(11.567128,24.26684),(11.541393,24.29751),(11.50863,24.313814),(11.46724,24.326339),(11.149996,24.422335),(10.911354,24.494501),(10.720668,24.552301),(10.699067,24.556125),(10.677363,24.553851),(10.566776,24.516463),(10.450194,24.476931),(10.410506,24.473288),(10.391799,24.47998),(10.260335,24.576641),(10.242248,24.595115),(10.229742,24.629945),(10.212172,24.722859),(10.193362,24.749937),(10.044534,24.829622),(10.032028,24.856339),(10.029961,24.995065),(10.025517,25.1364),(10.021383,25.26802),(10.007947,25.331426),(9.9695,25.395402),(9.816744,25.588465),(9.693961,25.743494),(9.541309,25.936351),(9.401162,26.113394),(9.377804,26.168946),(9.402506,26.216179),(9.416458,26.23225),(9.434752,26.271989),(9.468858,26.301031),(9.477643,26.315552),(9.481364,26.332606),(9.482604,26.352553),(9.835761,26.504223),(9.854571,26.524377),(9.896326,26.652793),(9.894052,26.67398),(9.88258,26.701782),(9.885474,26.736612),(9.910588,26.843117),(9.906661,26.857483),(9.890848,26.869576),(9.846096,26.891951),(9.835141,26.900995),(9.825529,26.92058),(9.806099,27.025122),(9.721349,27.291875),(9.721866,27.308463),(9.726517,27.32469),(9.743053,27.364119),(9.756283,27.42303),(9.770545,27.444217),(9.813643,27.486489),(9.821602,27.505687),(9.81168,27.526538),(9.797107,27.548914),(9.793903,27.569739),(9.818501,27.585733),(9.846613,27.599298),(9.863356,27.619246),(9.931274,27.818642),(9.934256,27.827398),(9.93591,27.866724),(9.789872,28.209442),(9.776953,28.267578),(9.827276,28.618647),(9.851264,28.785996),(9.848267,28.975726),(9.826149,29.128533),(9.746929,29.368428),(9.667709,29.608323),(9.54968,29.802316),(9.421729,29.968714),(9.369487,30.022794),(9.310005,30.084366),(9.286544,30.117129),(9.519708,30.228905),(9.743467,30.331328),(9.772922,30.338098),(9.845786,30.342283),(9.871314,30.355151),(9.995648,30.494522),(10.101171,30.641697),(10.192225,30.731252),(10.253927,30.841788),(10.26974,30.882147),(10.270153,30.915633),(10.245038,30.985707),(10.240594,31.021157),(10.246175,31.059552),(10.244832,31.078156),(10.213206,31.135362),(10.182717,31.240782),(10.108096,31.411831),(10.106235,31.429194),(10.116881,31.494409),(10.13259,31.517561),(10.196462,31.57859),(10.263952,31.680496),(10.315422,31.715843),(10.427766,31.714603),(10.482543,31.733103),(10.498873,31.744317),(10.513549,31.757029),(10.525538,31.772067),(10.542384,31.806638),(10.584552,31.84028),(10.597575,31.873508),(10.605946,31.953606),(10.628477,31.974122),(10.647288,31.971951),(10.665271,31.963218),(10.683564,31.957017),(10.703098,31.962185),(10.736585,31.985387),(10.772861,32.004508),(10.805624,32.032361),(10.845932,32.111788),(10.873217,32.136696),(11.182341,32.262223),(11.444035,32.36849),(11.513901,32.407997),(11.526085,32.417863),(11.546354,32.434275),(11.564131,32.465487),(11.560617,32.507578),(11.537363,32.543519),(11.47039,32.599277),(11.449926,32.637957),(11.449203,32.693018),(11.463775,32.798464),(11.456541,32.902101),(11.474421,32.969875),(11.474937,33.025841),(11.477418,33.041214),(11.506047,33.136376),(11.505112,33.181225),(11.505138,33.18122),(11.52589,33.176947),(11.560232,33.16592),(11.574962,33.157945),(11.587657,33.13231),(11.603038,33.121487),(11.635753,33.10871),(11.756602,33.092515),(11.793468,33.080756),(11.77296,33.099351),(11.707774,33.117174),(11.691091,33.135972),(11.739268,33.112982),(11.847016,33.082831),(12.08074,32.957831),(12.122406,32.921332),(12.160655,32.911689),(12.224864,32.875922),(12.303884,32.843085),(12.348318,32.832668),(12.729828,32.79857),(12.824392,32.804348),(13.074474,32.86636),(13.115489,32.882148),(13.147716,32.903998),(13.164724,32.912746),(13.187755,32.916246),(13.257091,32.918647),(13.351736,32.904242),(13.363129,32.899563),(13.373546,32.892035),(13.571462,32.802802),(13.616954,32.793402),(13.78712,32.799628),(13.830333,32.794094),(13.915294,32.772773),(13.991222,32.744574),(14.175548,32.717678),(14.185313,32.714504),(14.20338,32.700344),(14.209321,32.697211),(14.226329,32.690904),(14.262462,32.660305),(14.317149,32.630439),(14.404063,32.56684),(14.449392,32.525377),(14.469493,32.519029),(14.631602,32.495673),(14.647634,32.488267),(14.662934,32.476752),(14.706716,32.456285),(14.726817,32.450751),(14.911143,32.443915),(15.114757,32.412787),(15.160004,32.398668),(15.181977,32.395494),(15.195974,32.389797),(15.233246,32.347113),(15.269705,32.328843),(15.283051,32.317288),(15.292166,32.280911),(15.300792,32.26081),(15.322602,32.224189),(15.364513,32.174709),(15.370453,32.159084),(15.368663,32.138007),(15.35963,32.102118),(15.356863,32.061672),(15.355235,32.03852),(15.361095,31.965318),(15.370453,31.929389),(15.490408,31.664862),(15.514415,31.628363),(15.622813,31.49726),(15.687511,31.437812),(15.761485,31.388129),(16.044607,31.275539),(16.358653,31.227118),(16.728038,31.223822),(16.941905,31.183295),(17.16033,31.118801),(17.330577,31.086493),(17.365896,31.086615),(17.375011,31.083075),(17.382009,31.078762),(17.41863,31.062161),(17.447276,31.038723),(17.457774,31.033352),(17.466807,31.029975),(17.613943,30.992499),(17.691742,30.959662),(17.776052,30.935207),(17.848643,30.923651),(17.861664,30.913642),(17.889171,30.877916),(17.907481,30.863511),(17.926768,30.85517),(18.016856,30.837877),(18.175304,30.786078),(18.208344,30.769232),(18.235688,30.746812),(18.324229,30.656887),(18.56837,30.500067),(18.623302,30.445746),(18.653168,30.422309),(18.719249,30.391506),(18.760997,30.384223),(18.780528,30.375922),(18.925955,30.293362),(18.968028,30.277737),(19.056814,30.266181),(19.146007,30.264716),(19.239757,30.273993),(19.291677,30.287055)] +Saint Lucia [(-60.88679,14.010077),(-60.882965,13.980618),(-60.883046,13.954413),(-60.89509,13.877346),(-60.892201,13.833197),(-60.904612,13.784247),(-60.907297,13.77733),(-60.910308,13.776109),(-60.922841,13.772691),(-60.927113,13.769924),(-60.931752,13.760321),(-60.940785,13.722113),(-60.947011,13.716295),(-60.950103,13.714667),(-60.955068,13.714667),(-60.973378,13.739),(-61.048166,13.76732),(-61.064931,13.786933),(-61.068105,13.792182),(-61.074208,13.798733),(-61.078114,13.806301),(-61.071156,13.821967),(-61.070058,13.832099),(-61.071156,13.851793),(-61.072743,13.858222),(-61.075592,13.863267),(-61.078114,13.869615),(-61.078521,13.879788),(-61.075917,13.890367),(-61.066884,13.909003),(-61.064931,13.917304),(-61.059478,13.93122),(-61.035553,13.964911),(-61.026601,13.987372),(-61.002268,14.023139),(-60.99706,14.027167),(-60.987294,14.032538),(-60.98233,14.03734),(-60.97997,14.043524),(-60.976064,14.061184),(-60.972076,14.068101),(-60.947621,14.102281),(-60.933461,14.111884),(-60.914133,14.105699),(-60.918609,14.088446),(-60.911936,14.079495),(-60.901031,14.073391),(-60.892974,14.064683),(-60.890207,14.052232),(-60.88679,14.010077)] +Liechtenstein [(9.581203,47.05687),(9.560636,47.0524),(9.499554,47.059351),(9.477023,47.063898),(9.475886,47.073226),(9.487565,47.083949),(9.502861,47.094698),(9.51237,47.10803),(9.511853,47.129372),(9.503481,47.145392),(9.492629,47.15981),(9.484981,47.176346),(9.487358,47.210014),(9.504618,47.243732),(9.521155,47.262801),(9.53025,47.253654),(9.547096,47.243035),(9.540378,47.229108),(9.544823,47.220323),(9.554331,47.211615),(9.562909,47.19774),(9.561876,47.190609),(9.551954,47.175571),(9.552057,47.16689),(9.581823,47.154901),(9.605594,47.132266),(9.615723,47.106764),(9.608798,47.080771),(9.581203,47.05687)] +Lesotho [(28.980846,-28.909035),(28.995418,-28.908312),(29.018983,-28.913996),(29.040532,-28.922988),(29.049679,-28.933013),(29.049989,-28.95265),(29.055776,-28.965363),(29.069006,-28.973321),(29.091536,-28.978592),(29.125953,-28.992441),(29.208429,-29.068922),(29.241398,-29.077707),(29.281396,-29.078637),(29.311781,-29.089799),(29.316846,-29.147367),(29.32806,-29.159356),(29.343717,-29.169795),(29.357463,-29.183334),(29.365008,-29.200284),(29.375964,-29.235527),(29.403869,-29.268703),(29.413997,-29.290304),(29.414928,-29.296402),(29.413997,-29.311698),(29.415031,-29.318933),(29.419475,-29.325031),(29.432808,-29.336606),(29.435908,-29.342394),(29.432239,-29.356967),(29.413739,-29.380118),(29.411879,-29.395827),(29.41255,-29.410297),(29.4079,-29.421459),(29.399528,-29.430347),(29.388159,-29.437789),(29.361804,-29.447917),(29.332039,-29.455979),(29.303823,-29.466831),(29.282739,-29.485641),(29.275505,-29.506622),(29.275199,-29.528295),(29.275143,-29.532253),(29.282016,-29.556128),(29.296279,-29.571631),(29.279949,-29.581449),(29.278398,-29.597055),(29.278605,-29.613592),(29.26734,-29.626098),(29.190342,-29.646871),(29.1613,-29.666922),(29.145073,-29.691933),(29.132413,-29.720252),(29.113757,-29.750121),(29.113599,-29.752851),(29.11231,-29.775132),(29.106316,-29.801591),(29.105799,-29.825569),(29.120372,-29.843449),(29.132981,-29.852027),(29.135772,-29.859158),(29.135151,-29.868047),(29.137322,-29.882103),(29.148277,-29.901326),(29.150654,-29.911145),(29.144246,-29.919723),(29.132774,-29.924684),(29.106316,-29.931505),(29.09412,-29.936259),(29.015786,-29.978587),(28.976298,-29.999925),(28.860026,-30.066381),(28.795637,-30.089428),(28.729491,-30.101831),(28.639678,-30.131493),(28.605881,-30.131286),(28.557306,-30.114957),(28.540562,-30.113303),(28.524336,-30.116714),(28.480928,-30.139348),(28.456226,-30.146996),(28.407961,-30.140898),(28.383879,-30.144205),(28.364087,-30.159295),(28.355596,-30.17324),(28.338663,-30.201049),(28.323005,-30.214692),(28.313703,-30.22079),(28.3013,-30.2365),(28.294376,-30.242494),(28.284712,-30.246215),(28.255308,-30.249935),(28.237015,-30.256343),(28.216034,-30.267402),(28.200635,-30.282492),(28.198464,-30.301095),(28.20942,-30.314634),(28.224096,-30.320525),(28.235775,-30.329414),(28.238462,-30.352255),(28.231434,-30.373855),(28.218205,-30.387395),(28.133249,-30.445376),(28.125394,-30.457261),(28.127564,-30.465116),(28.139243,-30.482686),(28.142447,-30.492608),(28.141207,-30.500773),(28.124257,-30.547282),(28.120846,-30.553379),(28.112837,-30.562474),(28.104878,-30.568366),(28.096352,-30.572396),(28.088032,-30.577564),(28.081572,-30.586866),(28.075836,-30.60702),(28.076508,-30.623246),(28.078988,-30.639266),(28.078782,-30.658799),(28.054701,-30.649704),(27.936568,-30.640816),(27.915588,-30.634925),(27.895641,-30.626243),(27.886132,-30.619732),(27.878277,-30.612911),(27.869802,-30.607123),(27.858227,-30.603712),(27.849545,-30.604952),(27.830425,-30.613117),(27.8204,-30.614564),(27.778438,-30.609707),(27.743608,-30.600302),(27.713533,-30.583765),(27.659531,-30.530538),(27.598604,-30.490334),(27.5923,-30.481859),(27.590646,-30.472868),(27.590129,-30.463876),(27.586822,-30.454987),(27.562741,-30.425532),(27.536593,-30.403208),(27.533364,-30.393425),(27.529668,-30.382227),(27.493184,-30.367654),(27.477475,-30.356286),(27.466726,-30.341093),(27.459388,-30.316598),(27.452102,-30.310087),(27.43603,-30.30988),(27.414843,-30.317528),(27.407815,-30.318562),(27.397635,-30.317218),(27.377708,-30.312324),(27.377016,-30.312154),(27.366164,-30.311017),(27.367817,-30.295411),(27.345545,-30.241564),(27.343685,-30.212935),(27.365544,-30.165806),(27.38053,-30.152577),(27.381357,-30.142655),(27.371952,-30.135937),(27.356655,-30.132216),(27.334434,-30.132216),(27.322032,-30.1348),(27.312782,-30.131596),(27.300431,-30.114957),(27.293713,-30.100901),(27.280174,-30.053462),(27.265911,-30.033308),(27.217956,-29.998064),(27.198835,-29.978531),(27.17135,-29.921495),(27.088765,-29.750121),(27.088661,-29.750121),(27.088661,-29.750018),(27.080135,-29.735135),(27.050989,-29.696791),(27.037657,-29.686456),(27.024531,-29.680048),(27.010217,-29.669919),(27.002155,-29.666508),(27.014454,-29.641704),(27.014867,-29.625581),(27.022412,-29.616176),(27.032954,-29.616176),(27.042359,-29.628061),(27.049181,-29.620516),(27.056829,-29.604393),(27.062203,-29.600156),(27.072022,-29.599949),(27.075122,-29.605117),(27.077706,-29.611318),(27.085871,-29.614419),(27.090418,-29.611628),(27.122768,-29.581759),(27.128142,-29.578555),(27.156357,-29.568633),(27.18571,-29.565946),(27.195838,-29.562639),(27.213718,-29.554061),(27.24183,-29.548996),(27.263121,-29.541141),(27.295677,-29.524398),(27.300307,-29.52012),(27.302498,-29.518094),(27.309113,-29.509205),(27.314074,-29.498663),(27.316038,-29.487191),(27.321412,-29.483574),(27.344873,-29.484504),(27.350247,-29.480267),(27.354485,-29.462283),(27.365544,-29.446677),(27.407092,-29.406886),(27.413706,-29.402545),(27.417634,-29.396551),(27.41908,-29.383838),(27.416187,-29.375984),(27.410295,-29.369782),(27.406265,-29.363995),(27.408642,-29.35707),(27.417634,-29.350662),(27.426832,-29.347975),(27.436134,-29.343531),(27.445849,-29.331955),(27.448329,-29.322964),(27.450293,-29.299709),(27.45329,-29.291648),(27.469878,-29.282449),(27.510686,-29.270753),(27.518919,-29.268393),(27.528893,-29.260952),(27.527239,-29.249376),(27.520986,-29.226122),(27.521503,-29.21651),(27.528169,-29.207622),(27.538246,-29.202351),(27.548478,-29.19894),(27.555713,-29.195426),(27.61297,-29.133828),(27.635605,-29.096621),(27.634479,-29.091041),(27.630747,-29.07254),(27.637517,-29.065718),(27.64439,-29.07254),(27.649351,-29.070886),(27.658601,-29.066752),(27.664957,-29.065718),(27.656275,-29.055796),(27.64377,-29.044531),(27.63917,-29.035333),(27.655035,-29.031508),(27.667489,-29.026651),(27.679736,-29.015075),(27.699063,-28.990581),(27.702887,-28.989341),(27.707642,-28.990684),(27.711672,-28.990994),(27.713326,-28.98686),(27.713378,-28.979522),(27.714463,-28.976421),(27.716685,-28.973217),(27.71901,-28.967843),(27.720044,-28.959782),(27.720147,-28.945932),(27.728312,-28.937974),(27.744074,-28.93322),(27.754771,-28.925468),(27.747432,-28.908622),(27.861327,-28.915443),(27.887992,-28.904901),(27.897294,-28.889812),(27.903599,-28.873999),(27.91166,-28.86077),(27.926233,-28.853431),(27.945043,-28.855499),(27.956929,-28.86511),(27.966231,-28.875652),(27.977496,-28.880717),(28.004678,-28.880717),(28.013566,-28.878443),(28.014806,-28.872552),(28.014496,-28.8648),(28.018734,-28.856842),(28.056561,-28.812504),(28.100899,-28.770853),(28.104103,-28.765065),(28.131698,-28.729305),(28.145031,-28.714732),(28.154953,-28.70233),(28.164048,-28.70543),(28.218116,-28.700652),(28.23071,-28.699539),(28.250864,-28.707394),(28.273912,-28.709564),(28.297063,-28.706877),(28.317217,-28.700056),(28.33644,-28.684656),(28.363519,-28.643625),(28.382949,-28.626469),(28.403413,-28.618924),(28.542629,-28.610759),(28.562473,-28.606522),(28.619421,-28.572415),(28.634303,-28.570761),(28.653217,-28.58306),(28.66655,-28.59722),(28.675645,-28.613756),(28.681742,-28.633393),(28.688977,-28.674424),(28.699519,-28.68848),(28.743857,-28.689514),(28.758637,-28.700469),(28.787679,-28.748735),(28.795947,-28.754316),(28.82716,-28.759277),(28.827937,-28.759534),(28.843696,-28.764755),(28.858786,-28.772816),(28.859014,-28.77299),(28.872842,-28.783565),(28.885658,-28.797208),(28.925862,-28.859529),(28.980846,-28.909035)] +Luxembourg [(6.038628,50.148413),(6.061366,50.150738),(6.070048,50.154201),(6.076456,50.158645),(6.084207,50.159317),(6.097126,50.151307),(6.101467,50.142108),(6.10033,50.132652),(6.102604,50.124745),(6.117487,50.120456),(6.110562,50.105987),(6.105704,50.092241),(6.0994,50.064129),(6.101157,50.063405),(6.107151,50.063767),(6.109425,50.06356),(6.105704,50.060305),(6.096403,50.048626),(6.107255,50.044595),(6.113766,50.036378),(6.119967,50.015501),(6.117177,50.004391),(6.121517,49.996278),(6.138777,49.979328),(6.15397,49.951216),(6.161928,49.942482),(6.172677,49.956228),(6.189834,49.938297),(6.2227,49.887137),(6.238306,49.876905),(6.272206,49.867138),(6.286779,49.86104),(6.291533,49.855563),(6.295568,49.848616),(6.301558,49.838303),(6.302592,49.834944),(6.310653,49.834479),(6.325639,49.84037),(6.334424,49.840215),(6.351374,49.83329),(6.380106,49.815565),(6.397056,49.808589),(6.414523,49.805488),(6.462478,49.805488),(6.493278,49.799597),(6.497205,49.799442),(6.502579,49.79567),(6.502269,49.795876),(6.500099,49.794481),(6.499996,49.786058),(6.498549,49.785386),(6.493794,49.76363),(6.493691,49.756551),(6.496378,49.752106),(6.495965,49.748231),(6.48625,49.742701),(6.485526,49.733761),(6.4878,49.725596),(6.492554,49.718413),(6.499686,49.712212),(6.491004,49.714434),(6.486353,49.712936),(6.482942,49.708078),(6.489764,49.702962),(6.491727,49.700792),(6.418243,49.669889),(6.402741,49.655782),(6.404498,49.652474),(6.410905,49.649632),(6.417003,49.645756),(6.417933,49.639142),(6.415246,49.634646),(6.407701,49.627411),(6.397573,49.613872),(6.371528,49.592995),(6.356438,49.577595),(6.350754,49.566588),(6.350754,49.53491),(6.348809,49.52529),(6.342279,49.493001),(6.34538,49.462718),(6.345307,49.455349),(6.325329,49.456724),(6.298768,49.466232),(6.251117,49.48946),(6.249365,49.490314),(6.221976,49.497445),(6.193554,49.499409),(6.13609,49.495275),(6.142601,49.486076),(6.114386,49.484371),(6.107255,49.48251),(6.101984,49.476413),(6.102087,49.470005),(6.099813,49.46463),(6.087721,49.461633),(6.078006,49.452021),(6.06333,49.448456),(5.978064,49.445097),(5.9607,49.441324),(5.946954,49.469953),(5.928144,49.482304),(5.864686,49.492174),(5.839571,49.499874),(5.822104,49.510519),(5.790685,49.537753),(5.814456,49.545142),(5.8374,49.56111),(5.846909,49.576717),(5.829959,49.582763),(5.841224,49.589687),(5.849183,49.599713),(5.861998,49.62276),(5.869957,49.628858),(5.879878,49.634853),(5.885459,49.643534),(5.879878,49.657745),(5.872644,49.661724),(5.852593,49.663223),(5.845772,49.666582),(5.842258,49.67392),(5.843705,49.677486),(5.846702,49.68069),(5.847219,49.687201),(5.848769,49.69273),(5.853627,49.696296),(5.857347,49.70043),(5.856403,49.705807),(5.856004,49.708078),(5.850216,49.714021),(5.843705,49.714331),(5.837297,49.712936),(5.831716,49.713607),(5.825721,49.715778),(5.811769,49.718517),(5.805361,49.721876),(5.805774,49.724201),(5.803604,49.738154),(5.802054,49.742856),(5.778489,49.773035),(5.771875,49.779392),(5.759162,49.784456),(5.748414,49.785644),(5.738285,49.788848),(5.727743,49.800217),(5.721645,49.812775),(5.720198,49.824712),(5.724642,49.834272),(5.736528,49.83944),(5.726916,49.845227),(5.728673,49.848845),(5.730533,49.85117),(5.73198,49.854167),(5.731877,49.859955),(5.758129,49.858198),(5.748827,49.867293),(5.726709,49.878197),(5.714927,49.881866),(5.718958,49.891374),(5.753581,49.930183),(5.757612,49.93654),(5.759989,49.941604),(5.76371,49.946823),(5.771565,49.953541),(5.778593,49.95659),(5.793372,49.958812),(5.80164,49.963825),(5.812596,49.977571),(5.808565,49.9831),(5.801537,49.988681),(5.802674,50.002479),(5.808875,50.007801),(5.829132,50.013589),(5.836367,50.01855),(5.838847,50.026457),(5.838847,50.035862),(5.83771,50.047437),(5.843705,50.053638),(5.858278,50.061803),(5.864375,50.067488),(5.866856,50.074309),(5.86882,50.090535),(5.872437,50.096892),(5.888973,50.106607),(5.92618,50.118337),(5.941063,50.128311),(5.949021,50.142677),(5.953156,50.156371),(5.96163,50.165621),(5.982921,50.167068),(5.998321,50.174975),(6.004729,50.170479),(6.008036,50.160919),(6.014134,50.153581),(6.022967,50.15082),(6.027363,50.149447),(6.038628,50.148413)] +Latvia [(25.333678,58.031808),(25.339879,58.032583),(25.34639,58.034443),(25.356519,58.034753),(25.39662,58.023178),(25.457185,57.984059),(25.496614,57.970597),(25.53196,57.966437),(25.541676,57.96282),(25.550254,57.955327),(25.551816,57.94986),(25.552114,57.948815),(25.552941,57.942175),(25.558315,57.934243),(25.579399,57.919463),(25.601517,57.912203),(25.625081,57.910291),(25.650093,57.911428),(25.7038,57.921327),(25.714998,57.923391),(25.730295,57.923132),(25.745384,57.90918),(25.754686,57.888897),(25.767502,57.868924),(25.792616,57.855979),(26.002733,57.845979),(26.014515,57.842827),(26.021956,57.837944),(26.025264,57.828409),(26.02175,57.822415),(26.016065,57.816472),(26.013068,57.8073),(26.016065,57.786681),(26.024747,57.774356),(26.135231,57.724772),(26.168511,57.70405),(26.263182,57.620825),(26.297185,57.599147),(26.33863,57.583153),(26.351325,57.580203),(26.430678,57.561764),(26.430924,57.561707),(26.447564,57.552922),(26.48105,57.527136),(26.49955,57.515819),(26.515053,57.517266),(26.528696,57.52388),(26.542235,57.528169),(26.551743,57.526826),(26.570243,57.519591),(26.579855,57.517834),(26.590087,57.520366),(26.594841,57.52649),(26.598355,57.533854),(26.604763,57.540313),(26.634322,57.554421),(26.666982,57.56486),(26.700468,57.570751),(26.778086,57.568477),(26.795759,57.571319),(26.816327,57.581189),(26.828315,57.595039),(26.838547,57.60987),(26.854154,57.622556),(26.872654,57.627181),(26.884953,57.622091),(26.896115,57.614986),(26.911618,57.613435),(26.929188,57.615554),(26.946551,57.615347),(26.981071,57.608991),(27.004635,57.598914),(27.041326,57.568451),(27.061531,57.555661),(27.085354,57.549434),(27.165659,57.546695),(27.319965,57.516129),(27.352935,57.527601),(27.528169,57.528479),(27.522795,57.492022),(27.525637,57.46838),(27.514837,57.44789),(27.511323,57.430397),(27.536283,57.415695),(27.640824,57.389005),(27.694409,57.356375),(27.707952,57.348129),(27.809134,57.313945),(27.827738,57.304953),(27.840295,57.290639),(27.846134,57.267307),(27.841174,57.211212),(27.833939,57.18049),(27.824327,57.15907),(27.794045,57.143387),(27.700975,57.118789),(27.682217,57.103699),(27.696066,57.085457),(27.722059,57.07799),(27.745469,57.067991),(27.75074,57.042359),(27.745779,57.031455),(27.729552,57.009855),(27.723351,56.998796),(27.720767,56.988667),(27.718545,56.96872),(27.715135,56.957403),(27.648731,56.879268),(27.62837,56.844154),(27.644379,56.841772),(27.661185,56.839271),(27.744074,56.864799),(27.786397,56.871258),(27.830838,56.864282),(27.852232,56.854309),(27.891506,56.829711),(27.913521,56.82015),(27.918895,56.805888),(27.900085,56.783047),(27.876107,56.759431),(27.865461,56.742687),(27.882618,56.725479),(27.98101,56.687006),(27.991345,56.669979),(27.992172,56.624994),(27.997443,56.603833),(28.010982,56.587555),(28.028656,56.576754),(28.108651,56.55518),(28.126117,56.547764),(28.132215,56.535982),(28.125239,56.527145),(28.099246,56.513399),(28.093251,56.501591),(28.096455,56.491953),(28.104517,56.483065),(28.156503,56.44622),(28.164255,56.437952),(28.167872,56.427125),(28.164255,56.392812),(28.167148,56.369868),(28.174435,56.349637),(28.214794,56.281372),(28.217275,56.270727),(28.215311,56.255999),(28.20942,56.248144),(28.201358,56.241684),(28.193142,56.231039),(28.184408,56.207526),(28.178621,56.18391),(28.169112,56.161741),(28.148907,56.142414),(28.110976,56.156806),(28.06824,56.147582),(28.0511,56.140666),(28.023798,56.12965),(27.98101,56.118023),(27.939669,56.113062),(27.92706,56.109367),(27.911453,56.100246),(27.901532,56.089342),(27.892747,56.077095),(27.880654,56.063866),(27.812545,56.034514),(27.781229,56.016375),(27.776991,55.992397),(27.744435,55.959738),(27.64501,55.922841),(27.617156,55.878554),(27.610128,55.83096),(27.601498,55.809618),(27.592713,55.794244),(27.564601,55.792229),(27.438821,55.79874),(27.405851,55.804347),(27.374587,55.814837),(27.349627,55.831219),(27.329163,55.817576),(27.282448,55.791867),(27.263018,55.787216),(27.235526,55.795846),(27.173204,55.825741),(27.151448,55.832459),(27.110779,55.836283),(26.981071,55.826878),(26.979426,55.826291),(26.957817,55.818584),(26.900146,55.778715),(26.842785,55.719339),(26.822838,55.70611),(26.743049,55.682856),(26.720105,55.681874),(26.666878,55.693966),(26.64011,55.695568),(26.615615,55.687971),(26.594531,55.666991),(26.537481,55.669523),(26.48105,55.678308),(26.34235,55.716342),(26.279718,55.743239),(26.226905,55.796931),(26.203754,55.827446),(26.178639,55.84959),(26.079421,55.89814),(26.017616,55.937362),(25.961251,55.958459),(25.871268,55.992139),(25.795496,56.04013),(25.766261,56.058647),(25.708797,56.081048),(25.696602,56.087895),(25.687817,56.098334),(25.669213,56.132027),(25.661875,56.140812),(25.649679,56.143809),(25.590045,56.141122),(25.572888,56.143034),(25.522762,56.156573),(25.454808,56.149649),(25.349086,56.159876),(25.109196,56.183083),(25.073125,56.197811),(25.04398,56.22799),(25.026203,56.260185),(25.016488,56.2699),(24.983208,56.290493),(24.973183,56.300751),(24.962124,56.319277),(24.936286,56.379919),(24.910138,56.421958),(24.892258,56.438727),(24.870967,56.442602),(24.857118,56.435368),(24.853397,56.424722),(24.852157,56.413664),(24.845852,56.40493),(24.837688,56.403948),(24.81557,56.408806),(24.805545,56.408548),(24.71504,56.386253),(24.678628,56.377283),(24.639147,56.359972),(24.557911,56.29858),(24.538998,56.287625),(24.481327,56.26884),(24.44722,56.260521),(24.414354,56.265507),(24.350792,56.291552),(24.318546,56.29858),(24.287644,56.295531),(24.166824,56.260314),(24.140422,56.2576),(24.138919,56.257446),(24.108637,56.260701),(24.07515,56.271192),(23.981306,56.312404),(23.871107,56.332072),(23.858109,56.334392),(23.825036,56.334909),(23.7561,56.325969),(23.724991,56.328811),(23.723647,56.332118),(23.724784,56.338397),(23.723544,56.345812),(23.715069,56.352737),(23.706697,56.354442),(23.679412,56.351859),(23.609856,56.353822),(23.577713,56.348603),(23.517561,56.328656),(23.481595,56.330103),(23.37804,56.35463),(23.310649,56.370591),(23.288428,56.373046),(23.17257,56.357956),(23.154173,56.351394),(23.162854,56.341007),(23.112728,56.310879),(23.062292,56.304161),(23.016714,56.32385),(22.981367,56.373175),(22.956976,56.401985),(22.924523,56.412113),(22.888969,56.408444),(22.859603,56.39707),(22.822927,56.382864),(22.681437,56.350308),(22.666347,56.349094),(22.649087,56.353099),(22.604749,56.379092),(22.578222,56.387003),(22.57581,56.387722),(22.511731,56.395964),(22.214902,56.390383),(22.195265,56.394853),(22.158161,56.410253),(22.139144,56.415705),(22.094082,56.41741),(21.983173,56.388353),(21.965322,56.383677),(21.684495,56.310104),(21.596025,56.307882),(21.558921,56.297288),(21.419292,56.237395),(21.403685,56.234476),(21.358313,56.233235),(21.327618,56.224373),(21.290411,56.206932),(21.254857,56.185202),(21.229639,56.163188),(21.212586,56.130994),(21.205351,56.103424),(21.190365,56.084459),(21.150161,56.07818),(21.091353,56.077896),(21.053398,56.072604),(21.053396,56.072618),(21.053396,56.072943),(21.052582,56.077541),(21.042735,56.114569),(21.028819,56.147406),(20.98406,56.210435),(20.973399,56.232001),(20.969086,56.253485),(20.971039,56.25967),(20.980235,56.279283),(20.982677,56.290758),(20.982677,56.301459),(20.981456,56.310492),(20.970958,56.34984),(20.968598,56.369818),(20.970551,56.388983),(20.979015,56.404364),(20.992524,56.417914),(20.998383,56.425686),(21.003184,56.434801),(21.005382,56.445868),(21.005544,56.465522),(21.01059,56.475735),(21.003266,56.49258),(21.000499,56.510647),(21.006358,56.519965),(21.024262,56.510484),(21.030528,56.500149),(21.035818,56.473944),(21.044688,56.462104),(21.030528,56.448432),(21.037446,56.444648),(21.044688,56.442206),(21.044688,56.427965),(21.044688,56.421129),(21.030528,56.408108),(21.053396,56.38996),(21.061778,56.38703),(21.07016,56.38935),(21.077159,56.395209),(21.079763,56.403062),(21.068614,56.424058),(21.066661,56.44184),(21.068126,56.458808),(21.072113,56.46955),(21.067638,56.476386),(21.063243,56.493964),(21.05836,56.503648),(21.052908,56.511054),(21.048106,56.515611),(21.030528,56.524156),(21.019542,56.527086),(21.010509,56.527777),(21.003103,56.530015),(20.996349,56.537828),(20.992198,56.548896),(20.995128,56.553371),(21.000336,56.557685),(21.010509,56.5987),(21.046153,56.656195),(21.05836,56.688666),(21.065196,56.774319),(21.061209,56.794135),(21.05421,56.811957),(21.052745,56.828925),(21.065196,56.84634),(21.147227,56.87641),(21.156749,56.885565),(21.222911,56.907701),(21.240977,56.91828),(21.277599,56.949123),(21.287771,56.955512),(21.300141,56.95954),(21.328217,56.973619),(21.360118,56.989691),(21.382498,57.008938),(21.401622,57.037502),(21.413585,57.073188),(21.414806,57.113837),(21.411876,57.124457),(21.401052,57.151313),(21.403168,57.162055),(21.412608,57.176215),(21.414806,57.184882),(21.412608,57.250067),(21.414806,57.270901),(21.421397,57.288723),(21.433604,57.306464),(21.449474,57.320014),(21.466563,57.325507),(21.480235,57.333645),(21.517751,57.3876),(21.589122,57.438788),(21.699229,57.555325),(21.729666,57.573798),(21.771658,57.586127),(21.955903,57.592963),(21.999278,57.600328),(22.194509,57.65762),(22.483735,57.742499),(22.526134,57.749661),(22.549083,57.750637),(22.560313,57.752753),(22.572602,57.756822),(22.585785,57.759711),(22.600271,57.758043),(22.610362,57.754625),(22.610118,57.753485),(22.604991,57.751044),(22.600271,57.743842),(22.590831,57.706122),(22.587169,57.664984),(22.590994,57.644761),(22.600759,57.630113),(22.656098,57.585761),(22.878917,57.481269),(22.950369,57.432807),(23.031423,57.394477),(23.083344,57.378241),(23.117524,57.373928),(23.130219,57.370795),(23.133149,57.362982),(23.133556,57.353095),(23.138031,57.343166),(23.160167,57.31859),(23.164561,57.313666),(23.174571,57.297349),(23.182384,57.277655),(23.190196,57.242499),(23.198741,57.224189),(23.213552,57.216254),(23.222423,57.207017),(23.250499,57.114447),(23.260916,57.098944),(23.274913,57.092719),(23.292654,57.088935),(23.340099,57.05858),(23.422862,57.040229),(23.508556,57.031236),(23.520844,57.02558),(23.569672,56.986274),(23.578624,56.982082),(23.585134,56.979071),(23.632009,56.970933),(23.69516,56.967271),(23.866059,56.99018),(23.926931,57.006334),(23.952891,57.013251),(23.991222,57.031236),(24.009288,57.0456),(24.021983,57.059027),(24.035655,57.068996),(24.074555,57.074937),(24.113048,57.088731),(24.210785,57.123725),(24.219249,57.138007),(24.238617,57.149563),(24.261241,57.157457),(24.278575,57.161038),(24.278819,57.17178),(24.288748,57.1789),(24.312673,57.1883),(24.379161,57.230211),(24.400645,57.258124),(24.408865,57.298163),(24.405528,57.344468),(24.381602,57.469428),(24.379893,57.506537),(24.375173,57.528551),(24.364513,57.538398),(24.358572,57.55036),(24.362966,57.576606),(24.374766,57.613471),(24.363048,57.672268),(24.357677,57.685492),(24.313731,57.725043),(24.299571,57.743842),(24.299571,57.761908),(24.288829,57.808905),(24.285981,57.832587),(24.288829,57.845282),(24.296153,57.857367),(24.306159,57.868186),(24.349655,57.85864),(24.378181,57.859441),(24.401539,57.866469),(24.412701,57.876572),(24.429134,57.900343),(24.441639,57.908094),(24.481327,57.919308),(24.53383,57.945069),(24.553881,57.94742),(24.624057,57.943958),(24.684829,57.947575),(24.700435,57.95419),(24.718832,57.981837),(24.733508,57.992198),(24.764721,57.987909),(24.790765,57.978994),(24.81681,57.976669),(24.827417,57.981877),(24.848333,57.992146),(24.872518,58.00044),(24.949309,58.006435),(24.974837,58.01584),(25.034857,58.048574),(25.048838,58.056199),(25.070645,58.063615),(25.094209,58.067309),(25.141028,58.068007),(25.16697,58.058731),(25.180716,58.038164),(25.189914,58.013514),(25.20211,57.991965),(25.216786,57.985376),(25.232496,57.985376),(25.264535,57.994187),(25.284379,58.00814),(25.277557,58.024108),(25.249549,58.051186),(25.250686,58.068498),(25.263501,58.075138),(25.281692,58.073407),(25.299572,58.065604),(25.306393,58.058731),(25.318278,58.040619),(25.324583,58.034753),(25.333678,58.031808)] +Saint Martin [(-63.017569,18.033391),(-63.085886,18.058511),(-63.107004,18.062109),(-63.107004,18.06212),(-63.107004,18.066962),(-63.115305,18.065375),(-63.130523,18.060248),(-63.134348,18.059475),(-63.14387,18.064683),(-63.14684,18.070299),(-63.143625,18.074164),(-63.113759,18.074652),(-63.096099,18.078803),(-63.083811,18.087958),(-63.079091,18.104193),(-63.070872,18.110012),(-63.052113,18.116848),(-63.031402,18.121894),(-63.017649,18.122138),(-63.017934,18.100531),(-63.011098,18.070746),(-63.010732,18.040839),(-63.017568,18.033393),(-63.017569,18.033391)] +Morocco [(-5.40549,35.926519),(-5.399322,35.924465),(-5.398859,35.924504),(-5.389718,35.902047),(-5.378401,35.881687),(-5.362898,35.863807),(-5.340726,35.847366),(-5.340728,35.847357),(-5.34081,35.847113),(-5.345693,35.832587),(-5.342356,35.807685),(-5.327382,35.755845),(-5.322621,35.713772),(-5.318756,35.701728),(-5.312652,35.69245),(-5.304799,35.685207),(-5.298899,35.684312),(-5.28189,35.68651),(-5.276763,35.685207),(-5.27538,35.679389),(-5.277455,35.664211),(-5.276763,35.657904),(-5.259999,35.604722),(-5.24942,35.584621),(-5.228424,35.568508),(-5.186187,35.543769),(-5.150787,35.516099),(-5.066274,35.417467),(-5.050852,35.407538),(-5.026357,35.403998),(-5.008209,35.399237),(-4.988515,35.387885),(-4.954701,35.362454),(-4.926503,35.330308),(-4.909332,35.314521),(-4.86498,35.301988),(-4.810618,35.259996),(-4.770497,35.241034),(-4.628285,35.20539),(-4.495432,35.180772),(-4.494252,35.180569),(-4.376047,35.151842),(-4.347646,35.150133),(-4.327056,35.154771),(-4.269399,35.184882),(-4.130605,35.204779),(-4.046702,35.235907),(-3.961293,35.250434),(-3.919342,35.266832),(-3.909413,35.255276),(-3.91253,35.250918),(-3.924673,35.247556),(-3.929529,35.24382),(-3.925046,35.237842),(-3.918467,35.230893),(-3.903901,35.214173),(-3.889257,35.208407),(-3.86856,35.207343),(-3.840891,35.20539),(-3.821929,35.206773),(-3.787465,35.209215),(-3.764801,35.218451),(-3.755523,35.236396),(-3.747141,35.263658),(-3.726226,35.282294),(-3.699574,35.290839),(-3.673573,35.287909),(-3.654205,35.277004),(-3.612213,35.245347),(-3.590972,35.233303),(-3.516021,35.223538),(-3.489329,35.211005),(-3.477406,35.210679),(-3.464752,35.211819),(-3.453847,35.211615),(-3.44286,35.208645),(-3.423248,35.200832),(-3.412913,35.197943),(-3.36205,35.194525),(-3.319244,35.201809),(-3.195139,35.238227),(-3.17394,35.249091),(-3.128651,35.28856),(-3.118031,35.294135),(-3.109731,35.293647),(-3.100413,35.289537),(-3.08967,35.286282),(-3.077056,35.287909),(-3.0454,35.314439),(-3.006256,35.393541),(-2.980824,35.424506),(-2.982818,35.435004),(-2.977935,35.443305),(-2.968577,35.446438),(-2.956654,35.44123),(-2.952219,35.433051),(-2.95759,35.415839),(-2.952952,35.403998),(-2.963043,35.373481),(-2.949778,35.334947),(-2.94811,35.330268),(-2.947825,35.329779),(-2.947818,35.329768),(-2.96692,35.313866),(-2.963768,35.286219),(-2.943046,35.267874),(-2.912907,35.276916),(-2.899037,35.259996),(-2.907948,35.250963),(-2.912343,35.235785),(-2.913319,35.219062),(-2.90982,35.186713),(-2.905141,35.17357),(-2.896392,35.161811),(-2.881988,35.146715),(-2.856068,35.131293),(-2.820953,35.121894),(-2.748118,35.115953),(-2.791819,35.145168),(-2.868276,35.217353),(-2.883168,35.238511),(-2.878407,35.246324),(-2.864858,35.237616),(-2.816396,35.194525),(-2.808665,35.183783),(-2.761098,35.143256),(-2.718332,35.122992),(-2.666737,35.108222),(-2.563222,35.096137),(-2.517486,35.099351),(-2.493316,35.104397),(-2.477203,35.112616),(-2.456125,35.132473),(-2.437123,35.145087),(-2.416737,35.149156),(-2.321441,35.118842),(-2.299062,35.115953),(-2.275258,35.109565),(-2.248687,35.097235),(-2.222564,35.089301),(-2.221126,35.049955),(-2.211669,35.023445),(-2.193789,35.003601),(-2.1633,34.994041),(-2.126041,34.971923),(-2.094932,34.947687),(-2.061239,34.929704),(-2.01628,34.926241),(-2.00362,34.91818),(-1.999692,34.906346),(-1.9984,34.892703),(-1.993491,34.878854),(-1.979745,34.865263),(-1.926725,34.838081),(-1.892825,34.811675),(-1.787716,34.756691),(-1.769526,34.741343),(-1.773143,34.734057),(-1.786114,34.72584),(-1.810505,34.680727),(-1.862957,34.613599),(-1.871121,34.596649),(-1.750664,34.494175),(-1.714232,34.485054),(-1.702966,34.479679),(-1.809626,34.372451),(-1.771334,34.334701),(-1.746064,34.290311),(-1.674751,34.105956),(-1.672085,34.092021),(-1.669635,34.079213),(-1.672115,34.059188),(-1.718728,33.898087),(-1.722087,33.851165),(-1.713043,33.801995),(-1.702501,33.772823),(-1.703225,33.761816),(-1.710821,33.747063),(-1.72095,33.736366),(-1.732577,33.727865),(-1.74224,33.717762),(-1.746788,33.702388),(-1.740742,33.686601),(-1.725394,33.677713),(-1.690719,33.667326),(-1.673252,33.6565),(-1.6624,33.644692),(-1.617338,33.554439),(-1.612739,33.521469),(-1.6254,33.494236),(-1.640386,33.475529),(-1.659145,33.41977),(-1.672839,33.394604),(-1.683226,33.36923),(-1.683381,33.270839),(-1.674234,33.237972),(-1.623591,33.196605),(-1.605608,33.168028),(-1.592069,33.136609),(-1.571398,33.111985),(-1.545508,33.091831),(-1.516363,33.073977),(-1.499516,33.060205),(-1.493057,33.039483),(-1.493367,33.016151),(-1.496519,32.994292),(-1.498844,32.984008),(-1.502978,32.974629),(-1.50887,32.966309),(-1.516363,32.959488),(-1.558789,32.93365),(-1.423345,32.742395),(-1.390531,32.718779),(-1.32702,32.69891),(-1.047502,32.517009),(-1.031999,32.4944),(-1.08998,32.439442),(-1.123157,32.417945),(-1.16026,32.404948),(-1.201705,32.399858),(-1.217983,32.392623),(-1.234158,32.374614),(-1.244131,32.356915),(-1.257515,32.320845),(-1.273423,32.229442),(-1.275499,32.217518),(-1.275189,32.209069),(-1.276636,32.200852),(-1.282992,32.190181),(-1.289193,32.184858),(-1.305678,32.173722),(-1.309554,32.167443),(-1.305161,32.151165),(-1.288986,32.150907),(-1.251831,32.163516),(-1.232711,32.163723),(-1.211833,32.158348),(-1.195607,32.146049),(-1.190594,32.125224),(-1.210335,32.08967),(-1.249557,32.08166),(-1.324953,32.084709),(-1.333428,32.085071),(-1.357406,32.086053),(-1.395388,32.087552),(-1.445618,32.089515),(-1.506337,32.091944),(-1.575791,32.094735),(-1.652375,32.097835),(-1.734334,32.101091),(-1.819962,32.104501),(-1.907553,32.107964),(-1.995455,32.111478),(-2.081858,32.11494),(-2.165109,32.118299),(-2.243398,32.1214),(-2.315177,32.124294),(-2.378636,32.126774),(-2.516147,32.1322),(-2.695567,32.08967),(-2.881189,32.076286),(-2.938731,32.048639),(-2.869769,31.89243),(-2.827836,31.794586),(-3.002556,31.77362),(-3.21921,31.717709),(-3.511564,31.672745),(-3.548745,31.669954),(-3.591378,31.678274),(-3.659507,31.647821),(-3.673484,31.389234),(-3.747467,31.385166),(-3.802502,31.350646),(-3.815189,31.337158),(-3.81922,31.318865),(-3.812915,31.243365),(-3.814982,31.220524),(-3.836169,31.189777),(-3.842836,31.170192),(-3.839322,31.152828),(-3.827462,31.143837),(-3.810796,31.142906),(-3.792968,31.149676),(-3.763719,31.173447),(-3.748862,31.180217),(-3.731421,31.176341),(-3.717107,31.163267),(-3.689718,31.125595),(-3.671942,31.110867),(-3.635872,31.095674),(-3.624141,31.086527),(-3.614529,31.068027),(-3.610085,31.050302),(-3.608741,31.030872),(-3.554674,30.955927),(-3.610585,30.879049),(-3.659507,30.837116),(-3.652518,30.774217),(-3.645529,30.711317),(-3.834228,30.627452),(-4.001959,30.592507),(-4.155714,30.585519),(-4.274524,30.557563),(-4.372368,30.508641),(-4.484189,30.382842),(-4.623966,30.284999),(-4.770731,30.229088),(-4.875564,30.180166),(-4.95943,30.124256),(-5.071251,30.04039),(-5.176083,29.97749),(-5.273927,29.886635),(-5.343815,29.767825),(-5.43467,29.642026),(-5.539503,29.523216),(-5.637346,29.495261),(-5.721212,29.523216),(-5.756156,29.614071),(-5.881955,29.600093),(-6.000765,29.579127),(-6.126564,29.579127),(-6.27333,29.579127),(-6.413107,29.565149),(-6.559872,29.530205),(-6.699649,29.516227),(-6.783515,29.446339),(-6.958236,29.509238),(-7.070057,29.516227),(-7.146934,29.509238),(-7.258755,29.467305),(-7.34961,29.383439),(-7.463286,29.389137),(-7.48406,29.382445),(-7.506126,29.380223),(-7.528502,29.380947),(-7.572686,29.387613),(-7.619453,29.389422),(-7.653611,29.376193),(-7.714667,29.321829),(-7.729989,29.311158),(-7.777996,29.289324),(-7.839129,29.239043),(-7.945014,29.176231),(-8.036326,29.099853),(-8.069658,29.079337),(-8.182312,29.035541),(-8.250474,28.994769),(-8.316774,28.939062),(-8.333259,28.93038),(-8.368451,28.916531),(-8.383489,28.905782),(-8.417802,28.852349),(-8.430411,28.841006),(-8.475835,28.818759),(-8.520819,28.787081),(-8.648847,28.725948),(-8.667606,28.711685),(-8.678768,28.692823),(-8.682385,28.6659),(-8.682385,28.620218),(-8.682385,28.560273),(-8.682385,28.500406),(-8.682385,28.440487),(-8.682385,28.380543),(-8.682385,28.320624),(-8.682385,28.260679),(-8.682385,28.20076),(-8.682385,28.140893),(-8.682385,28.080949),(-8.682385,28.02103),(-8.682385,27.961085),(-8.682385,27.90114),(-8.682385,27.841222),(-8.682385,27.781354),(-8.682385,27.721436),(-8.682385,27.661439),(-8.752562,27.661439),(-8.816537,27.661465),(-8.817034,27.661465),(-8.817035,27.661464),(-8.818449,27.659398),(-8.81292,27.613354),(-8.783619,27.530362),(-8.773387,27.46003),(-8.788012,27.416054),(-8.801706,27.360424),(-8.795841,27.307688),(-8.773387,27.250069),(-8.752872,27.190486),(-8.752872,27.150463),(-8.793903,27.12018),(-8.888109,27.103566),(-9.000919,27.089924),(-9.083446,27.089924),(-9.207469,27.099691),(-9.284622,27.097727),(-9.352008,27.097727),(-9.412056,27.08796),(-9.486315,27.049875),(-9.568843,26.990292),(-9.672351,26.910219),(-9.734362,26.860429),(-9.816864,26.84968),(-9.899365,26.84968),(-9.979929,26.889729),(-10.031709,26.910219),(-10.065867,26.908281),(-10.122039,26.879962),(-10.188443,26.860429),(-10.250455,26.860429),(-10.353963,26.900478),(-10.477986,26.960035),(-10.550282,26.990292),(-10.653273,27.000058),(-10.756781,27.019592),(-10.829076,27.009825),(-10.921835,27.009825),(-11.045859,26.969802),(-11.149366,26.940501),(-11.262641,26.910219),(-11.391574,26.882908),(-11.36031,26.793043),(-11.315868,26.744208),(-11.315868,26.683644),(-11.3369,26.632897),(-11.398912,26.583081),(-11.469709,26.519597),(-11.510688,26.469807),(-11.55221,26.400457),(-11.582983,26.360408),(-11.63621,26.294985),(-11.683546,26.212975),(-11.698222,26.162177),(-11.717239,26.103576),(-11.753877,26.086006),(-11.879864,26.070399),(-11.959911,26.049884),(-12.029752,26.03035),(-12.055823,25.99583),(-12.055823,25.99583),(-12.060009,25.990301),(-12.080059,25.919969),(-12.080059,25.870205),(-12.100058,25.830156),(-12.129849,25.730549),(-12.169873,25.639728),(-12.200155,25.51958),(-12.229946,25.42),(-12.26997,25.259803),(-12.310019,25.110432),(-12.359835,24.969795),(-12.399884,24.879955),(-12.430141,24.830165),(-12.499982,24.7696),(-12.56003,24.730533),(-12.629845,24.679761),(-12.709943,24.629971),(-12.819781,24.570388),(-12.910137,24.51959),(-12.946879,24.496749),(-12.94688,24.496748),(-12.990184,24.4698),(-13.060025,24.400476),(-13.120099,24.299862),(-13.160122,24.219815),(-13.229963,24.0899),(-13.279753,24.019594),(-13.31001,23.980553),(-13.390108,23.940504),(-13.479948,23.910221),(-13.580045,23.870198),(-13.660118,23.830123),(-13.769982,23.790125),(-13.839797,23.750076),(-13.890129,23.690493),(-13.930127,23.620187),(-13.979943,23.519599),(-14.019992,23.410252),(-14.039991,23.33992),(-14.100065,23.099676),(-14.120089,22.960047),(-14.140088,22.870181),(-14.169906,22.759852),(-14.189904,22.589914),(-14.189904,22.450259),(-14.209955,22.370186),(-14.220187,22.309647),(-14.270003,22.240297),(-14.310052,22.190507),(-14.379841,22.120201),(-14.439915,22.080152),(-14.459914,22.040103),(-14.519988,21.990338),(-14.580036,21.91024),(-14.629852,21.860424),(-14.620085,21.820375),(-14.609827,21.750069),(-14.640109,21.679763),(-14.669875,21.599665),(-14.749974,21.500084),(-14.839813,21.450268),(-14.970167,21.440501),(-15.149872,21.440501),(-15.289992,21.450268),(-15.45993,21.450268),(-15.609818,21.469802),(-15.749964,21.490317),(-15.919876,21.500084),(-16.040024,21.500084),(-16.189886,21.48055),(-16.580043,21.48055),(-16.729956,21.469802),(-16.950149,21.429753),(-17.013743,21.419971),(-17.013743,21.419989),(-17.012807,21.445217),(-16.971059,21.592597),(-16.966908,21.636542),(-16.970326,21.674465),(-16.968007,21.697252),(-16.95108,21.724758),(-16.947662,21.736029),(-16.946401,21.748277),(-16.947011,21.759996),(-16.950266,21.765367),(-16.963246,21.775621),(-16.966908,21.781155),(-16.961537,21.795803),(-16.956939,21.82567),(-16.937815,21.866604),(-16.929799,21.907945),(-16.92101,21.931301),(-16.81664,22.130561),(-16.78067,22.165717),(-16.775054,22.174954),(-16.773427,22.180976),(-16.762074,22.205024),(-16.756337,22.210191),(-16.739898,22.221137),(-16.73412,22.226752),(-16.717885,22.260972),(-16.706776,22.275458),(-16.682607,22.284084),(-16.677154,22.289537),(-16.670318,22.29442),(-16.659006,22.295071),(-16.650258,22.291693),(-16.642649,22.285956),(-16.631703,22.273912),(-16.52184,22.314887),(-16.502187,22.329901),(-16.482167,22.352281),(-16.466624,22.377387),(-16.431508,22.493069),(-16.429351,22.510443),(-16.419545,22.521796),(-16.369781,22.568264),(-16.357289,22.583075),(-16.34439,22.646959),(-16.341379,22.732001),(-16.336822,22.75373),(-16.324859,22.789496),(-16.316477,22.806057),(-16.296457,22.832099),(-16.296254,22.84219),(-16.299957,22.850165),(-16.302113,22.856757),(-16.302154,22.868313),(-16.300608,22.875067),(-16.291737,22.893459),(-16.289622,22.899807),(-16.284779,22.903388),(-16.262603,22.905585),(-16.238637,22.911566),(-16.206451,22.937974),(-16.172963,22.973456),(-16.163238,22.993232),(-16.156484,23.013495),(-16.152577,23.035224),(-16.151275,23.059068),(-16.159535,23.082465),(-16.179067,23.086127),(-16.220204,23.075873),(-16.213124,23.094428),(-16.196034,23.126166),(-16.186676,23.137926),(-16.139272,23.178534),(-16.135121,23.185126),(-16.060414,23.34455),(-16.049143,23.3581),(-16.038319,23.363918),(-16.025543,23.374945),(-15.981191,23.445787),(-15.967193,23.512926),(-15.956451,23.531724),(-15.941314,23.551337),(-15.905507,23.610297),(-15.857086,23.661811),(-15.853871,23.667914),(-15.837392,23.679348),(-15.830393,23.685981),(-15.825063,23.696723),(-15.820058,23.717231),(-15.81607,23.727607),(-15.800649,23.750637),(-15.78482,23.768988),(-15.772613,23.787828),(-15.76769,23.812649),(-15.765452,23.856757),(-15.769154,23.875678),(-15.781972,23.898261),(-15.778676,23.903713),(-15.775136,23.911933),(-15.786773,23.903876),(-15.787953,23.892157),(-15.786,23.878363),(-15.788197,23.864163),(-15.795318,23.856635),(-15.820872,23.840277),(-15.830393,23.836249),(-15.843577,23.835883),(-15.852203,23.838121),(-15.861724,23.836168),(-15.877553,23.823188),(-15.888173,23.810736),(-15.895334,23.798774),(-15.91039,23.765326),(-15.923329,23.743598),(-15.925933,23.73725),(-15.92809,23.725165),(-15.937489,23.705227),(-15.939605,23.696234),(-15.948232,23.684312),(-15.994862,23.645006),(-16.009755,23.655422),(-16.003163,23.672105),(-15.981191,23.696234),(-15.975819,23.710761),(-15.939605,23.774807),(-15.877553,23.853583),(-15.871246,23.869208),(-15.856801,23.886949),(-15.840932,23.902655),(-15.768137,23.959866),(-15.735748,23.971177),(-15.692616,23.995795),(-15.679555,24.007514),(-15.646637,24.010403),(-15.620107,24.026272),(-15.599233,24.048326),(-15.583323,24.070258),(-15.542348,24.114244),(-15.514394,24.152167),(-15.476064,24.177802),(-15.459706,24.191881),(-15.453033,24.210191),(-15.444692,24.221869),(-15.353383,24.291083),(-15.298248,24.34516),(-15.229563,24.440741),(-15.203969,24.467475),(-15.171864,24.494127),(-15.153554,24.505601),(-15.133412,24.514635),(-15.112701,24.520575),(-15.069407,24.527289),(-15.048329,24.538275),(-15.014801,24.562445),(-15.01537,24.585679),(-15.012237,24.591539),(-14.999989,24.614488),(-14.976226,24.641425),(-14.952138,24.659247),(-14.926991,24.67178),(-14.907826,24.685492),(-14.895619,24.705715),(-14.885854,24.770738),(-14.861928,24.830146),(-14.853424,24.876614),(-14.83967,24.905341),(-14.836049,24.918687),(-14.837961,24.935126),(-14.84203,24.950263),(-14.84317,24.965277),(-14.836049,24.981391),(-14.843495,24.987616),(-14.837229,25.001695),(-14.83259,25.017564),(-14.829742,25.034247),(-14.829213,25.050238),(-14.831899,25.065741),(-14.84142,25.087551),(-14.843495,25.100531),(-14.842437,25.189032),(-14.849721,25.214179),(-14.819244,25.330227),(-14.812123,25.346096),(-14.782053,25.446926),(-14.736195,25.50552),(-14.723134,25.515815),(-14.714915,25.52558),(-14.68517,25.590888),(-14.678334,25.635565),(-14.676259,25.641913),(-14.66686,25.659735),(-14.661366,25.691311),(-14.620961,25.783596),(-14.546457,25.879218),(-14.519521,25.923774),(-14.513905,25.936957),(-14.511057,25.956855),(-14.494985,26.001614),(-14.486562,26.015448),(-14.490346,26.03148),(-14.480377,26.087795),(-14.483306,26.102484),(-14.492828,26.132717),(-14.490061,26.142727),(-14.482289,26.153876),(-14.471791,26.183051),(-14.466135,26.194241),(-14.410146,26.260077),(-14.400746,26.266303),(-14.353179,26.275946),(-14.29894,26.302232),(-14.215932,26.375474),(-14.202056,26.392239),(-14.192779,26.409491),(-14.180247,26.424384),(-14.157053,26.433783),(-14.046864,26.444403),(-14.02774,26.452379),(-13.923736,26.500881),(-13.742014,26.618109),(-13.619985,26.68891),(-13.561106,26.749091),(-13.500885,26.858303),(-13.480336,26.911689),(-13.461049,26.992743),(-13.431996,27.050767),(-13.402455,27.177191),(-13.383656,27.215277),(-13.301096,27.324449),(-13.300771,27.330024),(-13.307769,27.339342),(-13.307932,27.344957),(-13.29426,27.351752),(-13.240834,27.465399),(-13.20759,27.56745),(-13.205434,27.588568),(-13.200795,27.606513),(-13.180979,27.644843),(-13.178254,27.662491),(-13.178253,27.662502),(-13.178212,27.662787),(-13.177561,27.667141),(-13.171254,27.685004),(-13.160512,27.694648),(-13.13036,27.708075),(-13.097971,27.732245),(-13.061431,27.742906),(-13.045155,27.759833),(-13.003,27.821031),(-12.979563,27.893704),(-12.968088,27.914618),(-12.952382,27.928616),(-12.933095,27.938707),(-12.838938,27.970404),(-12.657826,27.998033),(-12.513539,27.995429),(-12.335032,28.047268),(-12.061431,28.089016),(-12.050404,28.096015),(-12.027903,28.116889),(-12.023101,28.119574),(-12.005605,28.123196),(-11.782379,28.21011),(-11.485585,28.325629),(-11.452789,28.348456),(-11.428822,28.375922),(-11.389312,28.434882),(-11.374013,28.449774),(-11.355946,28.463853),(-11.340972,28.479682),(-11.334706,28.499742),(-11.325917,28.515204),(-11.266469,28.551581),(-11.219635,28.602484),(-11.211822,28.616767),(-11.170318,28.639716),(-11.162465,28.647406),(-11.154205,28.661078),(-11.149159,28.66767),(-11.11498,28.69184),(-11.111562,28.695746),(-11.091054,28.726304),(-11.0631,28.752387),(-11.047597,28.761705),(-10.762603,28.890204),(-10.694203,28.930569),(-10.612416,28.967719),(-10.573801,28.990424),(-10.450917,29.09219),(-10.34789,29.229397),(-10.320872,29.257961),(-10.301991,29.271877),(-10.264027,29.284125),(-10.248402,29.299384),(-10.224355,29.333075),(-10.199127,29.361274),(-10.187571,29.378974),(-10.182729,29.397284),(-10.177642,29.405829),(-10.141754,29.428616),(-10.137034,29.434963),(-10.128163,29.455959),(-10.086985,29.509955),(-10.080922,29.521145),(-10.078684,29.542304),(-10.072621,29.564683),(-10.063629,29.584947),(-10.052968,29.599921),(-10.005279,29.638414),(-9.997792,29.650824),(-9.991689,29.666815),(-9.949941,29.71601),(-9.820221,29.838935),(-9.717926,29.996568),(-9.655141,30.126899),(-9.645253,30.164008),(-9.628407,30.291409),(-9.610015,30.357815),(-9.60733,30.377631),(-9.611643,30.404364),(-9.622711,30.417426),(-9.638173,30.426663),(-9.655141,30.442206),(-9.666249,30.459296),(-9.691762,30.509589),(-9.700063,30.542711),(-9.708404,30.547512),(-9.719553,30.548529),(-9.730824,30.552069),(-9.739817,30.559882),(-9.758168,30.586819),(-9.829661,30.628607),(-9.850942,30.629625),(-9.874013,30.633979),(-9.888539,30.648261),(-9.886708,30.686672),(-9.865631,30.72427),(-9.839019,30.759833),(-9.820221,30.792304),(-9.81371,30.814683),(-9.812896,30.827135),(-9.816803,30.836656),(-9.823842,30.845649),(-9.824371,30.851955),(-9.821889,30.859117),(-9.820221,30.87108),(-9.827707,31.06745),(-9.831451,31.085354),(-9.847524,31.121283),(-9.835032,31.144761),(-9.808949,31.2862),(-9.80663,31.343451),(-9.810902,31.366848),(-9.821523,31.379462),(-9.834788,31.388821),(-9.847524,31.402411),(-9.816233,31.436835),(-9.792958,31.47134),(-9.769643,31.53148),(-9.758168,31.545803),(-9.739613,31.560004),(-9.733266,31.567369),(-9.727651,31.58515),(-9.713612,31.597846),(-9.707631,31.60932),(-9.694203,31.625718),(-9.68928,31.635199),(-9.675201,31.715399),(-9.667307,31.731147),(-9.575795,31.816107),(-9.53539,31.864488),(-9.527943,31.871243),(-9.513295,31.880845),(-9.504954,31.888414),(-9.497426,31.898139),(-9.488678,31.915351),(-9.483795,31.922553),(-9.366119,32.026313),(-9.354075,32.046698),(-9.346425,32.06151),(-9.334828,32.10163),(-9.333079,32.118069),(-9.328114,32.130439),(-9.291982,32.168931),(-9.27774,32.196601),(-9.270009,32.227484),(-9.26476,32.330634),(-9.268951,32.335517),(-9.28775,32.343492),(-9.291982,32.350816),(-9.289662,32.372463),(-9.283355,32.387763),(-9.256256,32.432563),(-9.24885,32.452541),(-9.246938,32.472317),(-9.254791,32.488267),(-9.263661,32.498481),(-9.272369,32.512926),(-9.27831,32.529527),(-9.278961,32.546332),(-9.259918,32.57689),(-9.112172,32.682847),(-8.998525,32.797105),(-8.901682,32.854804),(-8.867787,32.881903),(-8.754709,33.010647),(-8.62914,33.127631),(-8.62149,33.13935),(-8.620351,33.152004),(-8.621002,33.173529),(-8.611887,33.186265),(-8.529164,33.268704),(-8.521148,33.272528),(-8.512522,33.270494),(-8.502797,33.261542),(-8.49413,33.259508),(-8.469797,33.260647),(-8.45165,33.264228),(-8.415028,33.280015),(-8.378774,33.304674),(-8.320221,33.365383),(-8.284657,33.389838),(-8.243153,33.404527),(-8.106557,33.430854),(-8.011545,33.466417),(-7.962554,33.484809),(-7.916249,33.494574),(-7.891428,33.503363),(-7.86974,33.526557),(-7.844797,33.535956),(-7.777984,33.55329),(-7.738189,33.570624),(-7.719472,33.574205),(-7.700999,33.58275),(-7.684438,33.599921),(-7.667551,33.612698),(-7.647857,33.608344),(-7.63622,33.614569),(-7.626617,33.613227),(-7.617258,33.609361),(-7.606191,33.608344),(-7.596669,33.611558),(-7.579254,33.620754),(-7.549957,33.625556),(-7.529124,33.632636),(-7.510243,33.641547),(-7.49706,33.64997),(-7.463287,33.68651),(-7.434316,33.698228),(-7.406361,33.726996),(-7.387115,33.732489),(-7.393951,33.725043),(-7.37385,33.719306),(-7.35261,33.724677),(-7.341135,33.731106),(-7.267486,33.772406),(-7.229319,33.80093),(-7.192942,33.817694),(-7.152577,33.830064),(-7.117014,33.834866),(-7.116567,33.834906),(-7.099477,33.840277),(-7.06786,33.863674),(-7.031809,33.874254),(-6.927358,33.944159),(-6.822092,34.039618),(-6.733754,34.162584),(-6.667795,34.280504),(-6.557932,34.417711),(-6.54776,34.434719),(-6.530914,34.474026),(-6.507924,34.504788),(-6.292104,34.880805),(-6.205393,35.124579),(-6.023915,35.501166),(-6.018544,35.520209),(-6.016672,35.544623),(-6.012318,35.558824),(-5.990834,35.598538),(-5.970041,35.652533),(-5.968251,35.660956),(-5.96524,35.670233),(-5.952056,35.685492),(-5.949045,35.69538),(-5.943105,35.742377),(-5.936187,35.765611),(-5.927235,35.780748),(-5.90803,35.797349),(-5.873402,35.801988),(-5.781402,35.79092),(-5.769276,35.792792),(-5.74234,35.814887),(-5.729888,35.822659),(-5.711741,35.830634),(-5.693512,35.834296),(-5.680898,35.829169),(-5.663442,35.835883),(-5.639719,35.836371),(-5.615956,35.831529),(-5.598988,35.822333),(-5.540028,35.850979),(-5.523264,35.863267),(-5.487457,35.896959),(-5.468861,35.910346),(-5.44811,35.918524),(-5.440027,35.918106),(-5.435452,35.914417),(-5.423497,35.908956),(-5.414198,35.909398),(-5.410361,35.917073),(-5.408,35.924748),(-5.40549,35.926519)] +Monaco [(7.437454,43.743361),(7.432845,43.739853),(7.417957,43.730904),(7.404319,43.717969),(7.380723,43.719273),(7.36575,43.72273),(7.367263,43.734125),(7.372655,43.745832),(7.387538,43.757899),(7.406969,43.763506),(7.426246,43.755464),(7.437454,43.743361)] +Moldova [(27.606873,48.457819),(27.627026,48.451256),(27.751773,48.451979),(27.78526,48.441566),(27.849855,48.40963),(27.864841,48.398907),(27.885371,48.378444),(27.896674,48.367178),(27.904529,48.362475),(27.92644,48.339428),(27.967057,48.328886),(28.003177,48.325883),(28.055941,48.321496),(28.076405,48.314933),(28.092838,48.302066),(28.098315,48.284108),(28.078678,48.244912),(28.093251,48.237444),(28.115575,48.236747),(28.131078,48.239589),(28.162084,48.257185),(28.178517,48.258864),(28.185752,48.242379),(28.189369,48.223052),(28.199911,48.211735),(28.216965,48.208144),(28.240322,48.211632),(28.261716,48.219952),(28.277529,48.229124),(28.294479,48.236488),(28.340575,48.240106),(28.357731,48.238607),(28.36817,48.230623),(28.37003,48.211632),(28.363364,48.191013),(28.352253,48.181866),(28.337887,48.175484),(28.322178,48.163211),(28.315563,48.149284),(28.317424,48.135358),(28.328586,48.127012),(28.349566,48.129725),(28.364966,48.141507),(28.37556,48.156648),(28.388634,48.168586),(28.411578,48.170704),(28.427288,48.163366),(28.436899,48.149853),(28.435659,48.134686),(28.419019,48.122232),(28.447441,48.082751),(28.459379,48.074457),(28.479584,48.064923),(28.490023,48.065491),(28.493744,48.074819),(28.494157,48.091846),(28.49979,48.108914),(28.501082,48.112827),(28.501113,48.112889),(28.519323,48.149129),(28.541596,48.155951),(28.573635,48.154969),(28.665619,48.129337),(28.735072,48.128691),(28.771246,48.124454),(28.799255,48.111793),(28.805921,48.103809),(28.80835,48.096574),(28.809176,48.089779),(28.811554,48.082906),(28.827573,48.057016),(28.830777,48.030868),(28.832534,48.024822),(28.839252,48.018285),(28.855685,48.007923),(28.862085,48.000502),(28.882557,47.976763),(28.914803,47.953146),(28.936087,47.942164),(28.950356,47.934801),(28.980846,47.926378),(29.017226,47.931081),(29.061047,47.96976),(29.092725,47.980173),(29.110037,47.979656),(29.123989,47.975987),(29.136288,47.968184),(29.147967,47.955369),(29.155822,47.939866),(29.164607,47.905604),(29.172565,47.891006),(29.186621,47.883642),(29.225999,47.87558),(29.236024,47.870723),(29.232768,47.85708),(29.21742,47.842895),(29.19892,47.829485),(29.186724,47.818219),(29.177733,47.800701),(29.177836,47.78972),(29.187448,47.783209),(29.221968,47.774811),(29.234732,47.766801),(29.238608,47.756001),(29.22667,47.743237),(29.196956,47.717502),(29.191479,47.686264),(29.192409,47.650917),(29.182074,47.613219),(29.156184,47.582781),(29.130501,47.55963),(29.117426,47.533327),(29.130397,47.4932),(29.130501,47.493097),(29.130604,47.493045),(29.130656,47.492942),(29.137189,47.484008),(29.140009,47.480152),(29.155615,47.449999),(29.163884,47.439379),(29.182074,47.429871),(29.192409,47.435814),(29.201866,47.446588),(29.21835,47.451601),(29.232613,47.44633),(29.2507,47.425375),(29.281396,47.411474),(29.288217,47.400777),(29.292713,47.388866),(29.300826,47.378194),(29.314675,47.372717),(29.330385,47.370495),(29.345836,47.365844),(29.35891,47.352718),(29.364078,47.336879),(29.364491,47.322436),(29.367592,47.308225),(29.370882,47.304434),(29.380821,47.29298),(29.394464,47.284712),(29.409553,47.279751),(29.425573,47.278666),(29.441696,47.282128),(29.459163,47.293497),(29.466087,47.307449),(29.470635,47.322746),(29.480867,47.338274),(29.501072,47.339825),(29.520968,47.33892),(29.539881,47.334218),(29.556573,47.324038),(29.57006,47.306778),(29.579259,47.283601),(29.580189,47.26045),(29.568717,47.243138),(29.544015,47.23425),(29.540398,47.212546),(29.55063,47.160172),(29.544842,47.135574),(29.530373,47.123688),(29.508669,47.119399),(29.480867,47.117487),(29.478593,47.114645),(29.47787,47.111544),(29.478696,47.108469),(29.480867,47.10524),(29.511459,47.066017),(29.520141,47.059919),(29.530993,47.066017),(29.539726,47.078885),(29.551353,47.090202),(29.570164,47.091442),(29.583393,47.085215),(29.594865,47.074595),(29.6021,47.061005),(29.60303,47.04576),(29.595433,47.032143),(29.583393,47.02279),(29.572489,47.011757),(29.564996,46.974498),(29.560626,46.961256),(29.559828,46.95884),(29.558691,46.94574),(29.567476,46.934656),(29.573161,46.933725),(29.598482,46.935379),(29.607577,46.93202),(29.623287,46.91954),(29.631865,46.914398),(29.648092,46.910419),(29.680855,46.908559),(29.696151,46.904683),(29.712481,46.893444),(29.735838,46.867192),(29.754132,46.85802),(29.785758,46.854661),(29.815213,46.856624),(29.843635,46.854144),(29.872212,46.837711),(29.876915,46.830786),(29.884873,46.812673),(29.889627,46.80717),(29.898516,46.806653),(29.907714,46.810942),(29.917429,46.813965),(29.928178,46.809754),(29.930658,46.803087),(29.930452,46.781642),(29.931795,46.772443),(29.935671,46.765157),(29.946678,46.750739),(29.951122,46.743117),(29.952621,46.724694),(29.944404,46.662476),(29.94027,46.650797),(29.935413,46.641857),(29.931899,46.632374),(29.931279,46.619171),(29.934948,46.608836),(29.947402,46.588346),(29.949675,46.578863),(29.9381,46.55734),(29.916086,46.554369),(29.898826,46.553129),(29.901926,46.53083),(29.916086,46.518815),(29.960217,46.505948),(29.962078,46.503442),(29.967039,46.493856),(29.970553,46.491737),(29.977064,46.493184),(29.989259,46.498687),(29.994944,46.498532),(30.00285,46.494217),(30.009413,46.488068),(30.021712,46.470653),(30.014064,46.462023),(30.060005,46.436805),(30.077006,46.422826),(30.086928,46.428873),(30.102017,46.430733),(30.118244,46.428692),(30.131576,46.422826),(30.107185,46.391898),(30.08114,46.374199),(30.037267,46.368928),(29.918669,46.373656),(29.902546,46.371176),(29.884666,46.3642),(29.847769,46.341462),(29.828132,46.339395),(29.808185,46.354691),(29.80617,46.361564),(29.806738,46.380891),(29.805085,46.389986),(29.80033,46.398358),(29.779557,46.421095),(29.72695,46.455796),(29.714134,46.47117),(29.713824,46.443058),(29.702869,46.42833),(29.682715,46.42293),(29.654396,46.422697),(29.647988,46.416393),(29.652949,46.391898),(29.645508,46.375594),(29.632072,46.36606),(29.615639,46.361822),(29.598586,46.363063),(29.582979,46.369651),(29.56944,46.382286),(29.555643,46.404197),(29.541432,46.413034),(29.527479,46.416651),(29.49606,46.420811),(29.480867,46.425152),(29.475079,46.432257),(29.473322,46.439802),(29.475286,46.447554),(29.480867,46.455512),(29.486241,46.462488),(29.488205,46.469361),(29.486448,46.475872),(29.480867,46.482048),(29.457612,46.484709),(29.456724,46.484366),(29.436838,46.476699),(29.418235,46.462488),(29.374723,46.416186),(29.362114,46.415928),(29.344234,46.434169),(29.320773,46.468741),(29.306717,46.471997),(29.289147,46.451636),(29.285943,46.439492),(29.290697,46.419261),(29.290077,46.410243),(29.283256,46.397427),(29.278192,46.395877),(29.27137,46.397427),(29.259175,46.394353),(29.222898,46.366473),(29.200677,46.35712),(29.183727,46.367171),(29.183417,46.37761),(29.190342,46.387196),(29.199282,46.396497),(29.205638,46.406109),(29.207602,46.417891),(29.206775,46.502511),(29.200212,46.523983),(29.184244,46.538039),(29.183059,46.538042),(29.162747,46.538091),(29.074948,46.503674),(29.055915,46.49874),(29.020326,46.489515),(28.945809,46.454788),(28.925448,46.432774),(28.919247,46.404662),(28.927309,46.368024),(28.944879,46.32074),(28.945809,46.304978),(28.939918,46.286995),(28.93289,46.272629),(28.93351,46.258986),(28.950615,46.243122),(28.95077,46.24307),(28.984112,46.221221),(29.009836,46.204364),(29.015365,46.182609),(29.00348,46.158941),(28.980846,46.132121),(28.946429,46.105094),(28.938781,46.089281),(28.941158,46.064683),(28.958935,46.021016),(28.956868,46.001379),(28.93196,45.993163),(28.757603,45.961175),(28.74024,45.953217),(28.729181,45.938644),(28.728406,45.921953),(28.742307,45.887329),(28.746441,45.870586),(28.745046,45.850484),(28.738276,45.837565),(28.725564,45.82878),(28.706392,45.821132),(28.677298,45.816584),(28.669753,45.812037),(28.669392,45.806301),(28.671924,45.797257),(28.673267,45.78687),(28.669753,45.77731),(28.643605,45.76651),(28.576684,45.761911),(28.560613,45.743204),(28.563525,45.735494),(28.567641,45.7246),(28.56144,45.71659),(28.532501,45.710079),(28.515241,45.702018),(28.504182,45.693698),(28.480928,45.669462),(28.474003,45.657938),(28.482891,45.650755),(28.498498,45.644295),(28.511314,45.635045),(28.516895,45.620989),(28.518755,45.607036),(28.523096,45.593239),(28.536893,45.579803),(28.510435,45.571018),(28.504596,45.567246),(28.503743,45.566102),(28.498239,45.558719),(28.497981,45.556445),(28.500048,45.554585),(28.506456,45.520582),(28.502012,45.508748),(28.480928,45.501978),(28.416849,45.503787),(28.341918,45.517636),(28.270501,45.521512),(28.270423,45.521471),(28.217275,45.493348),(28.217171,45.493193),(28.217171,45.493142),(28.20849,45.481411),(28.201565,45.468854),(28.199498,45.461774),(28.172936,45.484357),(28.165908,45.494589),(28.165391,45.528282),(28.164048,45.530607),(28.161567,45.532726),(28.157743,45.538927),(28.140949,45.560218),(28.118004,45.572723),(28.062142,45.593601),(28.074751,45.604866),(28.091184,45.615976),(28.107721,45.6244),(28.120846,45.627707),(28.153713,45.6275),(28.167975,45.632461),(28.161774,45.645432),(28.163738,45.661503),(28.154953,45.761807),(28.146478,45.771161),(28.128908,45.795035),(28.113302,45.825369),(28.110511,45.854308),(28.114955,45.859734),(28.128184,45.8664),(28.131078,45.871361),(28.129115,45.875134),(28.120226,45.887846),(28.117436,45.895236),(28.118779,45.903142),(28.12281,45.910791),(28.124981,45.918387),(28.120846,45.926293),(28.114852,45.933218),(28.112371,45.939213),(28.110511,45.950426),(28.08612,46.000552),(28.082709,46.014712),(28.084466,46.024582),(28.096869,46.05967),(28.096558,46.065045),(28.090461,46.06799),(28.090151,46.073365),(28.092838,46.078377),(28.100796,46.081995),(28.107823,46.096103),(28.110506,46.101491),(28.127358,46.135325),(28.133249,46.159974),(28.144721,46.183229),(28.141517,46.191962),(28.135626,46.198835),(28.129321,46.204674),(28.110976,46.225603),(28.108961,46.23413),(28.120846,46.237851),(28.132112,46.239918),(28.134489,46.245344),(28.131078,46.262397),(28.135212,46.269322),(28.144928,46.272939),(28.156296,46.275368),(28.165753,46.27883),(28.177794,46.287047),(28.191333,46.307769),(28.192883,46.311231),(28.191953,46.323504),(28.187922,46.343787),(28.190351,46.351074),(28.202392,46.353916),(28.207146,46.358153),(28.212934,46.388694),(28.219548,46.393345),(28.226796,46.395548),(28.228643,46.39611),(28.233294,46.401768),(28.22606,46.415359),(28.240219,46.420268),(28.246058,46.427865),(28.247247,46.436185),(28.247144,46.467191),(28.2458,46.475511),(28.242338,46.476518),(28.2381,46.475588),(28.234121,46.478069),(28.221099,46.495768),(28.219032,46.503726),(28.221099,46.541191),(28.224768,46.548736),(28.234121,46.553129),(28.225439,46.569562),(28.230504,46.583902),(28.240529,46.596382),(28.247144,46.607156),(28.24735,46.620825),(28.245085,46.631451),(28.24425,46.635372),(28.234121,46.662424),(28.178104,46.739836),(28.178156,46.758646),(28.137796,46.80624),(28.121518,46.8343),(28.122615,46.84227),(28.124257,46.854195),(28.124257,46.861637),(28.113095,46.87143),(28.114335,46.883393),(28.11356,46.894761),(28.096869,46.902616),(28.105447,46.91768),(28.104994,46.920185),(28.102295,46.935121),(28.082709,46.971527),(28.069067,46.988503),(28.038146,47.015483),(28.037027,47.016459),(28.028036,47.03297),(28.008295,47.026304),(27.986591,47.033228),(27.96313,47.043383),(27.938739,47.046638),(27.938429,47.061056),(27.925923,47.068756),(27.897604,47.081417),(27.867012,47.104645),(27.85771,47.109322),(27.848202,47.111415),(27.843757,47.114386),(27.849855,47.121724),(27.849855,47.12852),(27.80655,47.144617),(27.794665,47.155831),(27.805879,47.158234),(27.807687,47.162471),(27.804793,47.168492),(27.802106,47.176346),(27.800349,47.176966),(27.788309,47.204277),(27.763039,47.226317),(27.752393,47.238926),(27.753634,47.251432),(27.733273,47.275617),(27.722835,47.283317),(27.697823,47.287502),(27.689865,47.290887),(27.68232,47.295254),(27.671727,47.299853),(27.6447,47.303987),(27.636948,47.306674),(27.624029,47.321428),(27.599948,47.360728),(27.588724,47.367389),(27.586409,47.368764),(27.572353,47.375197),(27.580311,47.405996),(27.562534,47.416538),(27.565531,47.428269),(27.569356,47.438553),(27.574782,47.446252),(27.582998,47.450671),(27.575867,47.460412),(27.563154,47.468344),(27.548168,47.474261),(27.534526,47.477982),(27.532975,47.477413),(27.50724,47.477982),(27.501453,47.479945),(27.497525,47.482426),(27.492564,47.484545),(27.483676,47.485423),(27.473134,47.491779),(27.466726,47.506352),(27.459491,47.533224),(27.456908,47.533896),(27.446056,47.534877),(27.442128,47.536634),(27.440061,47.541027),(27.440268,47.550096),(27.438976,47.553713),(27.435824,47.55994),(27.431342,47.572638),(27.429404,47.57813),(27.428382,47.581024),(27.397066,47.589086),(27.369161,47.60831),(27.304049,47.666549),(27.281104,47.693007),(27.272009,47.71497),(27.295057,47.718174),(27.295057,47.724427),(27.289579,47.731687),(27.29113,47.74241),(27.288114,47.75068),(27.287512,47.752332),(27.282448,47.755691),(27.264671,47.764553),(27.260847,47.769075),(27.256196,47.77755),(27.244879,47.792588),(27.231082,47.807083),(27.219196,47.813775),(27.253406,47.828089),(27.245809,47.83659),(27.234906,47.840208),(27.222813,47.842662),(27.212375,47.847933),(27.213202,47.854134),(27.211548,47.885011),(27.212375,47.889507),(27.194185,47.904054),(27.17155,47.912632),(27.160698,47.921727),(27.178268,47.937928),(27.178268,47.942096),(27.178268,47.944129),(27.171964,47.946429),(27.150983,47.957797),(27.162869,47.965006),(27.169793,47.973791),(27.16876,47.983067),(27.157184,47.991955),(27.143748,47.986839),(27.134602,48.000456),(27.121476,48.013194),(27.095793,48.005598),(27.093364,48.00844),(27.091452,48.011851),(27.090005,48.015623),(27.088971,48.019809),(27.109332,48.026088),(27.109332,48.033503),(27.083184,48.043658),(27.059206,48.05805),(27.041739,48.077273),(27.034298,48.101768),(27.036882,48.107349),(27.047424,48.116496),(27.047955,48.121409),(27.048044,48.122232),(27.042773,48.127296),(27.033678,48.132386),(27.025099,48.135048),(27.012697,48.128123),(26.99399,48.132412),(26.966602,48.143367),(26.966602,48.149594),(26.986239,48.150421),(26.997607,48.15794),(26.997607,48.16657),(26.963088,48.175381),(26.955646,48.186),(26.950582,48.197524),(26.938128,48.204811),(26.929085,48.199049),(26.917716,48.187964),(26.908001,48.184528),(26.90397,48.201452),(26.897665,48.208971),(26.855497,48.237832),(26.844749,48.23331),(26.821908,48.252534),(26.804906,48.25827),(26.76372,48.252741),(26.744031,48.255583),(26.733127,48.27075),(26.722379,48.259769),(26.711475,48.261319),(26.688531,48.274832),(26.665741,48.274212),(26.617889,48.258968),(26.618613,48.267184),(26.625124,48.282894),(26.636079,48.294883),(26.6691,48.30881),(26.67401,48.321703),(26.679797,48.330178),(26.699434,48.325113),(26.712974,48.314907),(26.723619,48.302582),(26.735918,48.291834),(26.754573,48.286149),(26.774365,48.287183),(26.785734,48.294108),(26.790075,48.307053),(26.789351,48.32594),(26.78408,48.345164),(26.778189,48.357204),(26.777518,48.36617),(26.78806,48.375963),(26.793589,48.376273),(26.810074,48.371881),(26.816947,48.371726),(26.825628,48.377772),(26.828419,48.385136),(26.831933,48.391363),(26.842785,48.39374),(26.875961,48.383999),(26.908724,48.36524),(26.943244,48.351262),(26.981071,48.35568),(26.990579,48.362372),(26.997814,48.361545),(27.004635,48.358755),(27.015591,48.359401),(27.027683,48.357747),(27.033057,48.360202),(27.031817,48.36524),(27.02851,48.370795),(27.027786,48.374774),(27.0282,48.381389),(27.025409,48.389864),(27.02634,48.397099),(27.037398,48.399683),(27.048044,48.397667),(27.068818,48.388882),(27.175788,48.361804),(27.208551,48.360615),(27.246481,48.373741),(27.25193,48.37831),(27.306012,48.42366),(27.342186,48.436114),(27.36141,48.432807),(27.389832,48.415005),(27.403474,48.411491),(27.420217,48.417149),(27.480885,48.451411),(27.50383,48.472365),(27.503896,48.472365),(27.545171,48.472365),(27.557057,48.474355),(27.582998,48.486034),(27.604806,48.484122),(27.606873,48.457819)] +Macedonia [(22.345023,42.313439),(22.443622,42.214427),(22.481449,42.193317),(22.494678,42.164559),(22.506939,42.148927),(22.510181,42.144793),(22.531058,42.129109),(22.617771,42.082704),(22.627177,42.079127),(22.675856,42.060612),(22.705725,42.055935),(22.710272,42.05299),(22.713993,42.048623),(22.718437,42.044463),(22.725052,42.042474),(22.77063,42.043998),(22.780862,42.043171),(22.785306,42.039141),(22.787684,42.032578),(22.791094,42.025808),(22.798949,42.021235),(22.805977,42.02139),(22.821273,42.025369),(22.826958,42.025085),(22.838223,42.019478),(22.843701,42.014465),(22.845621,42.007408),(22.845768,42.006869),(22.846595,41.993639),(22.846905,41.993484),(22.85476,41.982632),(22.857137,41.971884),(22.858894,41.94788),(22.866335,41.924884),(22.877084,41.902043),(22.878634,41.895015),(22.878221,41.880261),(22.880804,41.872691),(22.882088,41.871618),(22.885042,41.869151),(22.896721,41.864448),(22.901372,41.860418),(22.907676,41.848584),(22.918322,41.814348),(22.939716,41.776702),(22.945917,41.769338),(22.956872,41.765669),(22.98054,41.764739),(22.991185,41.760992),(23.008859,41.739934),(23.009582,41.71637),(22.998627,41.693115),(22.985435,41.677198),(22.976613,41.666553),(22.970101,41.652032),(22.967001,41.647046),(22.961523,41.644488),(22.945813,41.641077),(22.940852,41.63764),(22.936098,41.626168),(22.932998,41.612345),(22.932068,41.597953),(22.933721,41.584595),(22.936925,41.57891),(22.946434,41.567748),(22.948707,41.560978),(22.94788,41.555139),(22.943023,41.538551),(22.943599,41.523201),(22.946227,41.453233),(22.94757,41.448376),(22.953358,41.438195),(22.954598,41.432408),(22.952118,41.427705),(22.940542,41.416905),(22.937339,41.410755),(22.939406,41.389413),(22.94447,41.368432),(22.940852,41.349829),(22.916978,41.335773),(22.826027,41.340992),(22.796818,41.337039),(22.780966,41.334894),(22.762293,41.3225),(22.751303,41.315205),(22.742003,41.28703),(22.740865,41.283579),(22.736731,41.204411),(22.727222,41.165809),(22.71575,41.145603),(22.704898,41.139661),(22.691875,41.14457),(22.674099,41.15661),(22.666347,41.164517),(22.661903,41.172268),(22.657185,41.176986),(22.656115,41.178056),(22.64454,41.180227),(22.629347,41.177074),(22.625936,41.169788),(22.626763,41.160796),(22.624489,41.152631),(22.607333,41.135992),(22.590176,41.125139),(22.586634,41.124085),(22.571263,41.119507),(22.549248,41.118525),(22.516589,41.122246),(22.500673,41.122142),(22.481449,41.11775),(22.467496,41.115011),(22.451477,41.113667),(22.421814,41.114649),(22.410446,41.117905),(22.389258,41.128343),(22.380163,41.131702),(22.367658,41.132374),(22.342336,41.128964),(22.323422,41.128498),(22.315051,41.124416),(22.308746,41.124984),(22.306679,41.128447),(22.305232,41.141624),(22.302649,41.1455),(22.29345,41.147515),(22.262961,41.150461),(22.225134,41.159608),(22.213637,41.160684),(22.205807,41.161416),(22.183173,41.159918),(22.160332,41.151908),(22.124365,41.127207),(22.103384,41.121522),(22.095943,41.123641),(22.062767,41.13718),(22.060286,41.140022),(22.058632,41.145087),(22.055532,41.149892),(22.048194,41.151856),(22.04406,41.149944),(22.033828,41.141263),(22.029074,41.138575),(21.965098,41.124364),(21.934712,41.11191),(21.925545,41.106754),(21.909081,41.097493),(21.901226,41.090775),(21.897195,41.081266),(21.896333,41.064705),(21.896162,41.061422),(21.894301,41.053826),(21.880659,41.038426),(21.845002,41.012381),(21.831463,40.993726),(21.831359,40.993675),(21.831359,40.993623),(21.831256,40.99352),(21.793636,40.973572),(21.783714,40.964167),(21.781853,40.955899),(21.78175,40.945099),(21.778133,40.93373),(21.765524,40.923911),(21.757091,40.922506),(21.736998,40.919157),(21.685115,40.927994),(21.6569,40.918227),(21.654833,40.9143),(21.652662,40.901381),(21.648838,40.895799),(21.643877,40.894456),(21.629511,40.895076),(21.623724,40.894404),(21.613698,40.888306),(21.590341,40.870685),(21.581556,40.866292),(21.55365,40.870426),(21.509519,40.900502),(21.505731,40.900903),(21.42942,40.908977),(21.404926,40.908615),(21.381258,40.900502),(21.344878,40.873062),(21.329271,40.866292),(21.295372,40.860866),(21.260955,40.860815),(21.245824,40.863226),(21.209072,40.869083),(21.183027,40.870168),(21.112127,40.853942),(20.965262,40.849394),(20.964849,40.875956),(20.956684,40.894766),(20.939941,40.907065),(20.890228,40.918279),(20.837415,40.924066),(20.836544,40.923904),(20.816951,40.920242),(20.783672,40.899055),(20.766102,40.893732),(20.740883,40.89797),(20.730573,40.904611),(20.717216,40.913214),(20.702746,40.936314),(20.683419,40.99383),(20.664092,41.059149),(20.65386,41.075272),(20.643008,41.081576),(20.634129,41.082576),(20.631536,41.082868),(20.618927,41.082403),(20.605284,41.083488),(20.597419,41.086273),(20.576966,41.093513),(20.569938,41.107104),(20.570558,41.124829),(20.565494,41.147412),(20.549681,41.170615),(20.51268,41.210147),(20.500071,41.23552),(20.483121,41.289471),(20.477747,41.319598),(20.478108,41.321585),(20.481674,41.341199),(20.49604,41.337788),(20.510407,41.344403),(20.523429,41.356805),(20.532937,41.370447),(20.539965,41.387139),(20.540172,41.400678),(20.539049,41.402944),(20.534074,41.412977),(20.522189,41.42569),(20.514644,41.429462),(20.498004,41.431477),(20.490873,41.436025),(20.488909,41.441451),(20.486842,41.457781),(20.483535,41.46548),(20.481597,41.468269),(20.470822,41.483774),(20.463174,41.489768),(20.452012,41.493592),(20.444984,41.508475),(20.447878,41.53545),(20.444157,41.549661),(20.49294,41.557671),(20.507409,41.56227),(20.520845,41.568368),(20.52932,41.574879),(20.534694,41.585266),(20.53467,41.587324),(20.534591,41.594026),(20.513404,41.640405),(20.508339,41.661748),(20.500381,41.734095),(20.503275,41.744637),(20.511337,41.757943),(20.521155,41.767658),(20.54441,41.784763),(20.550921,41.793522),(20.550136,41.80006),(20.54844,41.814193),(20.540482,41.839437),(20.540786,41.844865),(20.541722,41.86158),(20.567147,41.873182),(20.590298,41.854733),(20.602391,41.849876),(20.61872,41.850522),(20.626162,41.855198),(20.637014,41.870365),(20.643422,41.873647),(20.652827,41.86928),(20.671844,41.849307),(20.681456,41.84401),(20.702953,41.849591),(20.714398,41.859163),(20.723313,41.866619),(20.739953,41.888039),(20.750495,41.906797),(20.751052,41.910218),(20.754423,41.930904),(20.751439,41.940338),(20.741814,41.970773),(20.743054,41.993484),(20.755353,42.042784),(20.765378,42.064333),(20.784912,42.082032),(20.810543,42.092936),(20.90417,42.116668),(20.975145,42.134658),(21.003916,42.141951),(21.029238,42.151408),(21.04094,42.15997),(21.074403,42.184455),(21.098484,42.195953),(21.106236,42.195798),(21.112954,42.194402),(21.12639,42.188925),(21.164423,42.16704),(21.199873,42.14115),(21.216203,42.121151),(21.225402,42.106785),(21.229298,42.103822),(21.237804,42.097354),(21.245727,42.096167),(21.28886,42.089706),(21.299299,42.091411),(21.300796,42.098425),(21.301263,42.10061),(21.300332,42.120893),(21.298782,42.129419),(21.295785,42.134794),(21.293718,42.140168),(21.294958,42.148979),(21.353766,42.215977),(21.360602,42.220114),(21.366788,42.223858),(21.384255,42.224943),(21.419085,42.215021),(21.429834,42.215848),(21.428697,42.222566),(21.421462,42.231351),(21.419912,42.240058),(21.436345,42.24688),(21.44792,42.244141),(21.457222,42.237035),(21.467557,42.235123),(21.471973,42.23913),(21.48151,42.247784),(21.499287,42.238663),(21.519854,42.239025),(21.561815,42.247164),(21.564066,42.246289),(21.575044,42.242022),(21.624654,42.242772),(21.65969,42.235563),(21.676886,42.234945),(21.67695,42.234943),(21.69204,42.242022),(21.706509,42.25507),(21.719521,42.260957),(21.8172,42.305145),(21.837354,42.308556),(21.877352,42.30822),(21.88438,42.309512),(21.918279,42.331345),(21.929028,42.335117),(21.941534,42.333102),(21.994967,42.312612),(22.027627,42.303956),(22.045407,42.302424),(22.060906,42.301088),(22.095529,42.305817),(22.233402,42.348889),(22.259757,42.369095),(22.268852,42.370335),(22.273296,42.365477),(22.27402,42.348476),(22.276914,42.341241),(22.29159,42.328399),(22.307609,42.31933),(22.325283,42.314318),(22.345023,42.313439)] +Mali [(-4.821226,24.994755),(-4.744925,24.947057),(-4.668677,24.899334),(-4.592351,24.851688),(-4.516025,24.803991),(-4.404946,24.731308),(-4.325235,24.679218),(-4.245498,24.627077),(-4.165865,24.574987),(-4.086154,24.522897),(-4.006495,24.470807),(-3.926732,24.418717),(-3.846996,24.366576),(-3.767336,24.314434),(-3.687625,24.262344),(-3.608018,24.210203),(-3.528281,24.158113),(-3.448544,24.106023),(-3.368808,24.053959),(-3.289123,24.001844),(-3.209489,23.949702),(-3.129649,23.897612),(-3.043065,23.840923),(-2.956404,23.784234),(-2.869768,23.727623),(-2.783107,23.670985),(-2.696446,23.614348),(-2.609836,23.557685),(-2.523226,23.500996),(-2.436513,23.444358),(-2.349852,23.387747),(-2.26319,23.331109),(-2.176632,23.274446),(-2.089919,23.217757),(-2.00331,23.161042),(-1.916648,23.104456),(-1.830039,23.047819),(-1.743326,22.991182),(-1.656716,22.93457),(-1.570054,22.877881),(-1.483496,22.821166),(-1.396783,22.764555),(-1.310122,22.707969),(-1.223512,22.65128),(-1.136903,22.594643),(-1.05019,22.537954),(-0.96358,22.481265),(-0.876918,22.424627),(-0.790309,22.368041),(-0.703647,22.311404),(-0.616934,22.254767),(-0.530325,22.198078),(-0.443663,22.141389),(-0.357028,22.084751),(-0.270392,22.028114),(-0.183731,21.971477),(-0.097044,21.914839),(-0.010408,21.85815),(0.003735,21.848899),(0.076253,21.801461),(0.162966,21.744824),(0.249499,21.688238),(0.33616,21.631601),(0.422795,21.574963),(0.509457,21.518274),(0.596067,21.461585),(0.682676,21.404896),(0.769389,21.34831),(0.855999,21.291673),(0.942609,21.235036),(1.029322,21.178347),(1.146524,21.101711),(1.15934,21.081505),(1.177943,21.017323),(1.180114,20.995309),(1.167505,20.886013),(1.145284,20.795889),(1.14456,20.776252),(1.147247,20.751448),(1.154585,20.738787),(1.168538,20.733464),(1.191276,20.73057),(1.212463,20.73088),(1.252254,20.738994),(1.273338,20.739407),(1.296696,20.733464),(1.310545,20.722716),(1.331526,20.687937),(1.346925,20.669127),(1.363978,20.657707),(1.40718,20.645046),(1.447487,20.638741),(1.465781,20.633522),(1.483454,20.622618),(1.520351,20.616986),(1.559729,20.597504),(1.623704,20.551253),(1.643961,20.522676),(1.650059,20.487019),(1.649232,20.412089),(1.659154,20.397516),(1.778113,20.304291),(1.799197,20.294886),(1.820901,20.293594),(1.838885,20.29592),(1.855008,20.294835),(1.870614,20.283543),(1.880329,20.263054),(1.883843,20.24414),(1.891388,20.231789),(1.913402,20.231092),(1.924254,20.23613),(1.941204,20.251116),(1.95526,20.254915),(1.967146,20.253416),(1.975621,20.248429),(1.983372,20.241918),(1.993397,20.235949),(2.056339,20.215046),(2.071222,20.213263),(2.097474,20.224193),(2.138195,20.260728),(2.161346,20.274939),(2.18243,20.278505),(2.200826,20.273906),(2.21819,20.264087),(2.279581,20.21794),(2.316478,20.180165),(2.348208,20.137635),(2.388722,20.067407),(2.400401,20.056555),(2.415697,20.051284),(2.439882,20.04609),(2.459312,20.038778),(2.495382,20.020097),(2.514812,20.015937),(2.525665,20.015162),(2.616925,19.998367),(2.671805,19.996222),(2.946001,19.941652),(3.072608,19.88889),(3.130485,19.845224),(3.147022,19.837938),(3.183195,19.827731),(3.198802,19.820523),(3.212754,19.807758),(3.216785,19.794064),(3.198285,19.592397),(3.199422,19.553769),(3.212238,19.517156),(3.217509,19.511162),(3.222883,19.508061),(3.228051,19.504159),(3.232288,19.495478),(3.231668,19.489044),(3.22619,19.4692),(3.225984,19.459692),(3.234769,19.441347),(3.247481,19.426464),(3.25823,19.410393),(3.260813,19.388327),(3.250995,19.36546),(3.232701,19.351843),(3.211514,19.340862),(3.192911,19.325798),(3.183816,19.307505),(3.178855,19.268722),(3.17441,19.251643),(3.152706,19.230197),(3.13927,19.221929),(3.134206,19.212859),(3.126558,19.193352),(3.111779,19.171337),(3.102684,19.153561),(3.10413,19.135526),(3.120874,19.112814),(3.138754,19.096045),(3.158597,19.08155),(3.179785,19.07),(3.225984,19.05106),(3.284895,18.995741),(3.308356,18.981685),(3.318381,18.977706),(3.333057,18.975561),(3.358689,18.976853),(3.439717,18.995638),(3.439821,18.995638),(3.54462,19.015068),(3.715566,19.046901),(3.790291,19.06077),(3.886512,19.07863),(4.057561,19.110437),(4.22861,19.142244),(4.229023,19.018582),(4.229436,18.894946),(4.22985,18.771284),(4.230263,18.647648),(4.230271,18.645374),(4.230677,18.524038),(4.23109,18.400325),(4.231504,18.276741),(4.231917,18.153105),(4.232227,18.029443),(4.232408,17.975234),(4.23264,17.905782),(4.233054,17.78212),(4.233364,17.658458),(4.233777,17.534796),(4.234294,17.411186),(4.234707,17.287525),(4.235018,17.163915),(4.235328,17.100818),(4.235638,16.995863),(4.222305,16.986561),(4.21166,16.986044),(4.203702,16.982789),(4.197811,16.965219),(4.19657,16.947132),(4.202048,16.848895),(4.197604,16.838508),(4.184581,16.818509),(4.181998,16.809621),(4.182308,16.746472),(4.183031,16.612682),(4.183444,16.526538),(4.183961,16.416053),(4.1759,16.392644),(4.16174,16.379983),(4.118229,16.358331),(4.094768,16.340812),(4.075647,16.321072),(4.060558,16.298334),(3.971158,16.086099),(3.96692,16.058504),(3.970848,16.030857),(3.98325,16.00135),(3.983973,16.00011),(3.98449,15.998766),(3.984697,15.997371),(3.984594,15.995924),(3.9848,15.989826),(3.98418,15.986881),(3.98325,15.983987),(3.925062,15.927608),(3.909869,15.904767),(3.903462,15.886318),(3.89447,15.78865),(3.886512,15.750099),(3.873849,15.720882),(3.871215,15.714804),(3.846101,15.685297),(3.808377,15.665582),(3.728899,15.65088),(3.692208,15.63145),(3.614074,15.547734),(3.526534,15.495954),(3.516508,15.469186),(3.507103,15.353973),(3.48881,15.357539),(3.483332,15.359296),(3.380393,15.376324),(3.19229,15.40751),(3.073021,15.427199),(3.03354,15.42645),(3.017521,15.422832),(3.010286,15.417665),(3.007806,15.407665),(3.005842,15.389294),(3.005739,15.35232),(3.000158,15.339117),(2.950651,15.337463),(2.85412,15.334207),(2.757485,15.331081),(2.660953,15.327825),(2.564215,15.324595),(2.467684,15.321417),(2.371049,15.318239),(2.274517,15.314984),(2.177882,15.311831),(2.081351,15.308576),(1.984612,15.305398),(1.888081,15.302194),(1.791446,15.29899),(1.694914,15.295734),(1.598383,15.292608),(1.501748,15.289352),(1.405216,15.286148),(1.331526,15.283616),(1.297832,15.275735),(1.270857,15.259897),(1.203161,15.198789),(1.123063,15.126313),(1.057537,15.067118),(0.973718,14.991257),(0.949327,14.979552),(0.922145,14.973971),(0.769183,14.969062),(0.739934,14.958339),(0.711408,14.947461),(0.683813,14.940872),(0.670067,14.939735),(0.514831,14.993556),(0.483515,14.992109),(0.418791,14.969888),(0.387035,14.963248),(0.353187,14.963429),(0.221257,14.995933),(0.213196,14.985417),(0.212782,14.960716),(0.218467,14.910977),(-0.033197,14.995933),(-0.033404,14.995933),(-0.166988,15.049677),(-0.236699,15.065619),(-0.299176,15.054741),(-0.361472,15.017741),(-0.397671,15.002135),(-0.425732,15.0026),(-0.435602,15.015157),(-0.458649,15.075463),(-0.4679,15.079908),(-0.500343,15.079721),(-0.719719,15.078461),(-0.752895,15.069727),(-0.771272,15.056619),(-0.782816,15.048385),(-0.836249,14.996088),(-0.836404,14.995985),(-1.043138,14.818062),(-1.043317,14.817908),(-1.07856,14.796359),(-1.116697,14.780443),(-1.307745,14.734657),(-1.350275,14.714969),(-1.69692,14.496119),(-1.766683,14.483174),(-1.836963,14.479582),(-1.919129,14.485861),(-1.967033,14.483742),(-1.997057,14.470694),(-2.005015,14.444236),(-2.023412,14.198643),(-2.027288,14.188127),(-2.035918,14.181229),(-2.085008,14.159668),(-2.104337,14.151179),(-2.11984,14.148776),(-2.151879,14.15614),(-2.385612,14.264712),(-2.46168,14.280912),(-2.516147,14.267864),(-2.597382,14.222311),(-2.619758,14.203604),(-2.676265,14.141729),(-2.69319,14.123196),(-2.840855,14.042994),(-2.867288,14.000542),(-2.861552,14.00173),(-2.858606,14.000232),(-2.85703,13.997777),(-2.855377,13.996175),(-2.89447,13.866571),(-2.912169,13.837942),(-2.928059,13.799624),(-2.923383,13.746035),(-2.895245,13.651648),(-2.930473,13.638523),(-2.965008,13.625655),(-2.97232,13.624467),(-2.979322,13.627567),(-2.986402,13.632063),(-2.994774,13.634983),(-3.019113,13.637515),(-3.026968,13.635345),(-3.038621,13.629583),(-3.05601,13.61085),(-3.067508,13.606767),(-3.07451,13.622141),(-3.077301,13.636791),(-3.08221,13.646222),(-3.100039,13.662733),(-3.125102,13.67728),(-3.146031,13.67666),(-3.167941,13.672112),(-3.195821,13.674903),(-3.240418,13.707976),(-3.267057,13.717045),(-3.286952,13.69777),(-3.266282,13.682344),(-3.259719,13.658315),(-3.263905,13.602659),(-3.269176,13.579095),(-3.283955,13.542198),(-3.248634,13.292781),(-3.262406,13.283919),(-3.42653,13.27423),(-3.448544,13.265781),(-3.452265,13.237514),(-3.440586,13.202839),(-3.439475,13.184855),(-3.449475,13.16881),(-3.461593,13.165761),(-3.473922,13.167601),(-3.516111,13.1739),(-3.538487,13.173409),(-3.54505,13.174494),(-3.553913,13.180256),(-3.569958,13.196767),(-3.576599,13.199299),(-3.589802,13.197387),(-3.596882,13.199402),(-3.678711,13.26175),(-3.724419,13.288828),(-3.798626,13.347145),(-3.817101,13.35469),(-3.85808,13.365516),(-3.8926,13.378926),(-3.908878,13.381975),(-3.928825,13.38027),(-3.948411,13.380838),(-3.971613,13.386755),(-3.984042,13.39647),(-3.971613,13.40833),(-3.963009,13.413162),(-3.942726,13.431946),(-3.934923,13.434892),(-3.925544,13.436313),(-3.918593,13.440318),(-3.917973,13.451066),(-3.923399,13.453754),(-3.94748,13.458198),(-3.956059,13.46166),(-3.959288,13.467939),(-3.964482,13.487808),(-3.965468,13.489217),(-3.970321,13.496154),(-3.974094,13.498945),(-3.977737,13.499926),(-3.981251,13.49897),(-3.984481,13.496051),(-3.997968,13.480522),(-3.992232,13.476233),(-3.979468,13.47538),(-3.971613,13.469954),(-3.97691,13.460627),(-3.990217,13.449129),(-4.005358,13.439517),(-4.016029,13.43577),(-4.028199,13.431533),(-4.043495,13.414454),(-4.052539,13.409002),(-4.079307,13.402129),(-4.087549,13.397995),(-4.104267,13.382698),(-4.114654,13.364534),(-4.131578,13.323839),(-4.147106,13.299603),(-4.16602,13.278157),(-4.176872,13.272369),(-4.186458,13.272834),(-4.195837,13.274695),(-4.205501,13.272989),(-4.220668,13.262835),(-4.23878,13.246789),(-4.253508,13.22909),(-4.258107,13.21413),(-4.251209,13.204751),(-4.230021,13.193149),(-4.227773,13.184442),(-4.234801,13.175605),(-4.24617,13.172479),(-4.310197,13.175553),(-4.327044,13.168551),(-4.339601,13.135298),(-4.345906,13.127133),(-4.351073,13.118322),(-4.351073,13.106075),(-4.345363,13.097057),(-4.316398,13.070857),(-4.289733,13.01347),(-4.276918,12.996236),(-4.24785,12.971948),(-4.229324,12.948952),(-4.221314,12.921254),(-4.224647,12.864513),(-4.211883,12.819193),(-4.213278,12.807178),(-4.23413,12.74235),(-4.243974,12.729922),(-4.245472,12.728936),(-4.257642,12.72093),(-4.276298,12.714677),(-4.297227,12.712145),(-4.310921,12.716021),(-4.339446,12.73279),(-4.36885,12.738991),(-4.402026,12.736562),(-4.435254,12.728423),(-4.464296,12.717261),(-4.46437,12.717251),(-4.474942,12.715762),(-4.481711,12.717416),(-4.485251,12.714677),(-4.491323,12.662794),(-4.482538,12.646258),(-4.439078,12.613288),(-4.42249,12.597217),(-4.401406,12.550398),(-4.392647,12.537427),(-4.387247,12.533965),(-4.386885,12.530192),(-4.393448,12.516446),(-4.407607,12.497946),(-4.426624,12.479653),(-4.443678,12.459447),(-4.451636,12.435314),(-4.415359,12.350307),(-4.406135,12.307467),(-4.435823,12.301731),(-4.444814,12.309431),(-4.452669,12.320283),(-4.462488,12.328189),(-4.47719,12.327311),(-4.488171,12.320696),(-4.490703,12.313823),(-4.490496,12.305762),(-4.49401,12.290104),(-4.492253,12.278838),(-4.493545,12.272844),(-4.497421,12.26871),(-4.585529,12.197241),(-4.560466,12.149492),(-4.570233,12.138898),(-4.600309,12.137555),(-4.636121,12.117556),(-4.646663,12.098022),(-4.648678,12.081951),(-4.652737,12.071627),(-4.653716,12.069135),(-4.673586,12.05973),(-4.683715,12.059058),(-4.704023,12.061487),(-4.714617,12.059007),(-4.725133,12.050118),(-4.732281,12.037263),(-4.738983,12.02521),(-4.746889,12.015082),(-4.761281,12.006607),(-4.789522,12.001801),(-4.806808,11.996271),(-4.826238,12.012705),(-4.847245,12.013066),(-4.889955,11.997925),(-4.910677,11.998132),(-4.932071,12.003144),(-4.95375,12.005108),(-4.975454,11.996271),(-4.984523,11.988572),(-4.994238,11.983249),(-5.004703,11.980665),(-5.016046,11.981285),(-5.034313,11.97927),(-5.073768,11.98051),(-5.089323,11.97927),(-5.103947,11.972759),(-5.136994,11.953122),(-5.167819,11.943665),(-5.182909,11.930901),(-5.209471,11.901497),(-5.248228,11.870439),(-5.268227,11.843051),(-5.275151,11.837418),(-5.282489,11.836436),(-5.288019,11.839123),(-5.293445,11.843206),(-5.300163,11.846358),(-5.306519,11.846048),(-5.311066,11.842896),(-5.314839,11.83933),(-5.319025,11.837418),(-5.353803,11.831734),(-5.357058,11.829615),(-5.364552,11.82176),(-5.369874,11.820158),(-5.37561,11.822225),(-5.387909,11.830804),(-5.392302,11.832354),(-5.405944,11.830442),(-5.412352,11.82853),(-5.412197,11.823569),(-5.405996,11.812303),(-5.400415,11.810185),(-5.374525,11.79525),(-5.370649,11.791064),(-5.353286,11.794527),(-5.344656,11.793907),(-5.334269,11.790806),(-5.314787,11.782486),(-5.298974,11.772668),(-5.28714,11.758922),(-5.279544,11.739026),(-5.278562,11.721456),(-5.280681,11.699494),(-5.289259,11.660426),(-5.294788,11.650298),(-5.302281,11.639859),(-5.307811,11.629007),(-5.307604,11.617638),(-5.299956,11.606424),(-5.290964,11.604461),(-5.280732,11.605753),(-5.269467,11.604099),(-5.233914,11.575987),(-5.224663,11.54077),(-5.224612,11.45801),(-5.219186,11.435143),(-5.218307,11.422198),(-5.22642,11.41349),(-5.248176,11.403181),(-5.263472,11.390184),(-5.267865,11.37202),(-5.26094,11.267737),(-5.262852,11.251588),(-5.275255,11.230711),(-5.306726,11.199395),(-5.316182,11.176322),(-5.322332,11.135549),(-5.332512,11.12157),(-5.356283,11.106894),(-5.373026,11.099763),(-5.390131,11.094699),(-5.489764,11.082115),(-5.504233,11.072684),(-5.507334,11.056949),(-5.505602,11.047985),(-5.495603,10.996203),(-5.501804,10.97021),(-5.479118,10.975533),(-5.465579,10.947886),(-5.447027,10.877993),(-5.43509,10.856909),(-5.431421,10.844688),(-5.445322,10.786991),(-5.445012,10.778568),(-5.446459,10.768698),(-5.45297,10.763969),(-5.461186,10.760042),(-5.467956,10.752678),(-5.473072,10.737873),(-5.482632,10.684233),(-5.482115,10.675215),(-5.477154,10.658808),(-5.475914,10.650385),(-5.460566,10.644571),(-5.470488,10.635605),(-5.477413,10.61956),(-5.47855,10.604238),(-5.471057,10.597365),(-5.468111,10.58783),(-5.48165,10.535327),(-5.505163,10.499179),(-5.508987,10.490937),(-5.5171,10.439984),(-5.522578,10.425489),(-5.549708,10.435643),(-5.571722,10.44988),(-5.584383,10.454247),(-5.594047,10.453937),(-5.621797,10.446935),(-5.677556,10.441508),(-5.806282,10.413474),(-5.87806,10.37606),(-5.893305,10.365027),(-5.904829,10.348284),(-5.908963,10.330068),(-5.904725,10.275291),(-5.916404,10.266635),(-5.963016,10.282733),(-5.974747,10.273638),(-5.978313,10.248626),(-5.985237,10.227284),(-5.997123,10.208189),(-6.015933,10.18987),(-6.105333,10.189276),(-6.180884,10.215838),(-6.19432,10.224183),(-6.214009,10.247851),(-6.224809,10.255034),(-6.240002,10.251933),(-6.243309,10.289011),(-6.240674,10.302576),(-6.228323,10.31609),(-6.225894,10.314488),(-6.22114,10.310354),(-6.21437,10.307796),(-6.206154,10.310819),(-6.203984,10.316038),(-6.205379,10.322627),(-6.207808,10.328518),(-6.208324,10.33198),(-6.183933,10.358852),(-6.198764,10.370815),(-6.195664,10.389212),(-6.180574,10.420218),(-6.196904,10.439157),(-6.200366,10.448769),(-6.198196,10.457399),(-6.187499,10.475408),(-6.185793,10.481325),(-6.190289,10.491144),(-6.196129,10.494684),(-6.20419,10.494373),(-6.215662,10.492616),(-6.222432,10.494632),(-6.228168,10.500575),(-6.233491,10.507577),(-6.238658,10.512744),(-6.24765,10.51383),(-6.256022,10.511608),(-6.261293,10.514088),(-6.260931,10.529152),(-6.256228,10.537239),(-6.237935,10.551941),(-6.231372,10.560235),(-6.230028,10.572043),(-6.232871,10.58411),(-6.238658,10.597985),(-6.2307,10.606925),(-6.219797,10.61186),(-6.209771,10.617751),(-6.204449,10.629611),(-6.207808,10.637543),(-6.216903,10.645088),(-6.227755,10.65085),(-6.246617,10.657619),(-6.249459,10.665603),(-6.244446,10.706867),(-6.245841,10.720742),(-6.25597,10.726478),(-6.28,10.723274),(-6.303564,10.713171),(-6.322219,10.700485),(-6.341701,10.691442),(-6.367539,10.692268),(-6.388055,10.695524),(-6.409811,10.694387),(-6.427019,10.686093),(-6.433995,10.667929),(-6.435856,10.628706),(-6.430688,10.61496),(-6.419061,10.6077),(-6.406658,10.60186),(-6.399217,10.592481),(-6.402783,10.569123),(-6.42149,10.556592),(-6.445984,10.552251),(-6.466965,10.553543),(-6.52138,10.564214),(-6.537555,10.569692),(-6.578069,10.591138),(-6.598585,10.604909),(-6.613623,10.618474),(-6.633983,10.65302),(-6.647109,10.66134),(-6.669175,10.654157),(-6.667883,10.650901),(-6.681939,10.627389),(-6.684213,10.626562),(-6.688967,10.607855),(-6.691086,10.589432),(-6.689225,10.580931),(-6.685608,10.574007),(-6.682817,10.565971),(-6.687778,10.52047),(-6.697545,10.488301),(-6.695788,10.471197),(-6.683076,10.451689),(-6.675634,10.447865),(-6.664627,10.444557),(-6.653982,10.440036),(-6.647781,10.432698),(-6.647936,10.421871),(-6.653052,10.413061),(-6.659615,10.405361),(-6.663955,10.397997),(-6.66827,10.36584),(-6.668916,10.361022),(-6.677391,10.349034),(-6.700336,10.34167),(-6.722557,10.344047),(-6.760229,10.366113),(-6.782088,10.373037),(-6.803895,10.370867),(-6.862755,10.34384),(-6.88203,10.341256),(-6.938719,10.348336),(-6.96125,10.344874),(-6.973136,10.33229),(-6.997113,10.25276),(-6.994891,10.239402),(-6.984298,10.230384),(-6.971172,10.222065),(-6.961612,10.211032),(-6.95939,10.185503),(-6.971637,10.164419),(-6.992411,10.149097),(-7.015769,10.140881),(-7.040522,10.140054),(-7.058247,10.15597),(-7.073129,10.178527),(-7.089459,10.19757),(-7.106357,10.207259),(-7.204749,10.234493),(-7.284021,10.246559),(-7.346963,10.247903),(-7.363396,10.252192),(-7.371819,10.264517),(-7.372698,10.288598),(-7.366342,10.329448),(-7.372336,10.34477),(-7.395022,10.346217),(-7.422204,10.336089),(-7.431402,10.333737),(-7.444425,10.334202),(-7.445768,10.340378),(-7.443288,10.349964),(-7.444683,10.360816),(-7.461478,10.388643),(-7.465457,10.398617),(-7.46618,10.40748),(-7.465354,10.417996),(-7.46618,10.429494),(-7.471606,10.441095),(-7.480236,10.450293),(-7.489848,10.456107),(-7.501475,10.458639),(-7.515841,10.457812),(-7.539613,10.427633),(-7.547416,10.420502),(-7.556382,10.417272),(-7.574339,10.417531),(-7.584416,10.416523),(-7.607774,10.418719),(-7.643689,10.440475),(-7.664411,10.437142),(-7.670044,10.42877),(-7.673971,10.416394),(-7.679036,10.405929),(-7.687924,10.403087),(-7.69981,10.404534),(-7.708646,10.402467),(-7.722289,10.391331),(-7.722289,10.384484),(-7.726785,10.382882),(-7.736035,10.378282),(-7.723994,10.363606),(-7.735337,10.347096),(-7.757429,10.334047),(-7.777583,10.329862),(-7.764405,10.312912),(-7.776342,10.292732),(-7.778254,10.27834),(-7.783835,10.270434),(-7.791225,10.265783),(-7.797736,10.260279),(-7.80125,10.249453),(-7.805074,10.241831),(-7.829001,10.211652),(-7.838664,10.203719),(-7.847423,10.197932),(-7.857216,10.194418),(-7.882847,10.190826),(-7.892253,10.184832),(-7.910959,10.169406),(-7.929046,10.160957),(-7.949872,10.155428),(-7.970904,10.155066),(-7.989663,10.161991),(-7.96801,10.209998),(-7.962584,10.233252),(-7.9646,10.258936),(-7.971214,10.281802),(-7.981549,10.307021),(-7.996277,10.32826),(-8.015708,10.339344),(-8.070071,10.341876),(-8.096116,10.346734),(-8.115495,10.360247),(-8.120921,10.373037),(-8.122109,10.399496),(-8.125417,10.411665),(-8.135442,10.427323),(-8.142056,10.429649),(-8.150583,10.424533),(-8.165983,10.418099),(-8.18903,10.413629),(-8.210579,10.414068),(-8.228873,10.423422),(-8.253884,10.469827),(-8.284425,10.511246),(-8.295535,10.537446),(-8.311142,10.735289),(-8.315586,10.753092),(-8.341941,10.763246),(-8.339822,10.783865),(-8.318893,10.83952),(-8.311814,10.847246),(-8.305871,10.856289),(-8.303649,10.874893),(-8.305096,10.978246),(-8.311142,11.000803),(-8.326593,11.02385),(-8.347315,11.043126),(-8.369329,11.054236),(-8.381318,11.053926),(-8.400645,11.043332),(-8.410464,11.041911),(-8.429067,11.048293),(-8.438162,11.04974),(-8.448704,11.047105),(-8.469013,11.046381),(-8.489064,11.052737),(-8.505755,11.052789),(-8.531645,10.999046),(-8.541567,10.983775),(-8.55955,10.971605),(-8.575622,10.966748),(-8.593347,10.964707),(-8.611382,10.965146),(-8.628228,10.967833),(-8.647969,10.965818),(-8.665229,10.956955),(-8.680938,10.952304),(-8.696234,10.962743),(-8.70073,10.978452),(-8.696906,10.996048),(-8.68869,11.012559),(-8.679801,11.025194),(-8.63368,11.071289),(-8.623112,11.091262),(-8.622389,11.102605),(-8.624921,11.112191),(-8.624611,11.122035),(-8.615413,11.13405),(-8.607222,11.137151),(-8.586991,11.137461),(-8.578154,11.14206),(-8.569679,11.157796),(-8.563943,11.193426),(-8.551799,11.210738),(-8.544616,11.214975),(-8.5241,11.22376),(-8.515625,11.229057),(-8.51206,11.230298),(-8.502138,11.231176),(-8.498779,11.233501),(-8.497022,11.24071),(-8.499244,11.246705),(-8.502345,11.25164),(-8.50312,11.255412),(-8.492578,11.277788),(-8.483224,11.28492),(-8.44457,11.276264),(-8.426897,11.274197),(-8.406691,11.275282),(-8.388398,11.281406),(-8.376719,11.294661),(-8.371035,11.32055),(-8.381267,11.325098),(-8.39956,11.322152),(-8.417957,11.325511),(-8.42607,11.340472),(-8.414133,11.353468),(-8.393359,11.363003),(-8.375324,11.367654),(-8.397648,11.385895),(-8.427724,11.40008),(-8.488134,11.418193),(-8.51578,11.418968),(-8.527563,11.423387),(-8.535521,11.438088),(-8.539425,11.456312),(-8.543996,11.477647),(-8.549577,11.490127),(-8.575208,11.470283),(-8.602183,11.472092),(-8.656754,11.496431),(-8.667967,11.510875),(-8.679026,11.52984),(-8.687346,11.55002),(-8.690705,11.568029),(-8.712874,11.640066),(-8.726517,11.649471),(-8.740366,11.646164),(-8.756541,11.638826),(-8.777211,11.635932),(-8.795195,11.641926),(-8.81168,11.651745),(-8.828526,11.659186),(-8.847233,11.657946),(-8.797004,11.913227),(-8.79783,11.925113),(-8.803205,11.934932),(-8.809974,11.94444),(-8.814909,11.955395),(-8.816434,11.976841),(-8.815452,11.995703),(-8.819793,12.012653),(-8.837983,12.028156),(-8.858757,12.031825),(-8.88165,12.029189),(-8.903715,12.030378),(-8.922112,12.045364),(-8.926298,12.064278),(-8.921957,12.086033),(-8.906971,12.125359),(-8.906041,12.147735),(-8.913896,12.169853),(-8.927021,12.187371),(-8.942008,12.195846),(-8.961696,12.187991),(-8.97384,12.187578),(-8.981178,12.198946),(-8.984537,12.20892),(-8.994278,12.224836),(-8.99756,12.23481),(-8.995906,12.26101),(-8.985261,12.282094),(-8.972135,12.301989),(-8.963092,12.32421),(-8.964745,12.346276),(-8.975907,12.368704),(-8.993839,12.387514),(-9.027765,12.404751),(-9.147318,12.465493),(-9.189486,12.479239),(-9.265864,12.495207),(-9.278938,12.494432),(-9.286379,12.488128),(-9.294079,12.483787),(-9.308187,12.488955),(-9.321519,12.496603),(-9.327307,12.497533),(-9.33418,12.496293),(-9.350872,12.484614),(-9.398155,12.473245),(-9.412573,12.455365),(-9.407251,12.445133),(-9.392781,12.428028),(-9.374694,12.41113),(-9.347151,12.396454),(-9.344464,12.389012),(-9.343947,12.380124),(-9.339167,12.370616),(-9.331648,12.366326),(-9.314801,12.362657),(-9.309169,12.357748),(-9.308497,12.345036),(-9.312889,12.32607),(-9.321829,12.310206),(-9.335007,12.306537),(-9.331906,12.282766),(-9.336816,12.269846),(-9.360173,12.246644),(-9.421513,12.257082),(-9.438877,12.254757),(-9.479598,12.235843),(-9.495876,12.224681),(-9.515616,12.20706),(-9.628167,12.170163),(-9.66,12.149802),(-9.675141,12.133989),(-9.682273,12.118538),(-9.683668,12.101485),(-9.681549,12.080814),(-9.686303,12.068153),(-9.698809,12.050997),(-9.722994,12.025417),(-9.778649,12.026657),(-9.796632,12.032342),(-9.806813,12.038439),(-9.823039,12.050893),(-9.833684,12.055131),(-9.840661,12.055028),(-9.861125,12.051875),(-9.870736,12.052082),(-9.888772,12.060557),(-9.923188,12.087584),(-9.941533,12.092751),(-9.961584,12.096007),(-9.996414,12.114145),(-10.015534,12.119881),(-10.027678,12.125669),(-10.04809,12.141379),(-10.060182,12.147528),(-10.070363,12.149854),(-10.087002,12.150577),(-10.09034,12.151584),(-10.097286,12.153678),(-10.105192,12.158639),(-10.118835,12.170163),(-10.128654,12.174503),(-10.135837,12.175485),(-10.160228,12.174503),(-10.179762,12.178224),(-10.21485,12.194606),(-10.247819,12.201065),(-10.254124,12.207215),(-10.258981,12.213778),(-10.26694,12.217808),(-10.304974,12.202874),(-10.31102,12.19104),(-10.313603,12.191143),(-10.316497,12.196879),(-10.323577,12.201995),(-10.325592,12.199773),(-10.329882,12.19042),(-10.339338,12.185459),(-10.348433,12.184787),(-10.354118,12.18086),(-10.353394,12.166494),(-10.368225,12.171506),(-10.37484,12.174814),(-10.381403,12.180136),(-10.39458,12.17161),(-10.428945,12.143394),(-10.435973,12.135178),(-10.445688,12.120708),(-10.493489,12.124429),(-10.511628,12.118073),(-10.512661,12.108461),(-10.504445,12.088359),(-10.507959,12.084586),(-10.517312,12.080349),(-10.517674,12.070737),(-10.514883,12.060144),(-10.51509,12.052909),(-10.535399,12.038698),(-10.555449,12.029344),(-10.566508,12.017252),(-10.55948,11.995186),(-10.574983,11.990329),(-10.595653,11.97989),(-10.613792,11.967694),(-10.621543,11.957669),(-10.625264,11.943872),(-10.634152,11.925423),(-10.645159,11.90837),(-10.655081,11.898965),(-10.669964,11.89204),(-10.711357,11.890386),(-10.740347,11.919894),(-10.781017,11.99622),(-10.807785,12.022833),(-10.812436,12.033427),(-10.811041,12.04154),(-10.801222,12.059213),(-10.798535,12.068102),(-10.804943,12.095955),(-10.822926,12.110476),(-10.846387,12.12138),(-10.869642,12.138433),(-10.909794,12.200135),(-10.927675,12.212951),(-10.952117,12.219462),(-10.972013,12.218583),(-11.015473,12.204424),(-11.038779,12.205251),(-11.052318,12.202512),(-11.059811,12.192435),(-11.072782,12.149492),(-11.084306,12.136573),(-11.116604,12.113732),(-11.117477,12.112702),(-11.122081,12.107272),(-11.136292,12.085103),(-11.14425,12.081331),(-11.152725,12.080866),(-11.159392,12.077507),(-11.165644,12.04862),(-11.176342,12.029499),(-11.191173,12.01441),(-11.206986,12.010172),(-11.223315,12.009294),(-11.25551,11.996168),(-11.274992,11.996271),(-11.294681,12.003093),(-11.315144,12.013325),(-11.334678,12.026192),(-11.351318,12.040403),(-11.391729,12.093733),(-11.409557,12.107893),(-11.470794,12.134609),(-11.489604,12.151197),(-11.507794,12.191608),(-11.491671,12.220909),(-11.463249,12.249951),(-11.444594,12.289484),(-11.444904,12.312531),(-11.451467,12.352115),(-11.447229,12.374543),(-11.431675,12.382966),(-11.407594,12.381933),(-11.388628,12.384465),(-11.388422,12.403895),(-11.386561,12.430457),(-11.379792,12.456864),(-11.377776,12.480221),(-11.390437,12.497533),(-11.392607,12.491848),(-11.400514,12.479549),(-11.402374,12.488541),(-11.408679,12.504923),(-11.410849,12.513346),(-11.416999,12.529314),(-11.42475,12.526368),(-11.430383,12.515723),(-11.429814,12.508333),(-11.437876,12.515361),(-11.449451,12.535205),(-11.456686,12.539753),(-11.467797,12.543525),(-11.460614,12.549829),(-11.43984,12.559286),(-11.437359,12.570758),(-11.438599,12.577993),(-11.440925,12.584866),(-11.441803,12.595511),(-11.436636,12.627086),(-11.436842,12.637473),(-11.441752,12.647756),(-11.449555,12.653182),(-11.457151,12.655973),(-11.460975,12.658402),(-11.461905,12.673129),(-11.455756,12.680622),(-11.447953,12.685945),(-11.437359,12.712248),(-11.424182,12.716383),(-11.410332,12.718811),(-11.402168,12.73173),(-11.404028,12.741213),(-11.41457,12.759713),(-11.41457,12.764209),(-11.407594,12.77147),(-11.405423,12.782348),(-11.406353,12.794285),(-11.408472,12.804491),(-11.411676,12.812888),(-11.416017,12.820071),(-11.419686,12.824671),(-11.420978,12.825575),(-11.423458,12.826402),(-11.428161,12.827022),(-11.432088,12.829347),(-11.432502,12.835523),(-11.430021,12.841052),(-11.427024,12.845238),(-11.425474,12.849553),(-11.428626,12.865805),(-11.424905,12.876166),(-11.419324,12.886501),(-11.415138,12.896656),(-11.417309,12.901953),(-11.423096,12.907069),(-11.427954,12.912495),(-11.427231,12.918618),(-11.420668,12.922029),(-11.413588,12.919703),(-11.407283,12.916293),(-11.402891,12.916396),(-11.394209,12.923321),(-11.387801,12.927119),(-11.384443,12.933114),(-11.386561,12.959107),(-11.388835,12.970553),(-11.393434,12.980811),(-11.401806,12.989492),(-11.404235,12.972103),(-11.411521,12.960709),(-11.423096,12.956006),(-11.438703,12.9589),(-11.435964,12.968848),(-11.433535,12.988356),(-11.433432,12.99696),(-11.430124,13.00099),(-11.424543,13.005202),(-11.422993,13.009414),(-11.431675,13.01347),(-11.435654,13.016726),(-11.43953,13.023005),(-11.445162,13.035226),(-11.45896,13.054682),(-11.456945,13.060444),(-11.451415,13.068067),(-11.450278,13.075095),(-11.46082,13.079177),(-11.477098,13.083285),(-11.489707,13.090778),(-11.501541,13.099589),(-11.515391,13.107754),(-11.533064,13.111811),(-11.538077,13.128011),(-11.538542,13.16297),(-11.547843,13.176199),(-11.559729,13.186922),(-11.569341,13.199195),(-11.572338,13.217101),(-11.568566,13.227902),(-11.555802,13.245911),(-11.554251,13.256866),(-11.55854,13.266504),(-11.581175,13.286141),(-11.605824,13.319653),(-11.613007,13.339058),(-11.613111,13.360813),(-11.620345,13.357532),(-11.632903,13.35438),(-11.643962,13.355594),(-11.646597,13.365516),(-11.645253,13.379753),(-11.649801,13.38412),(-11.674967,13.383215),(-11.694501,13.379184),(-11.70401,13.380373),(-11.714035,13.388099),(-11.719771,13.397891),(-11.726902,13.405798),(-11.741217,13.407813),(-11.756513,13.399803),(-11.76659,13.383164),(-11.772533,13.362674),(-11.775116,13.343347),(-11.817078,13.312341),(-11.822555,13.306708),(-11.828136,13.307277),(-11.840022,13.316889),(-11.844569,13.323839),(-11.850771,13.34314),(-11.854595,13.350556),(-11.862346,13.356085),(-11.888804,13.368875),(-11.897589,13.371175),(-11.899967,13.382182),(-11.885652,13.43577),(-11.883482,13.453547),(-11.890406,13.465148),(-11.898468,13.468507),(-11.907718,13.469644),(-11.918157,13.474708),(-11.923841,13.481142),(-11.932729,13.496051),(-11.939034,13.50295),(-11.996808,13.544161),(-12.015153,13.564444),(-12.037323,13.598267),(-12.049828,13.634363),(-12.070395,13.673249),(-12.083883,13.692964),(-12.097629,13.70441),(-12.012311,13.751177),(-11.978825,13.784819),(-11.962908,13.829467),(-11.956966,13.870007),(-11.956811,13.890342),(-11.962908,13.909152),(-11.980375,13.929642),(-11.99903,13.943569),(-12.015308,13.959304),(-12.025334,13.985246),(-12.02523,14.026742),(-12.002751,14.103456),(-11.995413,14.144022),(-11.997583,14.166165),(-12.03448,14.250268),(-12.044299,14.264919),(-12.058355,14.274091),(-12.097784,14.28807),(-12.10998,14.298146),(-12.119591,14.310575),(-12.127808,14.324295),(-12.113029,14.329592),(-12.108688,14.34202),(-12.115612,14.35512),(-12.208837,14.388761),(-12.22173,14.391242),(-12.21987,14.434598),(-12.222428,14.454933),(-12.234184,14.498574),(-12.236432,14.519451),(-12.230386,14.536685),(-12.211472,14.547976),(-12.204186,14.554255),(-12.201447,14.565184),(-12.200465,14.577354),(-12.198398,14.58756),(-12.191008,14.597999),(-12.171526,14.616422),(-12.165945,14.625181),(-12.165015,14.641872),(-12.172611,14.647918),(-12.182792,14.650244),(-12.18982,14.655954),(-12.192197,14.666884),(-12.190285,14.673653),(-12.185841,14.68081),(-12.180311,14.692825),(-12.191422,14.693445),(-12.207648,14.696598),(-12.222815,14.70329),(-12.230489,14.714555),(-12.236613,14.728456),(-12.256508,14.745794),(-12.26413,14.774939),(-12.246793,14.767007),(-12.224779,14.763441),(-12.203256,14.76618),(-12.160209,14.781011),(-12.138867,14.784525),(-12.123674,14.776644),(-12.081454,14.740032),(-12.070395,14.734399),(-12.062334,14.746259),(-12.057063,14.761942),(-12.049673,14.767213),(-12.03107,14.762821),(-12.011071,14.762743),(-11.991486,14.76804),(-11.973967,14.779848),(-11.950299,14.811552),(-11.935985,14.823618),(-11.895729,14.832067),(-11.877487,14.841524),(-11.862605,14.854082),(-11.854698,14.867311),(-11.850822,14.876483),(-11.845603,14.883227),(-11.840487,14.888498),(-11.837076,14.893097),(-11.833097,14.894699),(-11.826069,14.89656),(-11.820385,14.89997),(-11.820437,14.906404),(-11.827361,14.915576),(-11.8301,14.920331),(-11.830927,14.926429),(-11.825811,14.962473),(-11.820592,14.980275),(-11.813202,14.995933),(-11.813202,14.996088),(-11.811083,15.014304),(-11.81377,15.028541),(-11.82116,15.039755),(-11.832839,15.049005),(-11.839195,15.049005),(-11.844466,15.044328),(-11.851029,15.041951),(-11.860899,15.049005),(-11.859142,15.054069),(-11.856765,15.084248),(-11.845138,15.124556),(-11.844208,15.13484),(-11.847308,15.148741),(-11.848187,15.158146),(-11.845655,15.179075),(-11.826793,15.23256),(-11.821057,15.280102),(-11.816923,15.296096),(-11.783488,15.365885),(-11.767675,15.437198),(-11.754859,15.469083),(-11.729434,15.496058),(-11.727057,15.506987),(-11.727057,15.541171),(-11.70174,15.537425),(-11.69755,15.536805),(-11.670833,15.528407),(-11.644117,15.526444),(-11.614868,15.541171),(-11.579211,15.577965),(-11.562571,15.587241),(-11.535958,15.594915),(-11.524279,15.600289),(-11.515391,15.610082),(-11.513117,15.615043),(-11.512342,15.620185),(-11.513117,15.625275),(-11.515391,15.630262),(-11.519576,15.632742),(-11.522987,15.635248),(-11.525623,15.638349),(-11.527328,15.642561),(-11.524382,15.643465),(-11.515391,15.644421),(-11.458236,15.632949),(-11.434827,15.623389),(-11.409557,15.602201),(-11.316901,15.471667),(-11.298195,15.451048),(-11.045393,15.270206),(-11.012734,15.239588),(-10.98519,15.187498),(-10.948035,15.151996),(-10.915169,15.102904),(-10.906229,15.119776),(-10.890881,15.176749),(-10.882251,15.192846),(-10.855328,15.217651),(-10.844062,15.234549),(-10.834399,15.271395),(-10.827216,15.287698),(-10.811041,15.303124),(-10.800189,15.306845),(-10.790112,15.306845),(-10.78174,15.308421),(-10.770682,15.324673),(-10.754507,15.333639),(-10.746807,15.341132),(-10.738901,15.362164),(-10.740141,15.403583),(-10.736368,15.422626),(-10.725361,15.433064),(-10.709187,15.433865),(-10.64888,15.424874),(-10.607126,15.424434),(-10.587385,15.427251),(-10.584746,15.428127),(-10.551522,15.439162),(-10.534985,15.441694),(-10.515503,15.437741),(-10.500414,15.440351),(-10.398405,15.438697),(-10.370758,15.433504),(-10.322647,15.437095),(-10.308746,15.435209),(-10.223221,15.402033),(-10.214488,15.401981),(-10.196091,15.405288),(-10.188391,15.40472),(-10.167979,15.395185),(-10.131599,15.372629),(-10.108293,15.365885),(-10.067624,15.364748),(-9.951403,15.381207),(-9.835596,15.371104),(-9.797356,15.380303),(-9.740719,15.4126),(-9.720823,15.42092),(-9.672118,15.430661),(-9.42389,15.440532),(-9.435879,15.495903),(-9.435879,15.495954),(-9.451847,15.559206),(-9.451692,15.588326),(-9.437016,15.614888),(-9.375935,15.685917),(-9.356453,15.697854),(-9.332423,15.687571),(-9.329322,15.655247),(-9.342965,15.586931),(-9.349218,15.495644),(-9.175843,15.495593),(-9.141379,15.495581),(-9.018592,15.495541),(-9.003216,15.495526),(-8.911157,15.495438),(-8.843409,15.495438),(-8.769253,15.495438),(-8.68931,15.495438),(-8.60394,15.495386),(-8.470202,15.495283),(-8.327006,15.495283),(-8.175801,15.495205),(-8.017826,15.495128),(-7.854529,15.495076),(-7.6872,15.495024),(-7.517237,15.494973),(-7.345878,15.494921),(-7.174519,15.494818),(-7.004503,15.494818),(-6.837175,15.49474),(-6.673929,15.494663),(-6.516006,15.494611),(-6.364749,15.494559),(-6.320145,15.494543),(-6.221605,15.494508),(-6.087815,15.494456),(-6.010817,15.494378),(-5.938212,15.494353),(-5.870257,15.494353),(-5.807315,15.494353),(-5.673163,15.494301),(-5.515964,15.494249),(-5.515602,15.494146),(-5.515292,15.494042),(-5.514982,15.493913),(-5.514672,15.493836),(-5.514362,15.493732),(-5.514051,15.493629),(-5.513741,15.493526),(-5.51338,15.493422),(-5.513121,15.493422),(-5.512966,15.493422),(-5.51276,15.493422),(-5.512553,15.493422),(-5.512294,15.493422),(-5.512191,15.493422),(-5.511933,15.493422),(-5.511726,15.493422),(-5.511623,15.493526),(-5.511519,15.493681),(-5.511364,15.493732),(-5.511313,15.493887),(-5.511261,15.493991),(-5.511106,15.494042),(-5.510951,15.494197),(-5.510951,15.494301),(-5.510951,15.494508),(-5.510951,15.494663),(-5.510951,15.494818),(-5.510951,15.495076),(-5.510951,15.495283),(-5.510951,15.495438),(-5.510951,15.49567),(-5.510951,15.495903),(-5.509917,15.500812),(-5.508987,15.505695),(-5.508761,15.5069),(-5.508057,15.510656),(-5.507075,15.51554),(-5.488368,15.612666),(-5.469558,15.709792),(-5.4508,15.80684),(-5.431989,15.90394),(-5.413799,15.998559),(-5.395454,16.093179),(-5.377212,16.187799),(-5.358919,16.282366),(-5.353286,16.311977),(-5.354268,16.318385),(-5.355301,16.324793),(-5.360107,16.329909),(-5.364913,16.334921),(-5.404963,16.36169),(-5.445942,16.389027),(-5.485371,16.415433),(-5.529709,16.444992),(-5.566503,16.469487),(-5.60588,16.495893),(-5.614562,16.511861),(-5.623347,16.527829),(-5.627688,16.568137),(-5.63761,16.658364),(-5.647583,16.748643),(-5.657454,16.838818),(-5.667324,16.929097),(-5.677297,17.019324),(-5.687168,17.109499),(-5.697038,17.199726),(-5.70696,17.289954),(-5.716933,17.380181),(-5.726803,17.470356),(-5.736674,17.560583),(-5.746647,17.650758),(-5.756466,17.741037),(-5.766387,17.831264),(-5.776361,17.92144),(-5.78618,18.011667),(-5.79636,18.104374),(-5.80654,18.197082),(-5.816772,18.289892),(-5.826952,18.382548),(-5.837081,18.475333),(-5.847364,18.568067),(-5.857545,18.6608),(-5.867673,18.753585),(-5.877802,18.846318),(-5.888034,18.939052),(-5.898214,19.031785),(-5.908394,19.12457),(-5.914802,19.182887),(-5.92121,19.24123),(-5.927566,19.299547),(-5.934026,19.357941),(-5.949115,19.495478),(-5.949115,19.495529),(-5.949115,19.495581),(-5.949115,19.495633),(-5.963533,19.620612),(-5.977847,19.745618),(-5.992162,19.870597),(-6.00658,19.995525),(-6.020946,20.12053),(-6.035363,20.245484),(-6.049678,20.370489),(-6.064095,20.495443),(-6.076756,20.603343),(-6.083577,20.661892),(-6.098615,20.790722),(-6.113705,20.919551),(-6.120526,20.978204),(-6.134634,21.098868),(-6.148741,21.219533),(-6.162901,21.340197),(-6.177008,21.460862),(-6.191116,21.581578),(-6.205224,21.702242),(-6.219383,21.822855),(-6.233491,21.943571),(-6.247598,22.064236),(-6.261706,22.184952),(-6.275865,22.305616),(-6.289973,22.426281),(-6.304132,22.546997),(-6.318188,22.667661),(-6.332296,22.7883),(-6.346455,22.908965),(-6.360563,23.029655),(-6.371634,23.123981),(-6.374722,23.150293),(-6.388778,23.270958),(-6.402938,23.391674),(-6.417045,23.512339),(-6.431205,23.633029),(-6.445312,23.753719),(-6.45942,23.874409),(-6.466603,23.93624),(-6.482571,24.072304),(-6.498436,24.208368),(-6.505671,24.270277),(-6.506338,24.275967),(-6.515851,24.357067),(-6.525514,24.436727),(-6.535178,24.51636),(-6.54479,24.595993),(-6.554453,24.675549),(-6.564168,24.755234),(-6.57378,24.834868),(-6.583392,24.914424),(-6.593107,24.994134),(-6.371674,24.994238),(-6.150188,24.994341),(-5.928755,24.994444),(-5.707321,24.9946),(-5.485939,24.994703),(-5.264454,24.994806),(-5.043072,24.99491),(-4.821613,24.995065),(-4.821536,24.994961),(-4.821355,24.994806),(-4.821226,24.994755)] +Montenegro [(19.054991,43.5067),(19.076386,43.507242),(19.096023,43.512901),(19.122791,43.535948),(19.147699,43.538145),(19.195345,43.532796),(19.175191,43.509619),(19.175914,43.480887),(19.192244,43.454532),(19.218392,43.438202),(19.355645,43.393063),(19.372285,43.384226),(19.414039,43.338389),(19.473054,43.293276),(19.485146,43.280098),(19.502303,43.251935),(19.512431,43.240643),(19.547845,43.218815),(19.549948,43.217518),(19.580851,43.187804),(19.598111,43.176203),(19.618678,43.168245),(19.663016,43.158504),(19.684617,43.156721),(19.69733,43.160209),(19.705494,43.166178),(19.713556,43.165609),(19.742805,43.126516),(19.761202,43.108739),(19.781769,43.096466),(19.805127,43.089955),(19.838303,43.088353),(19.872203,43.090368),(19.883778,43.095691),(19.907136,43.113261),(19.916644,43.117059),(19.92915,43.113907),(19.936591,43.105897),(19.942276,43.095639),(19.949821,43.085924),(19.959742,43.07856),(20.019894,43.047348),(20.054388,43.022221),(20.056344,43.020796),(20.116942,42.976654),(20.129464,42.973605),(20.14092,42.970815),(20.19456,42.966836),(20.223189,42.957663),(20.275589,42.929887),(20.337084,42.906969),(20.35362,42.890975),(20.355171,42.86617),(20.345352,42.827439),(20.264427,42.817258),(20.226083,42.806768),(20.217608,42.802737),(20.209236,42.791704),(20.208409,42.782093),(20.20996,42.772972),(20.208409,42.763282),(20.183398,42.742508),(20.149498,42.749872),(20.112085,42.766538),(20.076325,42.773437),(20.065059,42.769458),(20.055638,42.763866),(20.034673,42.751423),(20.026508,42.743206),(20.024751,42.723414),(20.03612,42.707989),(20.037006,42.707363),(20.094205,42.666983),(20.101956,42.656674),(20.10392,42.653108),(20.090587,42.627348),(20.079218,42.61125),(20.075704,42.603085),(20.075394,42.586962),(20.078185,42.572906),(20.077048,42.55991),(20.064956,42.546758),(20.039221,42.557765),(20.017723,42.546241),(19.981757,42.510765),(19.956332,42.505314),(19.907549,42.506399),(19.882745,42.493609),(19.882745,42.493557),(19.882538,42.493402),(19.873339,42.486839),(19.835512,42.470251),(19.829063,42.468723),(19.819596,42.466479),(19.801406,42.468132),(19.784456,42.474566),(19.75159,42.493402),(19.73433,42.524382),(19.730919,42.533658),(19.730299,42.540428),(19.732159,42.555543),(19.733916,42.562597),(19.741358,42.574405),(19.746009,42.579934),(19.747766,42.578901),(19.746885,42.58893),(19.746009,42.5989),(19.737534,42.624402),(19.722134,42.64608),(19.699293,42.654814),(19.676039,42.646675),(19.658037,42.634613),(19.647927,42.627838),(19.621779,42.604997),(19.605035,42.584844),(19.599248,42.571046),(19.593667,42.54482),(19.588086,42.532857),(19.575683,42.522341),(19.561317,42.516243),(19.549328,42.508595),(19.543747,42.493557),(19.543747,42.493402),(19.531655,42.474773),(19.517806,42.45803),(19.501476,42.444129),(19.481735,42.434491),(19.468403,42.41811),(19.417243,42.374107),(19.412076,42.368397),(19.402671,42.352015),(19.400707,42.344755),(19.401327,42.331061),(19.400397,42.325893),(19.304589,42.215099),(19.274926,42.191276),(19.272033,42.180682),(19.281956,42.164723),(19.282058,42.164559),(19.297767,42.151666),(19.355025,42.12004),(19.369998,42.106507),(19.372491,42.104253),(19.374869,42.094667),(19.356575,42.064798),(19.351718,42.047615),(19.350581,42.027823),(19.354198,42.008703),(19.363396,41.993639),(19.363707,41.993484),(19.371045,41.98656),(19.365774,41.969713),(19.359779,41.965993),(19.351614,41.965166),(19.346447,41.961548),(19.352854,41.938501),(19.350477,41.931369),(19.346653,41.926176),(19.345413,41.921189),(19.34593,41.914471),(19.34531,41.910337),(19.347687,41.906358),(19.356989,41.89964),(19.364947,41.888995),(19.364223,41.862846),(19.365122,41.852372),(19.365082,41.852362),(19.346934,41.863959),(19.310232,41.894517),(19.293224,41.900784),(19.220225,41.91885),(19.202973,41.927069),(19.178477,41.933905),(19.170258,41.937974),(19.162283,41.947943),(19.161957,41.953437),(19.163259,41.95897),(19.16033,41.96898),(19.15561,41.970649),(19.145274,41.977607),(19.13795,41.985297),(19.142914,41.988837),(19.143565,41.993069),(19.139171,42.042426),(19.08253,42.081204),(19.074718,42.095649),(19.083832,42.110093),(19.076427,42.115953),(19.063975,42.120185),(19.048676,42.140204),(19.01059,42.139553),(19.002126,42.150214),(18.999848,42.161078),(18.994802,42.163642),(18.988048,42.163723),(18.981619,42.16706),(18.968028,42.188707),(18.953461,42.199856),(18.913341,42.222235),(18.901703,42.237494),(18.894705,42.270494),(18.885997,42.284369),(18.871593,42.290473),(18.854015,42.290473),(18.838878,42.285712),(18.831391,42.277533),(18.826508,42.282213),(18.820486,42.286689),(18.817638,42.291164),(18.801524,42.284369),(18.793956,42.280341),(18.788748,42.276028),(18.786388,42.274115),(18.778575,42.27147),(18.771983,42.276923),(18.762462,42.291164),(18.729503,42.311591),(18.714529,42.325263),(18.714122,42.338935),(18.708344,42.342475),(18.699718,42.34984),(18.693614,42.353217),(18.693614,42.359442),(18.695811,42.373765),(18.678477,42.385972),(18.658539,42.386623),(18.653168,42.366278),(18.646495,42.366278),(18.638438,42.370307),(18.61671,42.368069),(18.612315,42.36994),(18.607107,42.37641),(18.5949,42.383734),(18.580903,42.389838),(18.570649,42.392971),(18.573009,42.39643),(18.57309,42.397528),(18.574067,42.398261),(18.578136,42.400377),(18.552989,42.413642),(18.545177,42.42357),(18.550141,42.435126),(18.562836,42.438544),(18.644949,42.418362),(18.656505,42.415513),(18.685557,42.403998),(18.70045,42.392971),(18.708181,42.408515),(18.706554,42.421047),(18.683849,42.458808),(18.683279,42.468085),(18.687348,42.482896),(18.654145,42.451809),(18.608653,42.44538),(18.502452,42.455634),(18.502452,42.448188),(18.521251,42.437974),(18.51295,42.409003),(18.529796,42.400377),(18.510265,42.40526),(18.49643,42.416327),(18.497816,42.431158),(18.492855,42.442372),(18.475492,42.449813),(18.467741,42.453379),(18.454925,42.464722),(18.444279,42.477925),(18.437148,42.493402),(18.436425,42.510765),(18.442006,42.543012),(18.437355,42.559212),(18.44769,42.566214),(18.458956,42.569728),(18.470531,42.569056),(18.481797,42.563682),(18.492132,42.564767),(18.495852,42.570865),(18.493682,42.579831),(18.486654,42.58983),(18.506798,42.59849),(18.517247,42.602982),(18.538434,42.618304),(18.542832,42.626429),(18.549596,42.638923),(18.550009,42.668069),(18.539674,42.695457),(18.522518,42.71189),(18.502157,42.727445),(18.46743,42.769199),(18.453891,42.793151),(18.444589,42.817078),(18.443659,42.834467),(18.453478,42.845655),(18.465984,42.852812),(18.473322,42.862553),(18.467637,42.881699),(18.443969,42.916865),(18.434047,42.936889),(18.433531,42.954201),(18.452754,42.993398),(18.483037,43.014637),(18.538951,43.023887),(18.598379,43.024455),(18.638996,43.020243),(18.621116,43.09644),(18.620599,43.122563),(18.621128,43.124578),(18.629074,43.154886),(18.645301,43.180182),(18.688399,43.224469),(18.664318,43.233176),(18.679511,43.24948),(18.807151,43.318029),(18.833506,43.324153),(18.830302,43.328157),(18.824618,43.337408),(18.821207,43.341387),(18.839604,43.34782),(18.899135,43.351903),(18.923423,43.346838),(18.950295,43.333067),(18.957323,43.325858),(18.957943,43.318985),(18.957116,43.311828),(18.959493,43.303456),(18.968589,43.292216),(18.988949,43.272941),(18.989506,43.272016),(18.992463,43.267102),(19.002902,43.273949),(19.01086,43.28232),(19.017164,43.291157),(19.022535,43.296546),(19.024709,43.298728),(19.036285,43.303327),(19.062536,43.304386),(19.069668,43.30883),(19.039592,43.350714),(19.00993,43.410995),(18.975306,43.444274),(18.968278,43.448098),(18.946264,43.443938),(18.946368,43.44908),(18.950708,43.457297),(18.951225,43.463808),(18.937893,43.478949),(18.930658,43.482282),(18.915258,43.485383),(18.905647,43.490628),(18.90513,43.499051),(18.911021,43.507268),(18.920529,43.512203),(18.938926,43.518947),(18.962697,43.5383),(18.977477,43.546232),(19.000214,43.547886),(19.01427,43.537783),(19.025019,43.523029),(19.038145,43.511015),(19.054991,43.5067)] +Mongolia [(100.005968,51.731727),(100.098262,51.738652),(100.210296,51.726224),(100.510898,51.726895),(100.571101,51.704804),(100.638901,51.69204),(101.069469,51.553444),(101.117011,51.527838),(101.158766,51.521223),(101.200727,51.520913),(101.241551,51.515177),(101.279688,51.492595),(101.315448,51.463604),(101.350175,51.450452),(101.387795,51.450556),(101.482053,51.47288),(101.526392,51.475826),(101.569852,51.470089),(101.643697,51.450091),(101.696614,51.452442),(101.723692,51.450582),(101.742192,51.444845),(101.795316,51.419395),(101.821774,51.413581),(101.901873,51.417069),(101.920683,51.413039),(101.955616,51.393789),(101.97422,51.387226),(102.051217,51.383609),(102.074679,51.374824),(102.091267,51.364644),(102.183871,51.323897),(102.193379,51.307205),(102.179272,51.286431),(102.135295,51.240284),(102.133796,51.230853),(102.139688,51.220931),(102.147646,51.202638),(102.150023,51.185404),(102.148783,51.16879),(102.142168,51.134839),(102.146509,51.097632),(102.165371,51.057556),(102.191984,51.020582),(102.219373,50.992651),(102.229656,50.979267),(102.231051,50.964901),(102.225574,50.950741),(102.215238,50.938184),(102.239475,50.912294),(102.231878,50.88475),(102.212758,50.856742),(102.203043,50.829353),(102.216789,50.798864),(102.245676,50.778762),(102.307533,50.748221),(102.329392,50.718817),(102.320245,50.696131),(102.296836,50.674944),(102.275907,50.650191),(102.271566,50.620942),(102.282418,50.590608),(102.302933,50.563892),(102.327635,50.545546),(102.372697,50.533661),(102.471864,50.524927),(102.513101,50.503688),(102.586585,50.41527),(102.617798,50.399302),(102.619529,50.399009),(102.762595,50.374807),(102.887135,50.314966),(102.927391,50.302977),(102.974107,50.295639),(103.130015,50.309127),(103.20169,50.296983),(103.240189,50.244376),(103.253108,50.214972),(103.276776,50.197557),(103.306593,50.190426),(103.407104,50.197299),(103.43873,50.192596),(103.473973,50.182003),(103.533918,50.153787),(103.601407,50.13353),(103.66807,50.131205),(103.785272,50.186137),(103.845423,50.18469),(103.973994,50.148723),(104.03952,50.141178),(104.121685,50.148258),(104.198115,50.170014),(104.247466,50.206601),(104.268963,50.228873),(104.321363,50.254298),(104.349502,50.271868),(104.377225,50.28918),(104.405802,50.300548),(104.474119,50.313261),(104.576955,50.309488),(104.610441,50.314191),(104.632455,50.323751),(104.671884,50.348297),(104.697051,50.353207),(104.789552,50.352638),(104.81849,50.358323),(104.879004,50.383902),(104.901586,50.389794),(104.934246,50.393256),(105.050104,50.383489),(105.078216,50.385143),(105.10576,50.390052),(105.13134,50.398062),(105.240739,50.458006),(105.278462,50.472579),(105.32864,50.476455),(105.639371,50.421936),(105.779259,50.428913),(105.806544,50.424365),(105.854706,50.410929),(105.904212,50.403798),(105.958059,50.403591),(105.984879,50.399767),(106.038933,50.371397),(106.043274,50.364782),(106.043274,50.355532),(106.044462,50.346024),(106.048183,50.338117),(106.055934,50.33357),(106.135309,50.32711),(106.160941,50.319617),(106.201197,50.299722),(106.222281,50.292384),(106.244863,50.290265),(106.439787,50.327937),(106.548204,50.335792),(106.656518,50.327007),(106.746176,50.307421),(106.788293,50.291505),(106.936449,50.209133),(106.973656,50.196369),(106.982699,50.187119),(106.997996,50.149808),(107.006057,50.140196),(107.026211,50.125727),(107.033601,50.118802),(107.039233,50.10826),(107.048432,50.084644),(107.057113,50.074102),(107.070291,50.066247),(107.100728,50.056791),(107.114629,50.050486),(107.164497,50.01886),(107.192196,50.006044),(107.224907,49.997053),(107.254879,49.998913),(107.280407,50.007595),(107.30485,50.010023),(107.364071,49.976124),(107.729321,49.971938),(107.744604,49.967353),(107.750508,49.965582),(107.78694,49.948218),(107.80792,49.943878),(107.839185,49.946565),(107.850967,49.946048),(107.898199,49.935506),(107.946517,49.933491),(107.95649,49.923362),(107.952614,49.897472),(107.944398,49.880419),(107.935509,49.866621),(107.930032,49.851429),(107.932357,49.830293),(107.950031,49.782492),(107.955767,49.745544),(107.954836,49.732779),(107.949359,49.720635),(107.926828,49.68286),(107.927448,49.670044),(107.939489,49.663223),(107.962898,49.661104),(108.002792,49.663171),(108.015815,49.65573),(108.007546,49.633612),(108.005273,49.617799),(108.015711,49.602245),(108.032661,49.589326),(108.106197,49.554341),(108.126454,49.547158),(108.209911,49.540233),(108.23637,49.532482),(108.250529,49.522405),(108.259521,49.509641),(108.267272,49.495843),(108.277142,49.48251),(108.334865,49.436363),(108.473668,49.35642),(108.538057,49.32743),(108.569973,49.325719),(108.60844,49.323657),(108.751067,49.341175),(108.858967,49.340555),(108.930488,49.348824),(109.032962,49.327895),(109.058025,49.329083),(109.160603,49.346653),(109.286693,49.33854),(109.311911,49.332545),(109.336303,49.323347),(109.390976,49.309291),(109.411233,49.303193),(109.450714,49.305932),(109.462083,49.300454),(109.4657,49.29446),(109.469834,49.276632),(109.474382,49.269138),(109.491849,49.262782),(109.51624,49.255909),(109.728527,49.266451),(109.784957,49.251362),(109.81772,49.227746),(109.83219,49.226867),(109.913115,49.21369),(110.181419,49.161962),(110.225034,49.165372),(110.268339,49.177051),(110.30937,49.195861),(110.34544,49.220614),(110.361046,49.234619),(110.371175,49.24175),(110.382234,49.240045),(110.43329,49.202631),(110.451273,49.194569),(110.508221,49.184337),(110.603615,49.145322),(110.644957,49.136743),(110.688055,49.134521),(110.731359,49.137674),(110.841017,49.162427),(110.965557,49.207385),(111.13857,49.291566),(111.273549,49.32283),(111.291739,49.330788),(111.320988,49.355335),(111.338454,49.36474),(111.362742,49.367634),(111.385066,49.362259),(111.429611,49.346395),(111.454519,49.343087),(111.479117,49.343346),(111.503509,49.347067),(111.616473,49.386444),(111.661019,49.396366),(112.030195,49.411869),(112.126405,49.43994),(112.432238,49.529174),(112.473269,49.534135),(112.58427,49.526332),(112.671396,49.495946),(112.701472,49.491295),(112.733718,49.492794),(112.777126,49.501372),(112.868077,49.531655),(112.926161,49.566536),(112.947348,49.576096),(112.969776,49.583021),(112.992824,49.587155),(113.043673,49.588602),(113.06083,49.595992),(113.071578,49.617748),(113.074162,49.653353),(113.077159,49.669011),(113.087495,49.687408),(113.156741,49.777376),(113.182683,49.801974),(113.212448,49.822025),(113.415537,49.92238),(113.442305,49.946048),(113.458532,49.957262),(113.510415,49.981033),(113.527881,49.992815),(113.579661,50.019945),(113.75226,50.078598),(113.773138,50.081647),(113.815822,50.076893),(113.836803,50.076944),(113.849825,50.080717),(113.973125,50.160505),(113.993279,50.16867),(114.035137,50.176938),(114.055291,50.183811),(114.118233,50.224377),(114.200088,50.25621),(114.286285,50.276881),(114.333,50.272333),(114.424984,50.241844),(114.473043,50.234041),(114.659699,50.251404),(114.75375,50.236211),(114.997352,50.144331),(115.015232,50.132858),(115.028048,50.119888),(115.049649,50.090845),(115.063395,50.077513),(115.210156,49.97168),(115.368699,49.895405),(115.387819,49.891064),(115.450141,49.891426),(115.472982,49.887085),(115.508536,49.886775),(115.578195,49.893648),(115.683409,49.87768),(115.716275,49.877784),(115.750898,49.884967),(116.053619,49.998448),(116.135371,50.014416),(116.21764,50.013848),(116.300529,49.99297),(116.575447,49.92176),(116.617202,49.897317),(116.653375,49.863831),(116.684278,49.823265),(116.472921,49.516462),(116.457728,49.492794),(116.247767,49.181469),(116.037806,48.870145),(116.033568,48.852368),(116.047624,48.817693),(116.048038,48.799761),(116.028194,48.767464),(115.800404,48.530372),(115.791206,48.513836),(115.786555,48.49301),(115.786555,48.473011),(115.809292,48.273954),(115.799991,48.242328),(115.770845,48.224086),(115.536441,48.149155),(115.51422,48.131637),(115.51453,48.122103),(115.545846,47.992989),(115.561866,47.933199),(115.575715,47.909738),(115.5999,47.887414),(115.852701,47.705565),(115.914506,47.683912),(115.9729,47.709053),(116.084314,47.806928),(116.181569,47.849587),(116.243891,47.862894),(116.428893,47.835143),(116.49969,47.836358),(116.751664,47.874133),(116.822047,47.876304),(116.85326,47.872118),(116.972839,47.83765),(117.047356,47.81946),(117.069681,47.810158),(117.317107,47.654069),(117.360826,47.650865),(117.399893,47.685669),(117.43648,47.730499),(117.47286,47.757241),(117.527224,47.78649),(117.741681,47.977589),(117.766899,47.993144),(117.815165,48.004823),(117.972778,47.997898),(117.997169,47.999991),(118.064039,48.019577),(118.122536,48.027509),(118.182481,48.028206),(118.206252,48.023297),(118.254311,48.002859),(118.280046,47.998131),(118.472799,47.989449),(118.542252,47.966246),(118.605246,47.914673),(118.713301,47.793621),(118.767406,47.756156),(118.972614,47.695126),(119.059585,47.673474),(119.08346,47.661562),(119.096947,47.646602),(119.104233,47.62774),(119.116532,47.556039),(119.122113,47.53896),(119.133896,47.527539),(119.157564,47.517669),(119.251046,47.492942),(119.291044,47.48439),(119.310112,47.476095),(119.31776,47.462117),(119.312593,47.452247),(119.288822,47.429147),(119.281897,47.414859),(119.320654,47.40703),(119.475994,47.309206),(119.49067,47.297166),(119.503899,47.279182),(119.512994,47.262672),(119.525086,47.250812),(119.587356,47.238358),(119.629421,47.216086),(119.699959,47.159526),(119.728898,47.128649),(119.753961,47.094439),(119.760524,47.074595),(119.761713,47.015478),(119.764968,47.003825),(119.767294,46.998114),(119.770136,46.992998),(119.784295,46.978322),(119.81742,46.954913),(119.831683,46.942149),(119.83685,46.93357),(119.839692,46.925664),(119.843516,46.918171),(119.852301,46.910729),(119.862947,46.909024),(119.879225,46.908146),(119.892919,46.90551),(119.896433,46.898586),(119.890439,46.88825),(119.884961,46.880912),(119.881447,46.872851),(119.88124,46.860552),(119.883101,46.855436),(119.886821,46.851457),(119.891627,46.848485),(119.896795,46.84647),(119.902893,46.842413),(119.902118,46.837349),(119.898914,46.831251),(119.897983,46.824378),(119.898655,46.802054),(119.885891,46.770066),(119.883101,46.753013),(119.887183,46.74428),(119.903358,46.7264),(119.907027,46.718312),(119.904185,46.708933),(119.897983,46.701647),(119.890335,46.694774),(119.872662,46.673225),(119.85442,46.65966),(119.834421,46.650952),(119.817265,46.651624),(119.796284,46.658833),(119.782228,46.655629),(119.770033,46.643562),(119.754426,46.62439),(119.740267,46.613254),(119.719648,46.602712),(119.697789,46.594883),(119.680116,46.591628),(119.658773,46.596175),(119.623478,46.616329),(119.602188,46.619688),(119.575884,46.619171),(119.501263,46.628008),(119.452946,46.627491),(119.363287,46.613047),(119.316934,46.611678),(119.062376,46.660951),(119.036951,46.668729),(119.014058,46.683301),(118.984913,46.724539),(118.967239,46.740456),(118.947034,46.737148),(118.922074,46.715496),(118.907088,46.709398),(118.890551,46.713532),(118.879648,46.72733),(118.875203,46.74397),(118.867452,46.758336),(118.846523,46.765493),(118.816241,46.758181),(118.792211,46.737768),(118.753816,46.691156),(118.720071,46.676739),(118.684621,46.683457),(118.647414,46.697719),(118.60938,46.705781),(118.595169,46.703042),(118.567729,46.689735),(118.551967,46.685756),(118.472799,46.685679),(118.435179,46.691156),(118.371203,46.713971),(118.335547,46.722162),(118.30082,46.724849),(118.268987,46.722937),(118.238291,46.715393),(118.206045,46.700923),(118.169045,46.678496),(118.155506,46.674568),(118.101969,46.67307),(118.083882,46.668264),(118.005541,46.626974),(117.972778,46.623409),(117.923789,46.615192),(117.900638,46.607596),(117.878313,46.596382),(117.859297,46.580285),(117.832735,46.542793),(117.817025,46.527471),(117.797595,46.520262),(117.696206,46.512253),(117.673365,46.516025),(117.625202,46.535662),(117.607529,46.550545),(117.582001,46.591989),(117.568151,46.603539),(117.556266,46.601601),(117.510067,46.578476),(117.501799,46.577261),(117.491774,46.579096),(117.47286,46.584677),(117.393795,46.57137),(117.410125,46.539796),(117.412502,46.524629),(117.405474,46.510806),(117.369197,46.475691),(117.357518,46.448406),(117.353074,46.379496),(117.337468,46.357275),(117.301708,46.350144),(116.957853,46.366422),(116.831659,46.386369),(116.814606,46.38673),(116.804581,46.382906),(116.78484,46.365905),(116.722002,46.328698),(116.707325,46.324228),(116.64521,46.318466),(116.603559,46.309319),(116.581959,46.298012),(116.568316,46.290871),(116.548265,46.259296),(116.539584,46.24121),(116.525114,46.226792),(116.357166,46.105559),(116.213195,45.908155),(116.207098,45.88087),(116.220947,45.849761),(116.242134,45.82692),(116.251643,45.803252),(116.230352,45.769766),(116.169891,45.709097),(116.143949,45.694628),(116.094856,45.676541),(116.078733,45.673389),(116.063334,45.673337),(116.011967,45.678557),(116.002149,45.675559),(115.982822,45.659643),(115.767331,45.530142),(115.6924,45.468957),(115.667389,45.454281),(115.63783,45.444359),(115.472982,45.412785),(115.33728,45.394698),(115.126337,45.39444),(114.938855,45.373769),(114.905265,45.377748),(114.737317,45.425032),(114.703313,45.427151),(114.66931,45.42281),(114.533711,45.3855),(114.52379,45.38028),(114.519449,45.370927),(114.511697,45.325503),(114.502292,45.303231),(114.473043,45.259202),(114.418886,45.20148),(114.211767,45.06216),(114.163605,45.040146),(114.149342,45.030069),(114.139214,45.019165),(114.120403,44.993224),(114.089294,44.961753),(114.055291,44.940565),(114.01705,44.927285),(113.973125,44.919326),(113.913801,44.915451),(113.889306,44.908268),(113.83763,44.867908),(113.735621,44.815922),(113.672472,44.768173),(113.635058,44.746262),(113.604776,44.739699),(113.532429,44.74528),(113.517133,44.749518),(113.488917,44.766261),(113.473208,44.770705),(113.104858,44.794373),(113.016905,44.82109),(112.973186,44.821245),(112.748497,44.865273),(112.614242,44.908836),(112.586027,44.923822),(112.564529,44.943924),(112.523912,44.993275),(112.441333,45.052393),(112.412807,45.066036),(112.379631,45.070738),(112.107606,45.067379),(112.011488,45.087482),(111.984637,45.087154),(111.973351,45.087017),(111.958261,45.084536),(111.947926,45.077715),(111.938521,45.068981),(111.926739,45.06092),(111.906275,45.05415),(111.863177,45.046295),(111.843333,45.039526),(111.786489,45.008572),(111.760651,44.989296),(111.738533,44.9663),(111.551361,44.69319),(111.541026,44.668231),(111.540096,44.652211),(111.544436,44.618105),(111.543816,44.601258),(111.538235,44.58343),(111.530174,44.570614),(111.508986,44.546584),(111.483768,44.506432),(111.473226,44.495321),(111.470849,44.493306),(111.446871,44.475891),(111.424134,44.448037),(111.406357,44.416463),(111.397055,44.387369),(111.396435,44.346597),(111.410595,44.326081),(111.473226,44.298848),(111.49059,44.282621),(111.498134,44.264431),(111.503715,44.225725),(111.519425,44.18857),(111.543816,44.156737),(111.634457,44.065942),(111.66815,44.041344),(111.780701,43.986205),(111.811397,43.964294),(111.838785,43.938792),(111.930563,43.820143),(111.944309,43.786372),(111.947926,43.756968),(111.945136,43.72387),(111.933353,43.696636),(111.910409,43.684983),(111.893252,43.682606),(111.845813,43.666922),(111.77264,43.669299),(111.753829,43.663202),(111.59725,43.523391),(111.567691,43.50254),(111.535031,43.490732),(111.428681,43.483936),(111.401396,43.475513),(111.338558,43.438177),(111.096092,43.366656),(110.973412,43.3156),(110.933724,43.287772),(110.796989,43.148918),(110.680096,43.057657),(110.66573,43.0374),(110.641029,42.987791),(110.608163,42.944667),(110.566718,42.91056),(110.473391,42.854905),(110.449413,42.837335),(110.424815,42.785245),(110.406728,42.768605),(110.139871,42.682615),(110.105661,42.666673),(110.093156,42.657862),(110.084267,42.650059),(110.074862,42.643522),(110.060186,42.638355),(110.042719,42.635952),(109.987322,42.636468),(109.912701,42.62882),(109.667342,42.54898),(109.518307,42.467331),(109.510349,42.464748),(109.504871,42.464928),(109.500013,42.463327),(109.493812,42.455213),(109.490092,42.451286),(109.485131,42.449296),(109.328551,42.440486),(109.280285,42.428316),(109.253414,42.425939),(108.994463,42.449529),(108.961287,42.447539),(108.862688,42.40886),(108.82853,42.400049),(108.796852,42.398369),(108.536455,42.435111),(108.319775,42.432553),(108.234768,42.450072),(108.177355,42.454309),(108.04968,42.43912),(107.622396,42.388286),(107.195113,42.337453),(106.767829,42.286619),(106.318218,42.140052),(105.868607,41.993484),(105.473851,41.840341),(105.402744,41.811532),(105.358199,41.785848),(105.344557,41.78112),(105.325953,41.776702),(105.274483,41.755463),(105.218259,41.748435),(105.200896,41.743474),(105.014809,41.596144),(104.97383,41.586145),(104.935434,41.622422),(104.913678,41.638338),(104.892336,41.644772),(104.601243,41.645444),(104.504918,41.656554),(104.497993,41.665778),(104.500784,41.870598),(104.110885,41.813082),(103.720986,41.755566),(103.691427,41.759235),(103.398112,41.876411),(103.104797,41.993588),(103.104435,41.993639),(103.104383,41.993639),(103.073481,42.004517),(102.727042,42.064548),(102.380603,42.124579),(102.034164,42.18461),(101.97422,42.20789),(101.886473,42.278015),(101.735371,42.461156),(101.637599,42.515442),(101.524945,42.537456),(101.41074,42.544872),(101.21871,42.529834),(100.818132,42.578729),(100.417553,42.627623),(100.016975,42.676518),(99.971551,42.676285),(99.621903,42.597443),(99.474476,42.564199),(99.068355,42.60391),(98.662234,42.643622),(98.256113,42.683333),(97.849992,42.723045),(97.521632,42.755152),(97.193271,42.78726),(97.19068,42.787061),(96.832669,42.759604),(96.474659,42.732147),(96.379264,42.720546),(96.36634,42.722923),(96.357767,42.724499),(96.350635,42.740906),(96.337199,42.86648),(96.330688,42.889709),(96.318699,42.910069),(96.294308,42.933272),(95.908492,43.214547),(95.874385,43.247103),(95.854955,43.284543),(95.845446,43.326478),(95.841416,43.372522),(95.832837,43.408902),(95.692484,43.630542),(95.589235,43.869494),(95.535284,43.95768),(95.510273,43.979125),(95.474926,43.986619),(95.422733,43.988634),(95.327545,44.006669),(95.318967,44.017108),(95.31876,44.040724),(95.328269,44.09824),(95.321447,44.148417),(95.322688,44.158236),(95.327132,44.168313),(95.340568,44.187537),(95.347492,44.214925),(95.359688,44.231823),(95.389247,44.260762),(95.397722,44.280502),(95.379428,44.287117),(95.036814,44.254974),(94.993819,44.259418),(94.905762,44.294248),(94.720864,44.335796),(94.69823,44.343496),(94.683967,44.356622),(94.672598,44.373778),(94.657199,44.388816),(94.588055,44.4361),(94.460311,44.493306),(94.430132,44.504468),(94.366364,44.504313),(94.338458,44.512116),(94.321922,44.528033),(94.295464,44.571389),(94.27748,44.589579),(94.195005,44.65433),(94.181879,44.660841),(94.165342,44.665854),(94.149012,44.667197),(94.103744,44.651643),(94.058579,44.651281),(93.97507,44.659962),(93.927424,44.672933),(93.874507,44.714223),(93.714,44.874575),(93.688265,44.891059),(93.525278,44.951263),(93.420582,44.955087),(93.399911,44.960564),(93.36136,44.978393),(93.341,44.984852),(93.317229,44.985886),(93.268963,44.980098),(93.244158,44.981545),(93.165713,45.007642),(93.139152,45.009864),(93.075941,45.005192),(93.052439,45.003456),(93.033112,45.007642),(93.013888,45.009295),(92.994458,45.008365),(92.974924,45.004696),(92.945055,45.005833),(92.91622,45.014566),(92.861029,45.037872),(92.847593,45.039112),(92.81421,45.033893),(92.798914,45.03317),(92.752715,45.037976),(92.63851,45.0156),(92.572054,45.013016),(92.475109,44.997461),(92.458986,44.997926),(92.413821,45.011259),(92.396458,45.013119),(92.347365,45.007642),(92.331036,45.007848),(92.285354,45.019527),(92.267887,45.019527),(92.218898,45.010122),(92.19368,45.014514),(92.108414,45.058181),(92.075651,45.068878),(92.042991,45.074821),(92.009401,45.076216),(91.975088,45.073374),(91.919071,45.065571),(91.746989,45.072444),(91.724664,45.070738),(91.683633,45.061178),(91.662963,45.059525),(91.563951,45.077146),(91.552272,45.075338),(91.54328,45.071824),(91.533978,45.0711),(91.521783,45.077456),(91.45605,45.137453),(91.43848,45.146134),(91.41688,45.145669),(91.399723,45.136884),(91.3836,45.124224),(91.366547,45.11425),(91.346703,45.113733),(91.249138,45.129701),(91.184336,45.153834),(91.169763,45.163549),(91.147749,45.187217),(91.135036,45.197862),(91.101343,45.210678),(91.056798,45.217551),(91.011323,45.218946),(90.975149,45.214864),(90.90549,45.185977),(90.873243,45.186184),(90.857637,45.215071),(90.860324,45.231659),(90.865905,45.242563),(90.866629,45.25357),(90.854433,45.270623),(90.837173,45.280028),(90.796556,45.292844),(90.790975,45.304316),(90.790458,45.337699),(90.778055,45.365294),(90.762553,45.391597),(90.753251,45.42095),(90.737955,45.441724),(90.672325,45.475675),(90.651138,45.493142),(90.696613,45.730026),(90.710773,45.752196),(90.919235,45.950065),(90.975149,45.987323),(90.986208,45.993111),(91.002435,46.021843),(91.005432,46.068094),(90.995923,46.113724),(90.975149,46.140544),(90.948794,46.168294),(90.899185,46.281672),(90.896188,46.302033),(90.906006,46.317303),(90.935772,46.343865),(90.975149,46.416548),(90.986105,46.435255),(91.001401,46.475045),(91.014113,46.493184),(91.035611,46.529073),(91.045326,46.551087),(91.047496,46.566409),(91.03251,46.579923),(91.011323,46.585323),(90.995923,46.594625),(90.998094,46.620256),(91.011736,46.662941),(91.014292,46.689844),(91.01556,46.703197),(91.004812,46.74043),(90.975149,46.774149),(90.939389,46.79885),(90.925333,46.813139),(90.919959,46.833628),(90.922749,46.841586),(90.934428,46.856831),(90.936495,46.864427),(90.932775,46.874789),(90.92585,46.880654),(90.917685,46.885408),(90.91014,46.892384),(90.900322,46.910678),(90.893707,46.92817),(90.885129,46.944733),(90.869833,46.960339),(90.849472,46.973206),(90.828182,46.982301),(90.805547,46.986849),(90.78188,46.986332),(90.742399,46.991861),(90.712116,47.014702),(90.46872,47.308922),(90.466343,47.316338),(90.468514,47.323521),(90.475232,47.33029),(90.485567,47.344915),(90.490011,47.361839),(90.487221,47.378194),(90.475232,47.391088),(90.448153,47.404033),(90.441745,47.430543),(90.443606,47.462789),(90.441228,47.493045),(90.427276,47.506559),(90.394616,47.524671),(90.381594,47.538391),(90.352035,47.588311),(90.338496,47.60278),(90.327437,47.623037),(90.337462,47.63699),(90.349554,47.64779),(90.3448,47.658642),(90.32351,47.670166),(90.302116,47.678512),(90.209718,47.695746),(90.163416,47.710009),(90.119956,47.730137),(90.082852,47.756104),(90.070657,47.76985),(90.058771,47.789513),(90.052157,47.8107),(90.055981,47.828916),(90.064352,47.85062),(90.059856,47.868811),(90.044612,47.879766),(90.002496,47.880386),(89.96317,47.888654),(89.946685,47.883177),(89.939037,47.870852),(89.937642,47.857545),(89.934438,47.844264),(89.921364,47.832094),(89.889066,47.824317),(89.783543,47.818504),(89.751296,47.824317),(89.740238,47.836151),(89.731143,47.864754),(89.723391,47.878164),(89.707268,47.889042),(89.672025,47.89408),(89.655282,47.899816),(89.643913,47.912761),(89.636161,47.929582),(89.627376,47.943948),(89.613424,47.949581),(89.596577,47.952578),(89.583245,47.962035),(89.575648,47.976039),(89.576217,47.992886),(89.571876,48.020455),(89.5418,48.031023),(89.503663,48.029989),(89.475344,48.022961),(89.425425,48.021644),(89.409198,48.023116),(89.369201,48.038154),(89.354266,48.038774),(89.334268,48.032366),(89.285692,48.005598),(89.268587,47.993144),(89.243989,47.980225),(89.218719,47.976969),(89.167146,47.983997),(89.074697,47.984256),(89.045913,47.992886),(89.04581,47.992989),(89.045551,47.992989),(88.932328,48.096962),(88.916825,48.105954),(88.889282,48.110915),(88.831456,48.105153),(88.805411,48.105954),(88.775335,48.120552),(88.709189,48.166363),(88.680664,48.17303),(88.655446,48.171169),(88.635809,48.175846),(88.596225,48.197679),(88.580774,48.211994),(88.573487,48.229719),(88.568836,48.249201),(88.56124,48.268269),(88.558759,48.288087),(88.57297,48.32532),(88.565116,48.342993),(88.50269,48.392551),(88.479126,48.400148),(88.459127,48.398132),(88.439645,48.393714),(88.416701,48.394101),(88.383421,48.408674),(88.332107,48.453994),(88.304873,48.469006),(88.235627,48.493191),(88.21785,48.495),(88.183485,48.492752),(88.165967,48.493734),(88.148293,48.499366),(88.115737,48.516497),(88.088245,48.526083),(88.071812,48.538795),(88.062511,48.542878),(88.051969,48.543188),(88.028301,48.539622),(88.016622,48.539803),(87.983032,48.552335),(87.95182,48.575202),(87.942828,48.599489),(87.975488,48.616517),(87.989647,48.624165),(87.997812,48.635172),(88.003393,48.645998),(88.010162,48.653414),(88.055018,48.673413),(88.063854,48.682611),(88.05941,48.708087),(88.033779,48.72912),(87.975488,48.755992),(87.95244,48.761107),(87.907585,48.758834),(87.841697,48.779349),(87.821078,48.788289),(87.805885,48.800588),(87.802165,48.80958),(87.800511,48.830302),(87.796067,48.839759),(87.787489,48.84658),(87.77674,48.85118),(87.754726,48.857277),(87.737879,48.86937),(87.735709,48.886733),(87.743615,48.905181),(87.756896,48.920374),(87.835858,48.945902),(87.8726,48.96802),(87.872238,49.00409),(87.856942,49.015614),(87.837821,49.02042),(87.821905,49.02874),(87.815962,49.050599),(87.821078,49.071838),(87.829657,49.085997),(87.835548,49.100725),(87.832447,49.123876),(87.818081,49.154003),(87.816324,49.165837),(87.836995,49.159998),(87.855185,49.158964),(87.956781,49.168886),(87.975488,49.175811),(87.992954,49.191727),(88.029748,49.21555),(88.108503,49.247434),(88.143953,49.27074),(88.148397,49.296579),(88.129173,49.325931),(88.115531,49.356575),(88.135788,49.386082),(88.145606,49.397193),(88.161729,49.430111),(88.174752,49.443857),(88.19997,49.454347),(88.37877,49.475793),(88.401921,49.475844),(88.451117,49.465147),(88.475405,49.463649),(88.538761,49.466542),(88.557829,49.47109),(88.599739,49.488918),(88.614157,49.492794),(88.615759,49.492949),(88.633535,49.491244),(88.648676,49.483596),(88.67467,49.459825),(88.69565,49.446957),(88.719421,49.442926),(88.870627,49.436002),(88.875329,49.441789),(88.854865,49.473881),(88.856157,49.511501),(88.858741,49.527366),(88.868198,49.538114),(88.88892,49.54168),(88.90835,49.535944),(88.919099,49.52318),(88.926954,49.507419),(88.937599,49.492846),(88.947573,49.482821),(88.954704,49.471865),(88.962662,49.46215),(88.975323,49.455845),(89.01408,49.460548),(89.160738,49.502716),(89.195258,49.521526),(89.215619,49.545452),(89.201563,49.570619),(89.178205,49.598472),(89.187352,49.621985),(89.216445,49.634491),(89.252205,49.629427),(89.310703,49.59315),(89.339435,49.580799),(89.37194,49.581678),(89.39783,49.598989),(89.418604,49.624207),(89.4416,49.643586),(89.475344,49.643431),(89.520303,49.663171),(89.616318,49.685444),(89.682308,49.708336),(89.702411,49.719964),(89.712642,49.735157),(89.701532,49.75314),(89.683704,49.76115),(89.638952,49.775464),(89.626446,49.788022),(89.627376,49.796807),(89.641949,49.808124),(89.643551,49.818872),(89.638952,49.824815),(89.621072,49.835047),(89.615336,49.84192),(89.615284,49.854529),(89.621072,49.893338),(89.623862,49.902692),(89.633211,49.907939),(89.667684,49.92729),(89.720704,49.939744),(89.866432,49.942741),(89.920175,49.950854),(89.969423,49.96708),(89.996243,49.992764),(89.997091,50.003664),(89.998723,50.024648),(90.004924,50.050745),(90.020531,50.070743),(90.051226,50.084179),(90.182433,50.102473),(90.222947,50.11441),(90.34387,50.174665),(90.363921,50.179781),(90.404952,50.182623),(90.425002,50.186912),(90.475232,50.21461),(90.51895,50.218383),(90.604939,50.205981),(90.648451,50.206652),(90.666434,50.210373),(90.683901,50.216212),(90.699714,50.225152),(90.712633,50.237968),(90.717387,50.252024),(90.717594,50.280756),(90.726586,50.291867),(90.762449,50.305716),(90.839964,50.320806),(90.877068,50.339357),(90.948588,50.397493),(90.975149,50.413926),(91.012046,50.425295),(91.129765,50.426174),(91.163355,50.432788),(91.260093,50.466585),(91.297507,50.466378),(91.382153,50.454958),(91.415743,50.461365),(91.432486,50.478057),(91.440031,50.498572),(91.450366,50.519088),(91.475067,50.535986),(91.575733,50.561979),(91.602708,50.579601),(91.653144,50.640063),(91.679602,50.656547),(91.749779,50.684091),(91.824193,50.701558),(91.899951,50.707242),(92.062732,50.686313),(92.15885,50.689103),(92.242772,50.720006),(92.294449,50.791268),(92.297033,50.809871),(92.297446,50.827596),(92.301683,50.843358),(92.315223,50.855863),(92.33548,50.863615),(92.360905,50.868369),(92.384572,50.865579),(92.399869,50.850592),(92.418989,50.811732),(92.443277,50.786307),(92.474903,50.770494),(92.516451,50.760624),(92.554588,50.743002),(92.611845,50.687657),(92.649776,50.674066),(92.671893,50.675616),(92.695251,50.68192),(92.717369,50.692152),(92.735249,50.705227),(92.746617,50.721453),(92.753439,50.754681),(92.76026,50.770752),(92.796123,50.788012),(92.857722,50.795505),(92.921077,50.792456),(92.961695,50.777884),(92.973994,50.742175),(92.973374,50.694374),(92.991874,50.65479),(93.002933,50.634843),(93.011408,50.623319),(93.02288,50.616291),(93.04262,50.609884),(93.104942,50.598825),(93.139152,50.599445),(93.188348,50.599807),(93.421512,50.609367),(93.536337,50.584717),(93.886961,50.574976),(94.237586,50.565235),(94.25867,50.557535),(94.273346,50.544771),(94.278204,50.529217),(94.279754,50.492681),(94.319751,50.429016),(94.327503,50.404366),(94.332257,50.301013),(94.344349,50.249182),(94.354478,50.223602),(94.368534,50.202725),(94.391788,50.185568),(94.474987,50.162262),(94.491731,50.152289),(94.498552,50.139525),(94.502273,50.125055),(94.509094,50.109862),(94.520876,50.09777),(94.563974,50.071002),(94.574413,50.058548),(94.592293,50.029816),(94.603455,50.019739),(94.624539,50.015191),(94.650997,50.017827),(94.746392,50.040358),(94.921575,50.045887),(94.953718,50.040616),(94.98059,50.024751),(95.004051,49.992764),(95.021621,49.969819),(95.028339,49.963411),(95.076398,49.945531),(95.354727,49.947702),(95.399789,49.938865),(95.445161,49.914422),(95.461697,49.90264),(95.477201,49.894083),(95.480611,49.892201),(95.500661,49.886724),(95.520608,49.889617),(95.537145,49.900728),(95.56319,49.9276),(95.583964,49.936695),(95.680495,49.945996),(95.721423,49.958502),(95.75894,49.993074),(95.787672,50.011729),(95.827876,50.020152),(95.867047,50.014984),(95.892162,49.992919),(95.892162,49.992764),(95.904461,49.964807),(95.922651,49.944601),(95.946319,49.938503),(95.974844,49.952456),(95.985696,49.964962),(95.998305,49.975917),(96.011948,49.985219),(96.026624,49.992815),(96.04099,49.997931),(96.055976,49.99881),(96.071066,49.996743),(96.085949,49.992919),(96.086052,49.992867),(96.086259,49.992815),(96.086362,49.992764),(96.235603,49.9492),(96.281182,49.926256),(96.32335,49.897886),(96.346294,49.888584),(96.372856,49.886052),(96.399108,49.891736),(96.44882,49.913957),(96.474659,49.921657),(96.503287,49.922122),(96.523855,49.915766),(96.539254,49.901865),(96.553,49.879851),(96.56809,49.861764),(96.585143,49.857526),(96.604366,49.862901),(96.625967,49.873391),(96.680227,49.90972),(96.701932,49.91375),(96.969202,49.886672),(97.005892,49.865278),(97.042273,49.823213),(97.057259,49.812723),(97.08527,49.805838),(97.10015,49.802181),(97.119891,49.793654),(97.128986,49.775826),(97.152964,49.750246),(97.205053,49.734071),(97.262311,49.726113),(97.301688,49.725545),(97.343339,49.734175),(97.390778,49.749471),(97.474598,49.788693),(97.542707,49.822748),(97.57361,49.847501),(97.581258,49.877939),(97.571749,49.896749),(97.563171,49.908944),(97.566582,49.916799),(97.642236,49.930028),(97.7336,49.958347),(97.756338,49.961499),(97.777525,49.956177),(97.810701,49.931165),(97.829925,49.92331),(97.847391,49.93008),(97.874573,49.953955),(97.906199,49.973075),(98.047999,50.023046),(98.105567,50.06387),(98.262457,50.283805),(98.269278,50.299412),(98.272275,50.318997),(98.270105,50.335947),(98.261836,50.367469),(98.266281,50.400697),(98.298217,50.460125),(98.300594,50.492785),(98.300697,50.492836),(98.300697,50.49294),(98.293462,50.518623),(98.275376,50.537692),(98.251294,50.550559),(98.22556,50.557639),(98.163341,50.564667),(98.135953,50.570971),(98.060092,50.608902),(98.038491,50.622958),(98.023298,50.642026),(97.974515,50.723158),(97.944026,50.774473),(97.947437,50.79597),(97.990225,50.835606),(97.984644,50.846923),(97.953018,50.86284),(97.938755,50.874415),(97.92966,50.886611),(97.919428,50.897411),(97.871989,50.9171),(97.835713,50.940716),(97.808531,50.970482),(97.80636,51.001126),(97.870129,51.086805),(97.885632,51.120111),(97.894727,51.153855),(97.900308,51.168428),(97.92904,51.21504),(97.931727,51.230414),(97.92811,51.251472),(97.916328,51.285889),(97.915708,51.300617),(97.922839,51.318471),(97.933794,51.331777),(97.962216,51.355445),(97.974515,51.368597),(98.020611,51.435182),(98.039731,51.4573),(98.050893,51.46642),(98.066706,51.469263),(98.111355,51.484714),(98.137813,51.485877),(98.220392,51.475205),(98.2299,51.492879),(98.233828,51.516521),(98.224319,51.560006),(98.228247,51.583416),(98.238685,51.601477),(98.263387,51.635196),(98.273515,51.654833),(98.33222,51.718317),(98.425031,51.746222),(98.618714,51.780665),(98.651373,51.797485),(98.682689,51.819474),(98.711111,51.845105),(98.776637,51.930113),(98.791727,51.9775),(98.800201,51.992745),(98.838545,52.025275),(98.846504,52.039331),(98.848881,52.056307),(98.849604,52.090129),(98.855599,52.106691),(98.886398,52.128551),(98.927636,52.129584),(98.937652,52.124687),(98.962465,52.112557),(98.974454,52.080388),(98.994712,52.058296),(99.025097,52.045532),(99.19873,52.006594),(99.232837,51.994243),(99.255988,51.977914),(99.274694,51.959491),(99.295365,51.943549),(99.32389,51.934221),(99.556848,51.891459),(99.679321,51.888669),(99.709655,51.880581),(99.783966,51.837612),(99.848665,51.789346),(99.917911,51.749478),(100.005968,51.731727)] +Montserrat [(-62.147369,16.744289),(-62.147694,16.737047),(-62.151763,16.724514),(-62.150787,16.720364),(-62.147572,16.715888),(-62.14391,16.70897),(-62.141184,16.70185),(-62.140533,16.696479),(-62.144032,16.688218),(-62.14977,16.681789),(-62.157826,16.677314),(-62.167877,16.67536),(-62.218861,16.688707),(-62.230133,16.727607),(-62.218861,16.776313),(-62.202016,16.819322),(-62.189443,16.814439),(-62.182932,16.81273),(-62.174672,16.813137),(-62.179311,16.794501),(-62.170033,16.777004),(-62.156321,16.760321),(-62.147369,16.744289)] +Namibia [(13.184911,-16.964183),(13.19814,-16.957362),(13.205478,-16.963046),(13.212092,-16.972761),(13.222841,-16.977929),(13.245269,-16.98134),(13.257154,-16.98165),(13.267489,-16.977929),(13.267489,-16.98537),(13.293018,-16.973795),(13.308417,-16.970178),(13.315238,-16.974415),(13.321543,-16.974932),(13.345947,-16.968711),(13.363711,-16.964183),(13.382004,-16.970384),(13.417248,-16.993742),(13.435128,-16.999013),(13.458899,-17.001803),(13.479776,-17.010278),(13.494659,-17.024024),(13.507785,-17.063505),(13.522254,-17.076941),(13.530936,-17.093271),(13.521324,-17.1219),(13.606487,-17.167375),(13.69413,-17.236621),(13.790403,-17.288091),(13.884351,-17.338527),(13.896857,-17.349069),(13.942745,-17.408187),(13.957318,-17.419142),(13.980573,-17.423587),(13.992975,-17.421313),(14.008891,-17.411494),(14.017883,-17.40922),(14.029148,-17.410461),(14.047442,-17.416042),(14.069146,-17.418626),(14.085372,-17.423587),(14.097258,-17.423587),(14.108213,-17.420486),(14.123923,-17.411598),(14.130744,-17.40922),(14.174979,-17.416248),(14.197097,-17.412941),(14.206502,-17.393097),(14.207432,-17.388033),(14.218801,-17.388136),(14.219112,-17.388136),(14.287427,-17.388136),(14.543949,-17.38824),(14.800574,-17.388343),(15.057199,-17.388343),(15.313721,-17.388447),(15.559114,-17.388545),(15.570243,-17.38855),(15.826765,-17.388653),(16.08339,-17.388653),(16.339808,-17.388653),(16.59633,-17.388757),(16.852852,-17.388757),(17.109477,-17.38886),(17.278972,-17.388928),(17.366102,-17.388963),(17.622624,-17.388963),(17.879146,-17.389067),(18.000483,-17.389116),(18.135668,-17.38917),(18.392293,-17.389273),(18.445726,-17.389273),(18.453581,-17.389893),(18.455028,-17.395991),(18.458645,-17.405293),(18.465157,-17.40922),(18.471668,-17.414285),(18.488101,-17.452112),(18.489858,-17.462447),(18.492752,-17.464514),(18.516626,-17.471336),(18.55094,-17.535311),(18.554144,-17.54637),(18.567476,-17.553294),(18.619669,-17.594842),(18.622873,-17.60218),(18.627937,-17.619854),(18.633312,-17.628949),(18.64282,-17.638044),(18.66132,-17.646725),(18.670932,-17.653133),(18.728293,-17.710907),(18.74824,-17.736332),(18.761986,-17.747701),(18.800847,-17.756589),(18.89004,-17.799274),(19.020575,-17.822322),(19.105118,-17.818188),(19.139327,-17.805269),(19.160825,-17.800928),(19.17209,-17.801238),(19.201856,-17.807129),(19.246608,-17.804028),(19.262421,-17.81395),(19.421274,-17.859426),(19.59284,-17.857255),(19.649787,-17.844956),(19.672628,-17.842682),(19.693195,-17.847747),(19.702187,-17.86573),(19.711282,-17.872965),(19.732056,-17.88206),(19.755207,-17.889088),(19.77102,-17.890328),(19.775981,-17.885057),(19.78766,-17.866454),(19.793964,-17.862319),(19.951991,-17.862319),(19.989508,-17.882783),(20.024545,-17.894566),(20.03426,-17.895909),(20.092551,-17.890328),(20.119939,-17.890741),(20.132962,-17.888778),(20.147121,-17.882783),(20.154563,-17.890328),(20.169239,-17.878132),(20.193113,-17.872138),(20.219882,-17.873378),(20.243446,-17.882783),(20.278173,-17.854878),(20.288921,-17.861596),(20.302771,-17.860769),(20.336154,-17.854878),(20.347729,-17.858909),(20.386797,-17.890328),(20.412635,-17.884127),(20.437543,-17.894462),(20.460074,-17.913686),(20.479504,-17.934356),(20.489529,-17.942108),(20.523946,-17.958541),(20.552885,-17.979108),(20.565494,-17.985206),(20.590712,-17.978798),(20.630089,-17.976938),(20.666263,-17.980245),(20.682179,-17.988617),(20.68962,-17.996988),(20.706157,-18.00381),(20.722487,-18.006497),(20.729928,-18.002363),(20.737473,-17.993474),(20.754423,-17.997918),(20.784602,-18.012595),(20.806202,-18.031405),(20.831937,-18.029338),(20.8616,-18.018796),(20.894466,-18.012595),(20.908315,-17.986136),(20.986455,-17.965771),(21.000713,-17.962055),(21.09311,-17.938077),(21.10944,-17.945002),(21.12608,-17.941074),(21.143133,-17.933736),(21.161323,-17.930636),(21.175792,-17.93322),(21.216617,-17.930636),(21.23274,-17.93446),(21.278112,-17.958541),(21.335059,-17.977971),(21.364825,-17.992027),(21.381154,-18.012595),(21.386839,-18.014455),(21.405546,-18.009287),(21.477583,-17.996058),(21.728523,-17.949859),(21.979464,-17.903764),(22.230508,-17.857565),(22.481449,-17.811366),(22.685674,-17.772816),(22.889796,-17.734059),(23.093918,-17.695405),(23.29804,-17.656854),(23.381652,-17.641144),(23.422373,-17.633496),(23.45741,-17.626778),(23.47622,-17.626365),(23.505986,-17.620474),(23.548774,-17.611999),(23.591769,-17.603524),(23.634557,-17.595049),(23.677242,-17.586677),(23.72003,-17.578202),(23.762818,-17.569727),(23.805606,-17.561356),(23.848497,-17.552881),(23.891389,-17.544406),(23.934177,-17.536034),(23.976965,-17.52756),(24.01965,-17.519085),(24.062541,-17.510713),(24.105329,-17.502238),(24.148117,-17.493763),(24.190905,-17.485288),(24.220464,-17.4795),(24.238758,-17.478157),(24.257361,-17.480844),(24.310278,-17.482601),(24.321337,-17.488699),(24.329398,-17.485081),(24.371256,-17.473713),(24.388929,-17.471336),(24.407016,-17.474539),(24.449288,-17.489112),(24.47926,-17.494487),(24.498173,-17.503478),(24.523598,-17.507819),(24.53166,-17.5134),(24.537861,-17.520325),(24.546543,-17.526526),(24.562459,-17.53221),(24.571244,-17.533451),(24.580752,-17.532831),(24.591294,-17.528386),(24.606487,-17.515157),(24.617443,-17.509163),(24.622817,-17.502341),(24.629742,-17.49552),(24.639457,-17.49242),(24.684415,-17.49242),(24.769785,-17.505442),(24.775056,-17.507612),(24.780017,-17.512263),(24.786838,-17.516914),(24.79738,-17.519085),(24.829523,-17.517741),(24.898252,-17.531074),(24.924917,-17.542959),(24.93763,-17.560736),(24.95799,-17.551744),(24.969987,-17.559962),(24.971116,-17.560736),(24.982588,-17.576549),(24.998505,-17.588021),(25.008013,-17.588538),(25.02672,-17.58275),(25.036952,-17.5812),(25.040569,-17.584507),(25.033851,-17.60156),(25.033851,-17.608485),(25.040053,-17.616133),(25.045324,-17.619957),(25.052558,-17.621404),(25.064237,-17.621507),(25.067028,-17.625331),(25.085218,-17.640938),(25.088525,-17.642695),(25.096897,-17.67215),(25.098757,-17.676801),(25.107955,-17.678868),(25.115087,-17.684242),(25.120048,-17.691064),(25.122631,-17.697885),(25.131416,-17.686516),(25.138548,-17.686103),(25.153327,-17.700986),(25.156428,-17.70667),(25.155291,-17.719382),(25.156841,-17.72517),(25.161182,-17.729408),(25.172448,-17.735092),(25.177822,-17.738813),(25.190741,-17.755349),(25.198182,-17.75845),(25.215132,-17.759277),(25.228878,-17.762481),(25.242417,-17.770335),(25.253476,-17.781497),(25.259781,-17.794107),(25.194152,-17.782324),(25.153947,-17.781808),(25.120874,-17.813537),(25.087905,-17.826766),(25.057002,-17.827696),(25.047494,-17.807129),(25.019692,-17.823769),(25.007083,-17.825733),(24.998505,-17.81395),(24.983312,-17.820462),(24.975147,-17.816327),(24.968636,-17.807646),(24.958094,-17.800928),(24.964295,-17.786665),(24.953339,-17.788422),(24.948585,-17.79328),(24.945175,-17.799998),(24.93763,-17.807129),(24.931119,-17.81054),(24.857428,-17.833587),(24.838101,-17.835034),(24.820841,-17.839272),(24.79738,-17.858082),(24.776916,-17.862319),(24.770715,-17.865523),(24.764514,-17.879683),(24.756039,-17.882783),(24.74684,-17.88423),(24.738159,-17.887641),(24.730717,-17.891878),(24.725343,-17.895909),(24.698471,-17.928879),(24.664055,-17.949859),(24.649172,-17.962778),(24.598632,-18.020759),(24.595015,-18.022826),(24.591811,-18.028407),(24.577755,-18.044427),(24.574551,-18.050422),(24.564423,-18.052799),(24.518431,-18.057346),(24.505615,-18.060344),(24.471508,-18.029958),(24.469751,-18.014455),(24.465101,-18.008667),(24.458486,-18.005773),(24.451045,-17.998952),(24.433888,-17.967223),(24.421589,-17.956474),(24.399471,-17.95234),(24.365262,-17.950789),(24.350586,-17.95606),(24.334256,-17.971563),(24.305834,-18.019416),(24.296429,-18.026237),(24.287437,-18.02448),(24.270074,-18.015798),(24.259222,-18.012595),(24.238241,-18.009907),(24.218294,-18.012595),(24.183051,-18.029441),(24.135095,-18.085458),(24.101609,-18.108816),(24.065125,-18.115224),(24.05696,-18.119048),(24.028125,-18.145816),(24.02027,-18.151604),(23.991744,-18.163386),(23.979652,-18.171861),(23.974898,-18.177029),(23.971177,-18.18385),(23.966733,-18.180646),(23.961979,-18.177856),(23.956604,-18.176615),(23.950817,-18.177649),(23.915987,-18.201213),(23.912886,-18.235733),(23.89697,-18.250203),(23.867514,-18.269426),(23.855215,-18.280072),(23.837232,-18.305807),(23.825553,-18.317072),(23.809843,-18.321723),(23.715792,-18.419081),(23.700909,-18.42797),(23.680136,-18.431484),(23.656468,-18.458252),(23.649853,-18.46342),(23.645409,-18.466004),(23.609856,-18.477682),(23.592182,-18.478199),(23.57916,-18.467864),(23.571305,-18.426006),(23.555492,-18.383115),(23.546604,-18.369472),(23.560763,-18.348491),(23.551461,-18.327511),(23.518802,-18.293714),(23.527277,-18.277695),(23.521696,-18.268186),(23.511257,-18.260331),(23.505676,-18.249376),(23.501542,-18.23749),(23.49131,-18.23315),(23.477771,-18.230876),(23.464128,-18.225501),(23.458754,-18.217647),(23.444284,-18.200697),(23.429401,-18.188501),(23.418859,-18.198423),(23.410281,-18.197389),(23.40129,-18.194289),(23.395812,-18.191395),(23.394468,-18.186227),(23.396329,-18.169381),(23.395812,-18.163386),(23.389714,-18.153258),(23.359535,-18.119151),(23.348063,-18.09445),(23.336591,-18.07936),(23.3338,-18.073986),(23.33256,-18.067061),(23.3338,-18.04329),(23.330596,-18.039983),(23.323258,-18.039156),(23.31592,-18.037089),(23.312716,-18.029958),(23.312819,-18.016522),(23.311476,-18.009804),(23.305688,-18.005463),(23.292769,-17.998952),(23.254942,-17.997402),(23.185799,-18.003086),(23.099602,-18.010217),(22.981367,-18.020036),(22.894034,-18.036159),(22.809698,-18.051869),(22.725258,-18.067475),(22.640922,-18.083185),(22.556483,-18.098791),(22.472147,-18.1145),(22.387811,-18.13021),(22.303475,-18.145816),(22.219036,-18.161526),(22.134597,-18.177236),(22.050261,-18.192842),(21.966028,-18.208552),(21.881486,-18.224158),(21.79715,-18.239867),(21.71271,-18.255577),(21.628478,-18.271183),(21.544039,-18.28679),(21.526985,-18.289994),(21.509829,-18.293198),(21.492879,-18.296401),(21.475722,-18.299502),(21.456809,-18.300226),(21.437895,-18.301052),(21.39087,-18.302913),(21.343947,-18.304773),(21.296818,-18.306633),(21.249896,-18.308494),(21.193466,-18.310768),(21.136932,-18.312938),(21.080604,-18.315212),(21.024174,-18.317382),(20.993436,-18.318612),(20.975081,-18.319346),(20.975081,-18.347768),(20.975081,-18.388592),(20.975081,-18.429313),(20.975081,-18.470138),(20.975081,-18.511065),(20.975081,-18.551993),(20.975081,-18.592714),(20.975081,-18.633539),(20.975081,-18.674363),(20.975081,-18.715187),(20.975081,-18.756012),(20.975081,-18.796836),(20.975081,-18.83766),(20.975081,-18.878381),(20.975081,-18.919206),(20.975081,-18.96003),(20.975081,-19.000958),(20.975494,-19.125912),(20.975609,-19.172106),(20.975804,-19.250865),(20.976321,-19.375819),(20.976735,-19.500876),(20.977045,-19.625829),(20.977561,-19.750783),(20.977975,-19.87584),(20.978285,-20.000794),(20.978698,-20.125851),(20.979112,-20.250804),(20.97936,-20.351028),(20.979422,-20.375758),(20.979835,-20.500711),(20.980249,-20.625768),(20.980662,-20.750722),(20.981075,-20.875779),(20.981486,-20.999958),(20.981489,-21.000733),(20.981592,-21.058403),(20.981902,-21.116074),(20.982109,-21.173642),(20.982212,-21.231209),(20.982419,-21.28888),(20.982626,-21.346448),(20.982832,-21.404119),(20.983039,-21.46179),(20.983143,-21.519357),(20.983453,-21.577028),(20.983659,-21.634699),(20.983866,-21.69237),(20.984073,-21.750041),(20.984279,-21.807608),(20.984486,-21.865176),(20.984693,-21.922847),(20.984796,-21.963981),(20.97198,-22.000671),(20.914723,-22.000671),(20.680629,-22.000671),(20.446534,-22.000671),(20.21244,-22.000671),(19.978346,-22.000671),(19.978449,-22.086764),(19.978656,-22.237246),(19.978863,-22.387625),(19.978966,-22.538106),(19.979173,-22.688588),(19.979276,-22.860671),(19.979586,-23.032546),(19.979793,-23.204526),(19.979855,-23.308551),(19.979896,-23.376505),(19.980103,-23.548587),(19.98031,-23.720567),(19.980483,-23.864489),(19.980516,-23.892494),(19.980723,-24.064473),(19.980826,-24.236556),(19.981137,-24.408431),(19.981343,-24.580411),(19.981447,-24.752493),(19.981757,-24.764999),(19.981757,-24.821016),(19.981757,-24.877137),(19.981757,-24.933257),(19.98186,-24.989275),(19.981963,-25.045395),(19.981963,-25.101412),(19.981963,-25.15743),(19.981963,-25.21355),(19.981963,-25.269671),(19.981963,-25.325688),(19.981963,-25.381705),(19.982067,-25.437826),(19.982067,-25.493843),(19.982067,-25.549964),(19.982067,-25.606084),(19.982067,-25.618988),(19.982067,-25.662102),(19.982067,-25.718119),(19.982067,-25.774136),(19.982067,-25.830257),(19.98217,-25.886274),(19.982273,-25.942395),(19.982273,-25.998515),(19.982273,-26.054533),(19.982273,-26.11055),(19.982273,-26.16667),(19.982377,-26.222688),(19.982377,-26.278808),(19.982377,-26.334826),(19.982377,-26.390946),(19.982377,-26.446963),(19.982377,-26.503084),(19.98248,-26.559101),(19.982583,-26.615119),(19.982583,-26.671239),(19.982583,-26.727256),(19.982583,-26.783377),(19.982583,-26.839394),(19.982687,-26.895515),(19.982687,-26.951532),(19.982687,-27.007653),(19.982687,-27.06367),(19.982687,-27.119687),(19.982687,-27.175808),(19.98279,-27.231928),(19.982894,-27.287946),(19.982894,-27.344066),(19.982894,-27.400187),(19.982894,-27.456101),(19.982894,-27.512118),(19.982894,-27.568239),(19.982894,-27.624359),(19.982997,-27.680376),(19.982997,-27.736497),(19.982997,-27.792618),(19.982997,-27.848532),(19.982997,-27.904652),(19.982997,-27.960773),(19.982997,-28.01679),(19.982997,-28.072911),(19.9831,-28.129031),(19.983204,-28.185049),(19.983204,-28.241066),(19.983204,-28.297186),(19.983204,-28.353204),(19.983204,-28.392684),(19.981653,-28.422347),(19.950544,-28.429271),(19.940209,-28.430202),(19.907859,-28.426481),(19.896697,-28.427721),(19.870342,-28.440847),(19.82559,-28.47671),(19.796342,-28.484152),(19.748076,-28.487149),(19.725338,-28.494177),(19.705598,-28.508026),(19.688338,-28.515984),(19.587982,-28.522702),(19.579197,-28.525183),(19.568759,-28.531177),(19.562351,-28.538102),(19.55646,-28.546163),(19.547571,-28.555879),(19.542197,-28.564043),(19.533722,-28.58244),(19.527417,-28.585954),(19.517806,-28.589365),(19.511708,-28.598047),(19.482872,-28.678248),(19.472434,-28.692718),(19.45507,-28.705223),(19.434607,-28.713492),(19.353475,-28.731889),(19.339005,-28.73747),(19.32836,-28.735816),(19.304485,-28.718659),(19.290016,-28.719693),(19.277304,-28.729408),(19.265935,-28.742637),(19.248571,-28.771576),(19.244954,-28.792453),(19.251569,-28.814261),(19.288879,-28.871001),(19.288362,-28.883094),(19.27658,-28.889502),(19.243714,-28.891879),(19.237616,-28.895599),(19.226661,-28.911516),(19.218496,-28.918854),(19.161548,-28.945416),(19.120207,-28.957508),(19.081657,-28.959368),(19.064707,-28.939834),(19.060056,-28.9357),(19.048997,-28.932393),(19.01396,-28.928466),(19.006932,-28.926295),(18.99639,-28.915547),(18.971172,-28.88051),(18.954533,-28.866661),(18.745656,-28.839892),(18.553937,-28.864697),(18.51766,-28.882267),(18.496163,-28.888261),(18.491615,-28.886298),(18.479419,-28.876272),(18.474975,-28.873999),(18.469394,-28.874929),(18.460713,-28.87989),(18.455235,-28.88144),(18.435701,-28.884231),(18.424746,-28.887228),(18.416994,-28.891672),(18.397564,-28.898907),(18.373069,-28.895186),(18.331005,-28.88144),(18.30868,-28.879993),(18.220727,-28.891259),(18.18507,-28.902214),(18.166467,-28.901904),(18.082441,-28.875962),(18.044097,-28.858392),(17.983326,-28.813744),(17.949529,-28.794727),(17.913252,-28.781291),(17.746338,-28.748632),(17.714091,-28.751112),(17.703239,-28.755556),(17.683396,-28.767545),(17.673784,-28.771576),(17.660968,-28.772299),(17.628722,-28.764135),(17.607121,-28.75566),(17.602574,-28.735403),(17.603401,-28.710805),(17.598026,-28.689617),(17.582937,-28.680212),(17.565987,-28.683519),(17.54697,-28.691374),(17.526609,-28.695818),(17.485165,-28.700159),(17.44093,-28.709564),(17.403619,-28.704293),(17.401759,-28.674218),(17.414265,-28.63267),(17.420569,-28.593396),(17.409614,-28.571382),(17.373027,-28.559393),(17.365276,-28.542546),(17.359488,-28.519808),(17.332409,-28.488596),(17.324244,-28.470509),(17.328172,-28.456143),(17.341194,-28.442811),(17.358558,-28.432785),(17.375404,-28.428961),(17.39132,-28.418833),(17.399692,-28.395268),(17.402069,-28.367776),(17.400002,-28.346382),(17.394834,-28.335117),(17.378918,-28.316307),(17.371993,-28.306075),(17.368066,-28.293776),(17.367033,-28.283544),(17.364139,-28.273312),(17.355044,-28.261013),(17.35122,-28.251401),(17.349773,-28.238689),(17.345742,-28.22763),(17.334476,-28.222876),(17.308638,-28.224116),(17.245179,-28.237448),(17.21314,-28.232074),(17.191953,-28.20882),(17.187095,-28.162001),(17.189782,-28.139367),(17.189989,-28.116836),(17.180894,-28.099472),(17.155779,-28.092548),(17.136349,-28.084693),(17.123223,-28.066503),(17.111751,-28.046039),(17.097798,-28.031156),(17.086533,-28.027022),(17.076404,-28.026815),(17.056664,-28.031156),(17.045398,-28.036324),(17.012015,-28.058338),(16.98535,-28.05224),(16.973775,-28.055031),(16.959512,-28.06857),(16.947523,-28.072704),(16.937498,-28.07105),(16.927473,-28.060198),(16.919618,-28.058338),(16.91352,-28.062679),(16.896467,-28.079939),(16.892953,-28.082626),(16.885512,-28.162001),(16.878173,-28.172026),(16.873833,-28.171509),(16.868665,-28.167892),(16.852025,-28.168305),(16.847788,-28.165411),(16.843757,-28.163861),(16.837659,-28.168202),(16.835695,-28.174196),(16.838383,-28.179467),(16.855953,-28.199415),(16.856366,-28.206649),(16.84107,-28.209853),(16.819779,-28.20975),(16.814301,-28.213471),(16.810271,-28.222876),(16.813268,-28.229904),(16.820813,-28.240032),(16.8266,-28.251918),(16.824637,-28.264527),(16.815232,-28.270831),(16.805103,-28.267731),(16.795181,-28.26122),(16.786499,-28.257602),(16.768723,-28.265354),(16.764382,-28.283234),(16.768413,-28.303698),(16.775544,-28.319097),(16.796835,-28.347829),(16.803863,-28.366123),(16.793217,-28.374288),(16.778541,-28.382969),(16.773374,-28.402916),(16.772133,-28.425757),(16.769343,-28.442604),(16.758387,-28.459657),(16.740404,-28.480948),(16.720457,-28.496037),(16.703817,-28.494487),(16.699683,-28.485185),(16.696789,-28.472473),(16.692345,-28.461104),(16.683457,-28.456246),(16.673121,-28.45976),(16.597364,-28.526216),(16.559123,-28.537068),(16.531528,-28.549677),(16.50538,-28.565387),(16.487071,-28.572931),(16.468516,-28.585138),(16.458507,-28.600518),(16.445811,-28.610528),(16.419444,-28.607029),(16.407888,-28.600518),(16.346853,-28.556085),(16.315929,-28.524347),(16.301036,-28.50449),(16.19337,-28.408787),(16.175792,-28.402114),(16.167979,-28.395766),(16.107677,-28.323337),(16.04363,-28.257094),(15.911143,-28.171319),(15.884288,-28.147638),(15.833181,-28.089288),(15.761485,-28.038344),(15.747813,-28.024591),(15.716807,-27.980401),(15.684255,-27.949884),(15.678884,-27.942804),(15.677989,-27.931248),(15.684581,-27.910821),(15.685802,-27.9013),(15.673025,-27.869887),(15.646007,-27.836602),(15.546235,-27.747817),(15.533539,-27.730157),(15.528656,-27.70615),(15.529063,-27.654229),(15.526866,-27.646173),(15.520681,-27.633722),(15.425059,-27.496515),(15.408946,-27.464532),(15.396821,-27.448663),(15.380382,-27.44199),(15.371755,-27.433038),(15.342459,-27.380548),(15.301606,-27.333103),(15.295258,-27.322442),(15.281749,-27.243341),(15.276215,-27.233575),(15.269542,-27.226332),(15.263682,-27.218357),(15.261241,-27.205743),(15.268077,-27.164809),(15.254161,-27.100193),(15.261241,-27.085626),(15.241222,-27.048761),(15.235362,-27.029474),(15.233246,-27.006931),(15.234223,-26.965427),(15.228526,-26.945571),(15.212738,-26.927992),(15.20574,-26.925551),(15.187511,-26.924249),(15.178559,-26.921157),(15.176606,-26.916762),(15.169688,-26.906183),(15.162364,-26.897068),(15.158865,-26.897068),(15.155935,-26.875095),(15.148936,-26.856378),(15.116873,-26.796157),(15.111664,-26.779229),(15.116222,-26.752048),(15.105724,-26.732354),(15.091563,-26.712172),(15.083018,-26.695245),(15.080821,-26.672133),(15.083507,-26.652114),(15.091807,-26.637953),(15.106619,-26.632582),(15.116954,-26.630304),(15.127126,-26.626723),(15.134613,-26.62713),(15.137706,-26.636651),(15.137706,-26.6749),(15.144542,-26.6749),(15.148448,-26.655043),(15.168142,-26.602797),(15.168712,-26.592218),(15.162283,-26.579034),(15.141938,-26.517999),(15.128754,-26.457615),(15.105642,-26.420587),(15.07252,-26.389744),(15.034679,-26.366306),(14.975271,-26.344171),(14.966319,-26.335219),(14.958832,-26.257013),(14.962657,-26.181329),(14.942556,-26.153904),(14.939138,-26.147149),(14.943126,-26.135349),(14.949067,-26.135024),(14.956879,-26.137628),(14.966319,-26.133559),(14.979828,-26.101658),(14.979015,-26.05877),(14.968272,-26.015802),(14.952647,-25.98268),(14.907725,-25.915297),(14.90211,-25.882501),(14.91863,-25.845473),(14.911143,-25.845473),(14.859874,-25.790297),(14.842784,-25.763604),(14.840343,-25.751723),(14.840343,-25.743341),(14.842784,-25.729425),(14.842784,-25.650323),(14.846934,-25.629815),(14.876964,-25.578058),(14.879731,-25.561456),(14.879568,-25.53867),(14.875336,-25.518487),(14.853282,-25.498712),(14.847016,-25.473321),(14.842784,-25.42783),(14.818044,-25.366957),(14.812511,-25.320082),(14.802419,-25.282892),(14.80128,-25.262791),(14.832286,-25.188165),(14.829356,-25.176446),(14.84962,-25.105076),(14.853282,-25.064223),(14.843272,-25.026056),(14.829438,-25.000095),(14.808767,-24.961114),(14.796153,-24.92197),(14.792979,-24.841892),(14.780772,-24.803399),(14.723481,-24.703546),(14.699474,-24.673028),(14.650157,-24.628839),(14.636078,-24.598891),(14.601899,-24.562433),(14.595876,-24.537205),(14.59962,-24.526544),(14.61378,-24.511651),(14.616954,-24.505792),(14.616954,-24.464776),(14.612315,-24.445733),(14.590099,-24.40838),(14.568126,-24.35768),(14.513927,-24.261489),(14.493175,-24.192315),(14.473643,-24.159112),(14.466807,-24.113214),(14.459239,-24.098321),(14.464203,-24.07822),(14.464122,-24.044692),(14.459646,-24.010431),(14.451915,-23.988458),(14.459239,-23.974542),(14.465831,-23.947198),(14.472911,-23.933852),(14.479177,-23.931085),(14.488292,-23.92962),(14.496593,-23.925958),(14.500255,-23.916436),(14.513927,-23.892267),(14.506033,-23.88006),(14.507091,-23.823907),(14.489513,-23.776056),(14.486583,-23.758477),(14.500255,-23.614435),(14.495291,-23.578546),(14.48406,-23.551039),(14.446951,-23.460382),(14.434337,-23.415216),(14.435069,-23.405532),(14.443126,-23.396661),(14.467459,-23.356052),(14.479747,-23.344822),(14.479503,-23.365818),(14.484386,-23.374933),(14.490408,-23.369724),(14.493419,-23.347833),(14.491954,-23.309177),(14.473481,-23.192804),(14.462738,-23.157403),(14.445567,-23.13128),(14.431326,-23.103285),(14.420665,-23.070977),(14.413829,-23.036228),(14.410167,-22.970798),(14.411388,-22.961196),(14.416026,-22.951593),(14.429047,-22.93255),(14.431895,-22.923028),(14.431895,-22.881768),(14.435069,-22.879815),(14.440929,-22.879815),(14.443858,-22.883477),(14.438162,-22.892267),(14.442719,-22.898533),(14.44809,-22.908136),(14.451915,-22.912205),(14.445974,-22.932387),(14.444347,-22.952813),(14.451671,-22.963311),(14.472911,-22.95379),(14.471446,-22.965102),(14.459239,-22.995294),(14.474294,-22.982192),(14.496837,-22.941827),(14.510509,-22.933282),(14.521983,-22.923435),(14.529307,-22.90016),(14.534353,-22.854181),(14.527517,-22.679457),(14.508556,-22.548028),(14.485118,-22.512384),(14.474294,-22.467869),(14.438162,-22.398858),(14.418712,-22.339776),(14.386485,-22.276462),(14.380382,-22.268487),(14.315196,-22.200291),(14.294281,-22.167413),(14.293468,-22.143324),(14.291352,-22.134454),(14.137218,-21.946384),(14.062022,-21.880955),(14.05421,-21.864679),(13.97169,-21.792739),(13.952322,-21.783949),(13.952159,-21.77337),(13.956391,-21.762953),(13.958995,-21.758396),(13.96518,-21.733168),(13.965831,-21.726739),(13.962657,-21.714044),(13.958263,-21.704848),(13.87794,-21.592218),(13.862804,-21.528009),(13.831716,-21.456476),(13.729259,-21.330255),(13.66684,-21.232354),(13.628103,-21.187595),(13.602712,-21.158136),(13.513357,-21.007908),(13.471934,-20.955011),(13.459158,-20.918064),(13.444835,-20.904067),(13.417735,-20.883884),(13.397634,-20.849298),(13.387218,-20.816095),(13.37672,-20.733575),(13.349457,-20.644464),(13.262706,-20.485121),(13.239024,-20.397149),(13.233572,-20.354669),(13.213064,-20.27337),(13.177745,-20.189223),(13.154633,-20.154229),(13.114425,-20.142573),(13.07088,-20.114229),(13.037345,-20.059465),(13.005382,-19.935479),(12.927745,-19.794692),(12.918468,-19.765558),(12.875987,-19.712009),(12.802501,-19.584731),(12.793956,-19.5617),(12.783051,-19.54697),(12.757579,-19.49684),(12.749278,-19.486017),(12.7046,-19.410821),(12.691091,-19.379002),(12.686046,-19.359796),(12.679698,-19.31406),(12.668305,-19.292413),(12.636241,-19.252618),(12.615733,-19.217543),(12.567393,-19.102309),(12.546723,-19.071466),(12.516449,-19.03753),(12.480317,-19.011),(12.470388,-18.997654),(12.458669,-18.925551),(12.450043,-18.904555),(12.286876,-18.697686),(12.174731,-18.627939),(12.125743,-18.574802),(12.11964,-18.569513),(12.102061,-18.545994),(12.091645,-18.540704),(12.082042,-18.534356),(12.031889,-18.50535),(12.015961,-18.452895),(12.012462,-18.434503),(11.999522,-18.403497),(11.99822,-18.39186),(11.998546,-18.381768),(11.997569,-18.372003),(11.999522,-18.361912),(11.976085,-18.329767),(11.937348,-18.23211),(11.931163,-18.225356),(11.849082,-18.143183),(11.83364,-18.098045),(11.826524,-18.03922),(11.808499,-17.991542),(11.796911,-17.956089),(11.784037,-17.859645),(11.760941,-17.786424),(11.745552,-17.683948),(11.734031,-17.632721),(11.726736,-17.599867),(11.717621,-17.546319),(11.72169,-17.467869),(11.755138,-17.266697),(11.766124,-17.252699),(11.766184,-17.252751),(11.779518,-17.254915),(11.796882,-17.263803),(11.80763,-17.26587),(11.82241,-17.264423),(11.827474,-17.260082),(11.829644,-17.253468),(11.835536,-17.245406),(11.853932,-17.233417),(11.894963,-17.214607),(11.942092,-17.180501),(11.98302,-17.161897),(12.028909,-17.148978),(12.075211,-17.142983),(12.082239,-17.14133),(12.08813,-17.139159),(12.095261,-17.139676),(12.105597,-17.146084),(12.13991,-17.156006),(12.151279,-17.153629),(12.156653,-17.149081),(12.16151,-17.146291),(12.170709,-17.149185),(12.177117,-17.154766),(12.179494,-17.161587),(12.181148,-17.169235),(12.185075,-17.17709),(12.190656,-17.182568),(12.200474,-17.189286),(12.21174,-17.195177),(12.222282,-17.197657),(12.23179,-17.201895),(12.236545,-17.2113),(12.239335,-17.220705),(12.242642,-17.224839),(12.314679,-17.218121),(12.379482,-17.220395),(12.393951,-17.21471),(12.407594,-17.204065),(12.417929,-17.203445),(12.4417,-17.216984),(12.46051,-17.223082),(12.519215,-17.227836),(12.554561,-17.235588),(12.56717,-17.234554),(12.591458,-17.222565),(12.63621,-17.185151),(12.660705,-17.17709),(12.685923,-17.173576),(12.704733,-17.164274),(12.739873,-17.135542),(12.784315,-17.115078),(12.818318,-17.104846),(12.824932,-17.096371),(12.833097,-17.081799),(12.842296,-17.074047),(12.849944,-17.070843),(12.867721,-17.065572),(12.876402,-17.059784),(12.880536,-17.050793),(12.882293,-17.039527),(12.887151,-17.029812),(12.911025,-17.023508),(12.930456,-17.014206),(12.961668,-17.007385),(13.014275,-16.977929),(13.121762,-16.959842),(13.1445,-16.952401),(13.166307,-16.951057),(13.184911,-16.964183)] +Niger [(14.216217,22.616295),(14.23172,22.617949),(14.294869,22.649833),(14.466021,22.736184),(14.63707,22.822536),(14.808016,22.908887),(14.979168,22.995316),(14.979271,22.995368),(14.979909,22.995664),(14.991984,22.933097),(15.003973,22.87044),(15.015858,22.807782),(15.02795,22.745176),(15.039939,22.682544),(15.051928,22.619861),(15.064021,22.557177),(15.075906,22.494597),(15.087998,22.431914),(15.099987,22.369282),(15.11208,22.306598),(15.124069,22.243966),(15.136058,22.181335),(15.14815,22.118651),(15.156315,22.076173),(15.16448,22.033695),(15.172024,21.993387),(15.172438,21.973647),(15.173265,21.921557),(15.174608,21.847918),(15.176055,21.763427),(15.177502,21.678988),(15.178846,21.605297),(15.179776,21.553208),(15.180086,21.533467),(15.180396,21.507267),(15.18453,21.491196),(15.20024,21.476468),(15.247472,21.453265),(15.266592,21.440656),(15.301009,21.40133),(15.32478,21.366707),(15.34142,21.342161),(15.358266,21.317718),(15.375009,21.293223),(15.391753,21.268729),(15.408496,21.244234),(15.425342,21.219791),(15.441982,21.195193),(15.458829,21.17075),(15.475572,21.146256),(15.492212,21.121761),(15.509058,21.097266),(15.525801,21.072772),(15.542544,21.048277),(15.559288,21.023782),(15.576134,20.999339),(15.592774,20.974793),(15.60931,20.95066),(15.569003,20.928905),(15.544301,20.890302),(15.536033,20.844052),(15.544198,20.79899),(15.556084,20.773669),(15.570243,20.751913),(15.588123,20.732792),(15.669462,20.671866),(15.697264,20.642875),(15.755555,20.582001),(15.813846,20.521074),(15.872033,20.460199),(15.930324,20.399324),(15.953992,20.374571),(15.968151,20.352816),(15.970322,20.336331),(15.962984,20.319226),(15.94252,20.283957),(15.902419,20.214943),(15.862318,20.145955),(15.822321,20.076993),(15.782323,20.00803),(15.767234,19.982037),(15.736021,19.903541),(15.732404,19.861838),(15.728373,19.816259),(15.724342,19.770577),(15.720208,19.724999),(15.716177,19.679317),(15.712146,19.633764),(15.708116,19.588108),(15.704085,19.542529),(15.700054,19.496873),(15.696023,19.451243),(15.692096,19.405638),(15.687962,19.360008),(15.683931,19.314404),(15.6799,19.268747),(15.67587,19.223169),(15.671839,19.177539),(15.667808,19.131882),(15.663777,19.086304),(15.659747,19.040648),(15.655716,18.995069),(15.651582,18.949387),(15.647551,18.903834),(15.64352,18.858178),(15.639593,18.8126),(15.635562,18.766943),(15.631531,18.721313),(15.6275,18.675709),(15.62347,18.630078),(15.619439,18.584474),(15.615305,18.538818),(15.611274,18.493239),(15.607243,18.447583),(15.603213,18.402004),(15.599182,18.356348),(15.595151,18.310718),(15.59112,18.265088),(15.587193,18.219483),(15.583162,18.173879),(15.579028,18.128249),(15.574997,18.082644),(15.570966,18.03704),(15.567698,18.000039),(15.566936,17.991409),(15.562905,17.945779),(15.558874,17.900149),(15.554843,17.85457),(15.550813,17.808888),(15.546782,17.76331),(15.542648,17.717679),(15.538617,17.672049),(15.53469,17.626367),(15.530659,17.580737),(15.526628,17.535107),(15.522597,17.489528),(15.518567,17.443846),(15.514536,17.398267),(15.510505,17.352637),(15.506371,17.307058),(15.50234,17.261376),(15.498309,17.215746),(15.494279,17.170116),(15.490248,17.124537),(15.486217,17.078907),(15.48229,17.033277),(15.478259,16.987698),(15.474125,16.942068),(15.471954,16.916746),(15.468517,16.90491),(15.465547,16.89468),(15.452421,16.876232),(15.418418,16.840885),(15.3624,16.782646),(15.30628,16.7242),(15.250159,16.665909),(15.194039,16.607566),(15.137918,16.549275),(15.081797,16.490881),(15.02578,16.432538),(14.969659,16.374247),(14.913539,16.315904),(14.857418,16.257613),(14.801401,16.199219),(14.745384,16.140876),(14.689263,16.082534),(14.633143,16.024243),(14.576919,15.965797),(14.520798,15.907557),(14.482144,15.86725),(14.423543,15.806323),(14.368973,15.749634),(14.340447,15.710722),(14.310682,15.669949),(14.280709,15.629254),(14.250944,15.588455),(14.221178,15.547734),(14.191206,15.507039),(14.16144,15.466292),(14.131571,15.425545),(14.101702,15.384876),(14.071833,15.344181),(14.042068,15.303434),(14.012199,15.262687),(13.98233,15.221992),(13.952564,15.181219),(13.922592,15.140498),(13.892826,15.0997),(13.862957,15.059056),(13.833915,15.019601),(13.808077,14.965573),(13.775417,14.897438),(13.760534,14.866355),(13.75516,14.847209),(13.75392,14.825944),(13.75795,14.805532),(13.772006,14.762873),(13.773247,14.742512),(13.764358,14.719077),(13.749165,14.711248),(13.730045,14.709646),(13.709995,14.705124),(13.700021,14.697734),(13.668085,14.662879),(13.648345,14.649417),(13.644727,14.644249),(13.646278,14.639056),(13.657026,14.629651),(13.660334,14.623734),(13.666742,14.585519),(13.665605,14.56689),(13.657853,14.548725),(13.624264,14.521311),(13.608052,14.518266),(13.584369,14.513818),(13.543855,14.510562),(13.507785,14.495964),(13.482257,14.483587),(13.449494,14.439042),(13.449184,14.380131),(13.468304,14.310678),(13.482257,14.259777),(13.492695,14.213862),(13.499723,14.181978),(13.506958,14.150119),(13.514193,14.118235),(13.521324,14.086428),(13.528455,14.054518),(13.53569,14.022737),(13.542821,13.990853),(13.549953,13.958994),(13.557188,13.927161),(13.564319,13.895225),(13.57145,13.863418),(13.578582,13.831534),(13.585816,13.799727),(13.592948,13.767843),(13.600182,13.735984),(13.607314,13.7041),(13.35999,13.714409),(13.35892,13.714232),(13.329915,13.709423),(13.320716,13.702291),(13.321233,13.685109),(13.30604,13.674644),(13.266146,13.638032),(13.259221,13.628963),(13.253847,13.618911),(13.253537,13.614881),(13.258601,13.607801),(13.260048,13.602142),(13.257258,13.594236),(13.25085,13.592763),(13.243822,13.593254),(13.239481,13.591575),(13.230179,13.577751),(13.232246,13.572894),(13.246405,13.571085),(13.228112,13.548037),(13.203927,13.539381),(13.176952,13.534472),(13.150184,13.522664),(13.153698,13.5307),(13.155868,13.540777),(13.153698,13.548761),(13.143983,13.550621),(13.138402,13.546539),(13.13096,13.529821),(13.123519,13.522664),(13.123829,13.533439),(13.123519,13.536953),(13.107086,13.531552),(13.088276,13.530596),(13.07701,13.534679),(13.082488,13.544394),(13.082488,13.550621),(13.054893,13.548373),(13.029261,13.539175),(12.939344,13.495069),(12.911749,13.489901),(12.883844,13.495999),(12.87971,13.479695),(12.870614,13.478868),(12.857799,13.484914),(12.842296,13.489126),(12.842296,13.481685),(12.850564,13.479385),(12.857592,13.475328),(12.863897,13.469282),(12.870201,13.461247),(12.857075,13.450653),(12.829273,13.420293),(12.82855,13.417451),(12.829997,13.409364),(12.829273,13.406625),(12.826276,13.406056),(12.817594,13.407296),(12.815011,13.406625),(12.81067,13.404299),(12.797337,13.399648),(12.794547,13.396057),(12.798474,13.384275),(12.804779,13.376859),(12.805192,13.372983),(12.791136,13.371846),(12.788966,13.375464),(12.783281,13.382337),(12.77739,13.386703),(12.7746,13.382698),(12.773256,13.382233),(12.766538,13.365671),(12.740803,13.33482),(12.72437,13.322289),(12.701736,13.31725),(12.690057,13.311979),(12.683132,13.288932),(12.674347,13.283712),(12.659155,13.286606),(12.649233,13.293608),(12.640654,13.302393),(12.630009,13.310377),(12.628769,13.294177),(12.626805,13.28826),(12.62019,13.281438),(12.613266,13.276503),(12.606134,13.27423),(12.602724,13.279992),(12.597556,13.276503),(12.561073,13.242759),(12.558179,13.226532),(12.545156,13.208213),(12.538335,13.193356),(12.554251,13.187542),(12.547947,13.165451),(12.542572,13.15478),(12.534511,13.145917),(12.526966,13.143643),(12.504332,13.139613),(12.499784,13.135969),(12.491206,13.082639),(12.486659,13.070805),(12.472706,13.064165),(12.456376,13.067421),(12.437256,13.074009),(12.414312,13.077627),(12.386742,13.07858),(12.351576,13.079797),(12.335247,13.084474),(12.325738,13.078815),(12.3184,13.083854),(12.310959,13.092639),(12.301037,13.098116),(12.291528,13.096824),(12.285327,13.092019),(12.280883,13.086851),(12.277162,13.084474),(12.269204,13.085869),(12.267447,13.089641),(12.267034,13.095171),(12.26321,13.101863),(12.251841,13.108012),(12.201405,13.125427),(12.184765,13.122094),(12.163784,13.107961),(12.149625,13.105584),(12.116449,13.102845),(12.057641,13.116772),(12.038004,13.126358),(11.991908,13.162092),(11.852795,13.245394),(11.742311,13.289448),(11.440004,13.364431),(10.953005,13.361899),(10.771311,13.382698),(10.674986,13.375102),(10.647882,13.369406),(10.161529,13.267202),(10.119775,13.250097),(9.930122,13.145969),(9.912449,13.1292),(9.908211,13.118787),(9.904387,13.094344),(9.899736,13.084319),(9.891778,13.076231),(9.887747,13.075508),(9.882683,13.076231),(9.872038,13.072562),(9.852814,13.060444),(9.819328,13.029206),(9.647657,12.830538),(9.640734,12.822526),(9.629262,12.812785),(9.61841,12.805783),(9.611485,12.802941),(9.590298,12.80139),(9.377908,12.825782),(9.359821,12.824593),(9.306491,12.809839),(9.269387,12.809788),(8.977872,12.843183),(8.942792,12.847201),(8.679346,12.923579),(8.642655,12.944353),(8.625499,12.964791),(8.596767,13.011403),(8.577233,13.032436),(8.533515,13.06463),(8.50964,13.075921),(8.482665,13.081554),(8.47078,13.081657),(8.445975,13.078712),(8.434503,13.075095),(8.423134,13.069488),(8.419,13.066697),(8.415176,13.067059),(8.405151,13.070857),(8.397813,13.075405),(8.297974,13.164624),(8.273066,13.193873),(8.259836,13.205216),(8.246728,13.211292),(8.245677,13.211779),(8.216015,13.219608),(8.201442,13.226377),(8.167646,13.252371),(8.14005,13.269114),(8.116589,13.29105),(8.105117,13.299654),(8.077522,13.310016),(7.823997,13.345285),(7.789684,13.341977),(7.755578,13.327146),(7.391982,13.112534),(7.360667,13.102638),(7.324803,13.102845),(7.22052,13.121577),(7.198196,13.117392),(7.137424,13.047241),(7.090089,13.006391),(7.068695,12.996081),(7.062921,12.99514),(7.044924,12.992206),(6.970509,12.991844),(6.937127,12.995409),(6.906637,13.006856),(6.874185,13.030498),(6.837908,13.063493),(6.778687,13.130285),(6.753879,13.1749),(6.672543,13.321178),(6.509297,13.496051),(6.368944,13.626275),(6.302178,13.663844),(6.284208,13.667656),(6.229831,13.679192),(6.210608,13.675265),(6.152833,13.643561),(6.142395,13.640822),(6.13578,13.643664),(6.129476,13.649065),(6.12038,13.654077),(5.837349,13.763748),(5.554317,13.873418),(5.521761,13.880291),(5.374069,13.855254),(5.346268,13.841559),(5.334795,13.826702),(5.318052,13.789935),(5.304203,13.773941),(5.273507,13.752521),(5.262035,13.747741),(5.227618,13.741333),(5.084371,13.747534),(4.983189,13.72968),(4.925105,13.733091),(4.902367,13.742987),(4.879836,13.764019),(4.856892,13.774096),(4.824852,13.770737),(4.625845,13.723151),(4.506732,13.694669),(4.452575,13.673766),(4.405756,13.641236),(4.248453,13.494139),(4.220548,13.480625),(4.190472,13.475018),(4.125774,13.472977),(4.123707,13.233586),(4.120325,13.210608),(4.088773,12.996236),(3.929093,12.750386),(3.864394,12.689666),(3.6457,12.528539),(3.641565,12.517997),(3.651487,12.26902),(3.624512,12.137658),(3.623995,12.09425),(3.648903,12.021024),(3.653554,11.986815),(3.636604,11.953587),(3.619551,11.936275),(3.608492,11.921961),(3.603945,11.905579),(3.609733,11.848787),(3.612937,11.838968),(3.618621,11.828375),(3.622032,11.825016),(3.626269,11.822535),(3.64973,11.797834),(3.662029,11.779489),(3.66699,11.759697),(3.659859,11.738096),(3.647767,11.726004),(3.5964,11.695773),(3.589372,11.701509),(3.58007,11.717374),(3.571699,11.72187),(3.568185,11.729518),(3.566221,11.738354),(3.5625,11.746003),(3.557436,11.761815),(3.553715,11.76967),(3.549271,11.773753),(3.54369,11.77706),(3.536972,11.782899),(3.503486,11.829977),(3.495424,11.837521),(3.484262,11.84517),(3.447675,11.857985),(3.40282,11.88527),(3.391658,11.888836),(3.380909,11.895037),(3.369127,11.897311),(3.355071,11.889043),(3.341635,11.882893),(3.327786,11.886407),(3.315487,11.894572),(3.307012,11.902375),(3.292749,11.918653),(3.269908,11.956532),(3.26257,11.974722),(3.257609,11.997408),(3.255129,12.018751),(3.252028,12.024125),(3.238489,12.034202),(3.235389,12.039525),(3.063409,12.193779),(3.022895,12.252483),(3.013077,12.271087),(3.009356,12.276306),(3.000984,12.27889),(2.967808,12.282559),(2.956026,12.286848),(2.944967,12.292481),(2.936802,12.300852),(2.930394,12.323332),(2.922643,12.335631),(2.912618,12.346328),(2.892257,12.357076),(2.844301,12.399244),(2.832416,12.384051),(2.808645,12.383225),(2.798413,12.381209),(2.778156,12.381933),(2.768544,12.380072),(2.757485,12.372941),(2.741465,12.354131),(2.732267,12.346793),(2.721828,12.344261),(2.711286,12.351237),(2.700434,12.347103),(2.69506,12.341212),(2.692166,12.334029),(2.690202,12.326174),(2.686895,12.318422),(2.672942,12.296718),(2.663847,12.291551),(2.628604,12.300801),(2.621679,12.299509),(2.60969,12.290775),(2.603593,12.28783),(2.598632,12.288347),(2.590053,12.293308),(2.586126,12.294031),(2.550573,12.284523),(2.546025,12.281629),(2.53693,12.27305),(2.531246,12.269691),(2.523701,12.269175),(2.5206,12.273671),(2.51905,12.279148),(2.516259,12.281422),(2.504477,12.281835),(2.495072,12.283231),(2.488044,12.280388),(2.483393,12.268038),(2.477709,12.257599),(2.472644,12.259253),(2.46696,12.265041),(2.459519,12.266746),(2.454351,12.263025),(2.446083,12.251811),(2.443706,12.249228),(2.43089,12.247987),(2.407946,12.248918),(2.3942,12.247212),(2.370015,12.236257),(2.36123,12.218894),(2.362057,12.196156),(2.371875,12.140449),(2.405568,12.046708),(2.41115,12.036786),(2.418281,12.028673),(2.428616,12.020353),(2.439262,12.015598),(2.44877,12.013376),(2.455281,12.008674),(2.457348,11.99622),(2.456728,11.979063),(2.44939,11.977513),(2.438951,11.981285),(2.428926,11.980355),(2.422002,11.973172),(2.414147,11.958703),(2.407429,11.95121),(2.398747,11.948781),(2.389342,11.950073),(2.380867,11.947902),(2.375183,11.935035),(2.376526,11.924079),(2.388205,11.906768),(2.390169,11.896536),(2.338079,11.940099),(2.258807,12.048775),(2.188527,12.145461),(2.113803,12.247987),(2.070912,12.306898),(2.051792,12.341935),(2.054169,12.370926),(2.069258,12.383328),(2.126929,12.39511),(2.131477,12.398521),(2.138711,12.408339),(2.145016,12.41175),(2.148013,12.410768),(2.158762,12.405652),(2.163826,12.404774),(2.223254,12.409735),(2.23793,12.413455),(2.244958,12.424152),(2.242994,12.446166),(2.243098,12.451179),(2.246302,12.461669),(2.246302,12.465907),(2.242271,12.473452),(2.229559,12.487146),(2.223874,12.494846),(2.215709,12.510349),(2.210852,12.523061),(2.203204,12.583316),(2.2,12.595925),(2.193282,12.609464),(2.18429,12.620626),(2.165997,12.631737),(2.155455,12.640005),(2.144809,12.650753),(2.140985,12.656128),(2.135197,12.67561),(2.109049,12.705634),(2.068948,12.716279),(1.971693,12.724237),(1.962495,12.719121),(1.945545,12.700828),(1.934486,12.693542),(1.926631,12.694989),(1.919603,12.698347),(1.911438,12.696642),(1.906994,12.691836),(1.900173,12.678452),(1.883223,12.653957),(1.872681,12.634217),(1.860692,12.61706),(1.843742,12.606105),(1.826069,12.604193),(1.699462,12.61489),(1.597039,12.623675),(1.563863,12.63215),(1.535854,12.647498),(1.467124,12.704394),(1.412037,12.749869),(1.330595,12.817177),(1.304806,12.838508),(1.230756,12.899756),(1.170915,12.949211),(1.113968,12.996236),(1.083789,13.01099),(1.012269,13.016881),(0.983536,13.032358),(0.974648,13.048326),(0.971754,13.067317),(0.971661,13.085782),(0.971341,13.149405),(0.970824,13.243534),(0.970411,13.328335),(0.983536,13.36841),(1.004724,13.364844),(1.084719,13.33358),(1.138462,13.320377),(1.160683,13.311307),(1.167608,13.313426),(1.177633,13.34761),(1.182387,13.358695),(1.187658,13.364121),(1.205745,13.358901),(1.222075,13.344613),(1.241505,13.335544),(1.268687,13.34606),(1.249567,13.367066),(1.23427,13.377583),(1.217424,13.381768),(1.175049,13.38691),(1.157169,13.392646),(1.048235,13.441945),(1.015266,13.465665),(0.996559,13.496051),(0.991391,13.541113),(0.95098,13.583203),(0.896927,13.614932),(0.850728,13.628601),(0.813108,13.625035),(0.795331,13.625965),(0.775694,13.635293),(0.763705,13.646429),(0.762878,13.653044),(0.766289,13.657178),(0.767012,13.660873),(0.766185,13.666971),(0.766392,13.67511),(0.763498,13.682034),(0.75337,13.684101),(0.620665,13.679967),(0.59431,13.688881),(0.58046,13.713789),(0.584801,13.729008),(0.594516,13.74986),(0.600511,13.768721),(0.593689,13.778101),(0.574466,13.785025),(0.5632,13.796782),(0.552968,13.810037),(0.519275,13.831637),(0.504082,13.845358),(0.499926,13.851015),(0.49199,13.861817),(0.483515,13.880343),(0.47566,13.888947),(0.454809,13.902357),(0.448634,13.909617),(0.448065,13.920108),(0.456256,13.938143),(0.456695,13.94685),(0.445921,13.958581),(0.428377,13.967495),(0.411866,13.978424),(0.403934,13.996072),(0.401866,14.013797),(0.391376,14.022582),(0.378354,14.028809),(0.369155,14.039067),(0.369052,14.047852),(0.37732,14.063949),(0.378457,14.070434),(0.37422,14.078883),(0.368742,14.084154),(0.362463,14.088857),(0.356262,14.095704),(0.343575,14.114333),(0.339157,14.12578),(0.343472,14.137536),(0.367398,14.173787),(0.372153,14.185647),(0.377424,14.216601),(0.381118,14.22567),(0.390601,14.237633),(0.391635,14.245927),(0.388792,14.251612),(0.346366,14.307577),(0.202382,14.435545),(0.18865,14.44775),(0.158832,14.496119),(0.152941,14.54671),(0.219707,14.731221),(0.213092,14.761632),(0.184102,14.819562),(0.185756,14.84819),(0.198003,14.863797),(0.211852,14.874804),(0.220844,14.888214),(0.218467,14.910977),(0.212782,14.960716),(0.213196,14.985417),(0.221257,14.995933),(0.353187,14.963429),(0.387035,14.963248),(0.418791,14.969888),(0.483515,14.992109),(0.514831,14.993556),(0.670067,14.939735),(0.683813,14.940872),(0.711408,14.947461),(0.739934,14.958339),(0.769183,14.969062),(0.922145,14.973971),(0.949327,14.979552),(0.973718,14.991257),(1.057537,15.067118),(1.123063,15.126313),(1.203161,15.198789),(1.270857,15.259897),(1.297832,15.275735),(1.331526,15.283616),(1.405216,15.286148),(1.501748,15.289352),(1.598383,15.292608),(1.694914,15.295734),(1.791446,15.29899),(1.888081,15.302194),(1.984612,15.305398),(2.081351,15.308576),(2.177882,15.311831),(2.274517,15.314984),(2.371049,15.318239),(2.467684,15.321417),(2.564215,15.324595),(2.660953,15.327825),(2.757485,15.331081),(2.85412,15.334207),(2.950651,15.337463),(3.000158,15.339117),(3.005739,15.35232),(3.005842,15.389294),(3.007806,15.407665),(3.010286,15.417665),(3.017521,15.422832),(3.03354,15.42645),(3.073021,15.427199),(3.19229,15.40751),(3.380393,15.376324),(3.483332,15.359296),(3.48881,15.357539),(3.507103,15.353973),(3.516508,15.469186),(3.526534,15.495954),(3.614074,15.547734),(3.692208,15.63145),(3.728899,15.65088),(3.808377,15.665582),(3.846101,15.685297),(3.871215,15.714804),(3.873849,15.720882),(3.886512,15.750099),(3.89447,15.78865),(3.903462,15.886318),(3.909869,15.904767),(3.925062,15.927608),(3.98325,15.983987),(3.98418,15.986881),(3.9848,15.989826),(3.984594,15.995924),(3.984697,15.997371),(3.98449,15.998766),(3.983973,16.00011),(3.98325,16.00135),(3.970848,16.030857),(3.96692,16.058504),(3.971158,16.086099),(4.060558,16.298334),(4.075647,16.321072),(4.094768,16.340812),(4.118229,16.358331),(4.16174,16.379983),(4.1759,16.392644),(4.183961,16.416053),(4.183444,16.526538),(4.183031,16.612682),(4.182308,16.746472),(4.181998,16.809621),(4.184581,16.818509),(4.197604,16.838508),(4.202048,16.848895),(4.19657,16.947132),(4.197811,16.965219),(4.203702,16.982789),(4.21166,16.986044),(4.222305,16.986561),(4.235638,16.995863),(4.235328,17.100818),(4.235018,17.163915),(4.234707,17.287525),(4.234294,17.411186),(4.233777,17.534796),(4.233364,17.658458),(4.233054,17.78212),(4.23264,17.905782),(4.232408,17.975234),(4.232227,18.029443),(4.231917,18.153105),(4.231504,18.276741),(4.23109,18.400325),(4.230677,18.524038),(4.230271,18.645374),(4.230263,18.647648),(4.22985,18.771284),(4.229436,18.894946),(4.229023,19.018582),(4.22861,19.142244),(4.417229,19.178417),(4.605848,19.214616),(4.794467,19.250764),(4.983189,19.286963),(5.082821,19.306006),(5.301826,19.347993),(5.520831,19.389903),(5.620463,19.408997),(5.749344,19.433699),(5.794302,19.449796),(5.837607,19.478631),(5.916362,19.546276),(5.979407,19.600536),(6.042556,19.654745),(6.105601,19.709005),(6.168646,19.763213),(6.231692,19.817474),(6.294737,19.871682),(6.357782,19.925917),(6.420931,19.980177),(6.483769,20.034385),(6.546918,20.088646),(6.609963,20.142854),(6.672957,20.197115),(6.736105,20.251323),(6.799047,20.305532),(6.862092,20.35974),(6.925138,20.414001),(6.982808,20.46361),(7.020532,20.495443),(7.098047,20.558746),(7.169464,20.616986),(7.240881,20.675173),(7.312297,20.733464),(7.383611,20.791652),(7.482726,20.872577),(7.613778,20.94973),(7.681887,20.989831),(7.74979,21.029984),(7.8179,21.070085),(7.886009,21.110237),(7.953912,21.15039),(8.022022,21.190491),(8.090131,21.230592),(8.158034,21.270744),(8.226143,21.310845),(8.294253,21.350946),(8.362259,21.391047),(8.430265,21.431148),(8.498375,21.4713),(8.566381,21.51135),(8.634491,21.551502),(8.702497,21.591655),(8.770606,21.631807),(8.838613,21.671908),(8.906722,21.712061),(8.974832,21.75211),(9.042838,21.792263),(9.110844,21.832364),(9.178953,21.872516),(9.24696,21.912565),(9.314966,21.952718),(9.383075,21.992819),(9.451082,22.03292),(9.519088,22.073072),(9.587197,22.113225),(9.655203,22.153326),(9.723313,22.193427),(9.791319,22.233579),(9.859325,22.27368),(9.927435,22.313781),(9.995441,22.353882),(10.063447,22.394035),(10.131557,22.434136),(10.199563,22.474237),(10.267569,22.514337),(10.335679,22.554542),(10.403788,22.594643),(10.471691,22.634744),(10.539801,22.674896),(10.607807,22.714945),(10.675813,22.755046),(10.743923,22.795199),(10.812032,22.835326),(10.880038,22.875375),(10.948148,22.915527),(11.016257,22.955654),(11.084367,22.995755),(11.15227,23.035882),(11.220379,23.07606),(11.288489,23.116161),(11.356392,23.156262),(11.424501,23.196415),(11.492611,23.236516),(11.560514,23.276591),(11.628623,23.316717),(11.696733,23.356844),(11.764739,23.396945),(11.832745,23.437046),(11.900855,23.477173),(11.968861,23.517351),(12.057021,23.497611),(12.145284,23.477948),(12.233651,23.458285),(12.321811,23.438622),(12.409971,23.418882),(12.498337,23.399245),(12.586497,23.379582),(12.674657,23.359893),(12.763024,23.340179),(12.851184,23.32049),(12.939447,23.300827),(13.027607,23.281138),(13.115871,23.261449),(13.204134,23.241709),(13.292398,23.222098),(13.380661,23.202383),(13.482257,23.179672),(13.599562,23.119029),(13.655786,23.072624),(13.780895,22.969633),(13.906055,22.866616),(14.031009,22.763702),(14.156169,22.660737),(14.201644,22.62322),(14.216217,22.616295)] +Norfolk Island [(167.984141,-29.017836),(167.996349,-29.025649),(167.99464,-29.042576),(167.985037,-29.059259),(167.973481,-29.066339),(167.970063,-29.068943),(167.967947,-29.072035),(167.966482,-29.075779),(167.966645,-29.080011),(167.960704,-29.065606),(167.95045,-29.056573),(167.939708,-29.055759),(167.932628,-29.066339),(167.926443,-29.066339),(167.924327,-29.055597),(167.920177,-29.045505),(167.918305,-29.036391),(167.922374,-29.028741),(167.929942,-29.019464),(167.930512,-29.01214),(167.924571,-29.008722),(167.91212,-29.011651),(167.926524,-28.997491),(167.945567,-29.001235),(167.965831,-29.011814),(167.984141,-29.017836)] +Niue [(-169.851145,-18.965102),(-169.825307,-18.96795),(-169.822621,-18.972589),(-169.79426,-19.047133),(-169.782908,-19.068943),(-169.796864,-19.073907),(-169.805979,-19.081964),(-169.823842,-19.102309),(-169.865427,-19.129653),(-169.872996,-19.125909),(-169.880971,-19.129083),(-169.898915,-19.142755),(-169.902048,-19.132989),(-169.909983,-19.128595),(-169.921091,-19.128025),(-169.933705,-19.129653),(-169.930531,-19.126397),(-169.927968,-19.122817),(-169.924794,-19.119317),(-169.919423,-19.115981),(-169.924062,-19.099379),(-169.926259,-19.094903),(-169.950429,-19.087335),(-169.947703,-19.069431),(-169.926259,-19.03753),(-169.927968,-19.031834),(-169.931589,-19.026544),(-169.934397,-19.020929),(-169.933705,-19.013604),(-169.930247,-19.008396),(-169.926381,-19.00742),(-169.921824,-19.007013),(-169.916005,-19.003106),(-169.895823,-18.965102),(-169.863718,-18.964044),(-169.851145,-18.965102)] +Nepal [(81.779018,30.358045),(81.801497,30.3613),(81.822788,30.368173),(81.844389,30.371171),(81.887177,30.354996),(81.92149,30.357373),(81.941231,30.353962),(81.950119,30.348381),(81.962108,30.333653),(81.969032,30.328279),(81.978851,30.326832),(81.988463,30.329778),(81.998178,30.334067),(82.007635,30.336806),(82.049854,30.339235),(82.073212,30.337219),(82.088767,30.330088),(82.093211,30.31474),(82.0821,30.257327),(82.084994,30.230817),(82.095898,30.213454),(82.114243,30.202189),(82.140391,30.194024),(82.155688,30.181363),(82.150985,30.162243),(82.127576,30.124364),(82.128713,30.110773),(82.135224,30.089741),(82.144526,30.069432),(82.153827,30.058166),(82.17424,30.055479),(82.192171,30.061474),(82.210671,30.064419),(82.255733,30.039666),(82.27599,30.036927),(82.296506,30.036824),(82.318882,30.031811),(82.32715,30.025714),(82.339087,30.009229),(82.347304,30.003441),(82.363737,30.001167),(82.379137,30.003234),(82.394433,30.003131),(82.409781,29.994604),(82.422855,29.97967),(82.438926,29.965769),(82.457065,29.95409),(82.475823,29.945512),(82.524244,29.932386),(82.541814,29.923239),(82.618502,29.839833),(82.635865,29.829033),(82.646407,29.829343),(82.666974,29.835028),(82.67731,29.834407),(82.688988,29.827741),(82.689195,29.819576),(82.684648,29.809706),(82.681754,29.797717),(82.690952,29.780741),(82.751517,29.739323),(82.77012,29.714156),(82.781076,29.705113),(82.793065,29.699506),(82.805157,29.695966),(82.815544,29.690127),(82.822365,29.677957),(82.836576,29.659793),(82.857454,29.666201),(82.880088,29.681109),(82.899725,29.688422),(82.90913,29.684623),(82.923703,29.669663),(82.931919,29.664185),(82.9421,29.662945),(82.964321,29.665891),(82.975896,29.66403),(83.032895,29.620467),(83.040905,29.610287),(83.054496,29.586051),(83.064935,29.57879),(83.079559,29.579643),(83.085553,29.590391),(83.088447,29.604421),(83.093357,29.615144),(83.100281,29.617676),(83.126688,29.623413),(83.150046,29.625635),(83.162086,29.62517),(83.173558,29.621268),(83.187253,29.612095),(83.19087,29.606902),(83.194487,29.593647),(83.197175,29.589099),(83.204926,29.584914),(83.221876,29.579824),(83.229317,29.575948),(83.252572,29.5552),(83.26084,29.542048),(83.26332,29.527088),(83.25991,29.518768),(83.254019,29.51329),(83.248748,29.506572),(83.247197,29.494738),(83.26394,29.473008),(83.327968,29.485023),(83.355201,29.460735),(83.357785,29.442752),(83.355201,29.427972),(83.35701,29.415363),(83.38724,29.393504),(83.389411,29.382445),(83.388274,29.370224),(83.393132,29.356245),(83.405017,29.346479),(83.417781,29.340898),(83.428168,29.333456),(83.437212,29.305241),(83.448219,29.296766),(83.475814,29.286921),(83.493384,29.276147),(83.502996,29.261032),(83.512504,29.223489),(83.514571,29.20181),(83.517052,29.191708),(83.523718,29.183594),(83.535965,29.179228),(83.56139,29.176231),(83.572035,29.168402),(83.583818,29.162149),(83.624435,29.155457),(83.639266,29.154759),(83.654992,29.160414),(83.65601,29.160779),(83.663399,29.174809),(83.66774,29.192328),(83.675078,29.208761),(83.69549,29.226176),(83.719727,29.233591),(83.745358,29.23447),(83.770628,29.232248),(83.79321,29.234754),(83.837859,29.254004),(83.86163,29.260205),(83.868865,29.263435),(83.877391,29.276767),(83.883438,29.282012),(83.914392,29.289402),(83.93315,29.291779),(83.945553,29.291831),(83.957955,29.28904),(83.967257,29.284699),(83.973251,29.277025),(83.975835,29.263745),(83.988237,29.269532),(84.000898,29.27253),(84.012525,29.270204),(84.021517,29.259766),(84.035211,29.247622),(84.05304,29.25036),(84.072057,29.256975),(84.08973,29.256613),(84.099135,29.247001),(84.105336,29.219923),(84.112364,29.209097),(84.126007,29.206255),(84.141975,29.20827),(84.155462,29.206642),(84.161663,29.192534),(84.155204,29.175946),(84.141716,29.160263),(84.13226,29.143804),(84.137996,29.124657),(84.160113,29.105486),(84.166211,29.098458),(84.169725,29.088923),(84.175461,29.057401),(84.198199,29.045308),(84.220575,29.0389),(84.231427,29.025981),(84.206725,28.940664),(84.225291,28.914115),(84.235147,28.90002),(84.285997,28.873743),(84.354003,28.861289),(84.366302,28.856741),(84.376586,28.848835),(84.393071,28.82434),(84.41431,28.808269),(84.422733,28.799173),(84.437822,28.753336),(84.450845,28.73388),(84.475753,28.727292),(84.498594,28.72786),(84.515647,28.7214),(84.531977,28.712693),(84.551821,28.706388),(84.607218,28.698198),(84.616209,28.69365),(84.625821,28.67608),(84.632642,28.668794),(84.65228,28.662386),(84.671141,28.658949),(84.682975,28.650759),(84.677756,28.604405),(84.69083,28.596137),(84.736615,28.594173),(84.755632,28.585414),(84.781781,28.558904),(84.799144,28.546631),(84.81196,28.54198),(84.823949,28.540533),(84.879294,28.543634),(84.891438,28.541773),(84.907871,28.537019),(84.918723,28.535675),(84.92849,28.538466),(84.936448,28.54477),(84.948954,28.568283),(84.954948,28.574303),(84.984766,28.588592),(84.994067,28.590814),(85.002491,28.594431),(85.009157,28.602545),(85.018769,28.619856),(85.02528,28.628409),(85.032101,28.634067),(85.054942,28.638692),(85.075044,28.631664),(85.11189,28.608823),(85.160982,28.595),(85.16801,28.583192),(85.156952,28.533143),(85.153748,28.524901),(85.14765,28.515832),(85.140363,28.510922),(85.123155,28.504592),(85.117212,28.497331),(85.115662,28.491492),(85.115559,28.472733),(85.109461,28.459298),(85.083674,28.445526),(85.077577,28.435681),(85.08569,28.381008),(85.08569,28.361526),(85.081867,28.331702),(85.080212,28.318789),(85.087395,28.304113),(85.109409,28.292254),(85.134162,28.291969),(85.154574,28.300858),(85.173591,28.30432),(85.205734,28.278275),(85.223924,28.271686),(85.243406,28.267914),(85.259581,28.266932),(85.27312,28.269826),(85.301025,28.281066),(85.312601,28.282771),(85.325727,28.277397),(85.334822,28.268689),(85.345364,28.261248),(85.362572,28.259672),(85.377817,28.265976),(85.401381,28.288791),(85.41523,28.296439),(85.43156,28.297059),(85.44665,28.29215),(85.475692,28.279102),(85.497551,28.282616),(85.52065,28.282926),(85.543698,28.280394),(85.565299,28.275381),(85.585504,28.263186),(85.59894,28.250835),(85.611807,28.251145),(85.639093,28.287887),(85.646947,28.2937),(85.668135,28.300548),(85.675059,28.306387),(85.676196,28.31512),(85.67599,28.324732),(85.679142,28.332897),(85.692939,28.335222),(85.698004,28.313441),(85.699761,28.269102),(85.715574,28.243368),(85.734487,28.221534),(85.756605,28.203241),(85.782753,28.1881),(85.826885,28.170478),(85.848279,28.158928),(85.863368,28.143348),(85.867037,28.132935),(85.87174,28.110921),(85.889103,28.090276),(85.891067,28.080897),(85.889827,28.071259),(85.890447,28.059193),(85.898302,28.036016),(85.908947,28.022425),(85.943984,27.994726),(85.956593,27.976226),(85.956283,27.956873),(85.951838,27.936797),(85.951218,27.91623),(85.96269,27.891374),(85.98026,27.885172),(86.026459,27.889927),(86.051419,27.88755),(86.0546,27.888013),(86.061703,27.889048),(86.075655,27.894784),(86.107178,27.922845),(86.112862,27.926798),(86.112242,27.937262),(86.107178,27.944239),(86.100563,27.950233),(86.095602,27.957855),(86.095085,27.968888),(86.098031,27.977518),(86.098134,27.985631),(86.089401,27.994726),(86.089401,27.994881),(86.089298,27.994933),(86.089298,27.994881),(86.079169,28.001134),(86.077619,28.006948),(86.079531,28.01333),(86.079531,28.02165),(86.083923,28.038548),(86.084699,28.043871),(86.081546,28.0517),(86.070177,28.066712),(86.068731,28.076763),(86.15596,28.156525),(86.176011,28.153011),(86.186036,28.133529),(86.187173,28.108699),(86.180765,28.088752),(86.172238,28.071828),(86.17446,28.062448),(86.18185,28.054878),(86.189137,28.043612),(86.19601,28.01457),(86.203038,28.002581),(86.217765,27.994985),(86.21792,27.994933),(86.218385,27.994726),(86.238539,27.989559),(86.259003,27.987647),(86.278072,27.983694),(86.29466,27.972376),(86.318224,27.945789),(86.327733,27.939691),(86.337551,27.938037),(86.345613,27.940931),(86.353674,27.944807),(86.362976,27.946099),(86.371968,27.941965),(86.405713,27.917005),(86.425298,27.909925),(86.438837,27.910856),(86.475476,27.927599),(86.496921,27.937882),(86.510461,27.952429),(86.516765,27.971369),(86.516764,27.971432),(86.516455,27.994726),(86.516197,28.012245),(86.522295,28.023717),(86.530925,28.03369),(86.538366,28.047178),(86.540743,28.062164),(86.54126,28.07821),(86.544154,28.093015),(86.553559,28.104151),(86.569527,28.106606),(86.583118,28.098028),(86.596864,28.086504),(86.612315,28.080277),(86.627146,28.083481),(86.64947,28.10118),(86.661976,28.106838),(86.680063,28.105727),(86.699648,28.098751),(86.717683,28.088261),(86.731739,28.076918),(86.735977,28.064851),(86.732204,28.034957),(86.739801,28.021495),(86.76998,28.01209),(86.840466,28.014777),(86.868165,27.994881),(86.868165,27.994726),(86.876898,27.970645),(86.893073,27.954186),(86.914725,27.945117),(86.940357,27.943102),(86.970226,27.947443),(86.982093,27.950674),(86.988726,27.952481),(87.005676,27.951499),(87.030532,27.938089),(87.062003,27.908427),(87.116522,27.844581),(87.155796,27.825796),(87.181996,27.824504),(87.232897,27.829724),(87.290516,27.816081),(87.313926,27.828587),(87.335837,27.846363),(87.363845,27.855252),(87.385343,27.849412),(87.380692,27.835821),(87.369116,27.819078),(87.369116,27.803937),(87.38679,27.804402),(87.47557,27.826701),(87.514534,27.835201),(87.531587,27.836803),(87.551327,27.831894),(87.555978,27.827088),(87.559802,27.819078),(87.565073,27.810862),(87.573342,27.805022),(87.589981,27.804609),(87.621091,27.819543),(87.636077,27.823652),(87.659951,27.819879),(87.678529,27.813351),(87.700466,27.805642),(87.726821,27.807761),(87.756379,27.82037),(87.779841,27.839439),(87.798651,27.863468),(87.814154,27.89096),(87.825884,27.906566),(87.836685,27.908323),(87.856115,27.898608),(87.93456,27.895301),(87.945205,27.892304),(87.966392,27.882744),(87.978433,27.880522),(87.991817,27.88264),(88.018121,27.892149),(88.029954,27.893337),(88.052795,27.886516),(88.095739,27.865329),(88.118218,27.860885),(88.143023,27.855717),(88.156407,27.851273),(88.164623,27.845356),(88.166587,27.833599),(88.154598,27.815151),(88.159662,27.77412),(88.149327,27.748772),(88.134858,27.723167),(88.11088,27.639503),(88.048765,27.545348),(88.02334,27.494912),(88.0221,27.484241),(88.02334,27.474655),(88.028094,27.455121),(88.030781,27.450729),(88.039773,27.442357),(88.041633,27.438068),(88.039308,27.42949),(88.034812,27.423805),(88.029593,27.418741),(88.02582,27.412075),(88.017242,27.389234),(88.014762,27.378072),(88.015795,27.364222),(88.020136,27.35337),(88.032538,27.333888),(88.035122,27.322571),(88.029024,27.298076),(88.004663,27.249163),(87.989337,27.218391),(87.985461,27.14837),(87.970837,27.119224),(87.969183,27.110801),(87.970733,27.10274),(87.975488,27.095143),(87.9913,27.081501),(88.009491,27.045637),(88.027371,27.035353),(88.042822,27.028946),(88.055948,27.018042),(88.076877,26.99179),(88.096824,26.959337),(88.11181,26.924301),(88.12044,26.90885),(88.142816,26.878412),(88.151394,26.862806),(88.155321,26.845598),(88.159042,26.802551),(88.167827,26.762915),(88.169067,26.744002),(88.167517,26.725037),(88.163383,26.705141),(88.14664,26.661216),(88.101681,26.581944),(88.087136,26.5391),(88.079822,26.517556),(88.07915,26.507375),(88.082251,26.494921),(88.082251,26.49487),(88.074189,26.453942),(88.044321,26.405676),(88.006648,26.369864),(87.975488,26.366557),(87.961225,26.378959),(87.928979,26.396426),(87.914768,26.40826),(87.908515,26.41782),(87.902004,26.435287),(87.897301,26.443452),(87.894769,26.442935),(87.870688,26.460712),(87.869809,26.464639),(87.852084,26.46066),(87.821595,26.437509),(87.804439,26.437354),(87.785938,26.445984),(87.768988,26.451461),(87.756173,26.446914),(87.749455,26.425727),(87.74222,26.410482),(87.727544,26.403764),(87.710904,26.405676),(87.697572,26.41627),(87.68119,26.424228),(87.659641,26.41751),(87.648745,26.409993),(87.623984,26.392912),(87.586984,26.378029),(87.552051,26.386711),(87.480324,26.423401),(87.449628,26.428621),(87.416452,26.426967),(87.384206,26.418647),(87.356404,26.403712),(87.344932,26.389346),(87.326225,26.353328),(87.314029,26.343768),(87.30049,26.34599),(87.258425,26.36294),(87.2453,26.370226),(87.236308,26.3833),(87.229435,26.398752),(87.2191,26.408105),(87.188455,26.399578),(87.135022,26.394204),(87.10629,26.404746),(87.083294,26.432083),(87.066706,26.465621),(87.056681,26.49487),(87.056474,26.49487),(87.056474,26.494921),(87.045002,26.544272),(87.044433,26.561171),(87.041333,26.580187),(87.029912,26.579774),(87.015443,26.568974),(86.985212,26.540655),(86.972448,26.531973),(86.935153,26.520289),(86.907129,26.51151),(86.875968,26.494921),(86.865684,26.472442),(86.846357,26.45265),(86.821863,26.438129),(86.796438,26.431514),(86.78724,26.433065),(86.751893,26.445519),(86.738199,26.44371),(86.730706,26.433788),(86.724091,26.421954),(86.713601,26.414565),(86.695204,26.418234),(86.625337,26.456319),(86.5579,26.484018),(86.537953,26.49487),(86.537746,26.49487),(86.52431,26.509081),(86.510616,26.520139),(86.494906,26.527839),(86.475476,26.531973),(86.444832,26.543084),(86.383647,26.572849),(86.353674,26.582616),(86.344838,26.582616),(86.323185,26.580084),(86.316002,26.580963),(86.309026,26.587991),(86.308613,26.60215),(86.301378,26.609023),(86.284428,26.61202),(86.263086,26.609075),(86.225155,26.597396),(86.202883,26.58458),(86.195855,26.582668),(86.185364,26.584425),(86.179266,26.588611),(86.17446,26.593313),(86.167794,26.596621),(86.152653,26.600651),(86.146355,26.601356),(86.144798,26.60153),(86.122061,26.60029),(86.115859,26.602563),(86.110692,26.606749),(86.041704,26.645455),(86.01137,26.654447),(85.975713,26.64437),(85.952148,26.642044),(85.934682,26.632897),(85.866366,26.579929),(85.844765,26.568509),(85.828538,26.566131),(85.821614,26.571713),(85.819753,26.579516),(85.819547,26.588301),(85.817635,26.596724),(85.809728,26.603028),(85.800065,26.600703),(85.789988,26.597034),(85.780996,26.599204),(85.727046,26.6376),(85.712887,26.653206),(85.702241,26.68845),(85.709631,26.76245),(85.701828,26.796608),(85.687772,26.811853),(85.609379,26.851024),(85.598578,26.854383),(85.519462,26.826426),(85.475692,26.805238),(85.439622,26.78772),(85.421535,26.782656),(85.40319,26.787617),(85.385878,26.788444),(85.369238,26.775008),(85.355352,26.759912),(85.353219,26.757593),(85.337044,26.746792),(85.302369,26.737336),(85.28728,26.736974),(85.194934,26.758885),(85.165685,26.786273),(85.16553,26.820793),(85.162016,26.851024),(85.122845,26.8657),(85.100211,26.863529),(85.043987,26.843737),(85.018562,26.845804),(85.016857,26.85924),(85.018045,26.874433),(85.000837,26.882236),(84.988176,26.883787),(84.975774,26.886887),(84.952726,26.897636),(84.944251,26.915723),(84.938567,26.9366),(84.924046,26.955668),(84.901567,26.967192),(84.851751,26.982127),(84.828289,26.994839),(84.828134,26.994943),(84.817489,27.0106),(84.801934,27.013753),(84.785501,27.008482),(84.771962,26.99918),(84.760697,26.999025),(84.640239,27.028377),(84.627268,27.03649),(84.62148,27.057988),(84.630369,27.080829),(84.644528,27.103721),(84.654398,27.125374),(84.659824,27.165113),(84.657654,27.203405),(84.648197,27.240716),(84.631919,27.277044),(84.606546,27.310479),(84.577039,27.329031),(84.289408,27.376108),(84.267703,27.388562),(84.248893,27.412436),(84.239023,27.431143),(84.225536,27.440393),(84.195253,27.436053),(84.185848,27.438636),(84.175099,27.462976),(84.165746,27.472174),(84.141716,27.480753),(84.130968,27.486411),(84.121563,27.494964),(84.11717,27.513283),(84.099548,27.516874),(84.079601,27.509536),(84.028907,27.453726),(84.007668,27.440807),(83.975835,27.439722),(83.935941,27.446078),(83.923022,27.449954),(83.922043,27.449696),(83.899871,27.443856),(83.853517,27.440962),(83.834087,27.434037),(83.842717,27.418069),(83.87119,27.38944),(83.873671,27.380087),(83.87765,27.369907),(83.877391,27.361742),(83.867521,27.358383),(83.861733,27.354507),(83.854602,27.34505),(83.85334,27.346194),(83.847988,27.351045),(83.801995,27.365928),(83.663399,27.43228),(83.590432,27.45662),(83.480981,27.469746),(83.387034,27.470469),(83.360989,27.462201),(83.355925,27.452486),(83.353857,27.44029),(83.355821,27.428663),(83.370962,27.410214),(83.369567,27.398174),(83.362746,27.385616),(83.341145,27.356936),(83.32435,27.341691),(83.304868,27.331925),(83.282441,27.330943),(83.259496,27.338126),(83.249419,27.348099),(83.243115,27.362155),(83.231591,27.381224),(83.21924,27.393781),(83.169631,27.431195),(83.132786,27.444217),(83.010468,27.443391),(82.947164,27.457317),(82.901275,27.480365),(82.876264,27.487548),(82.752137,27.494964),(82.72971,27.518166),(82.718857,27.556123),(82.709246,27.630924),(82.69705,27.669397),(82.679687,27.694409),(82.673891,27.696458),(82.652143,27.70415),(82.526156,27.675211),(82.440683,27.666426),(82.401926,27.677175),(82.347924,27.726009),(82.270409,27.760477),(82.151037,27.848275),(82.107422,27.863572),(82.090369,27.872331),(82.071662,27.89003),(82.051611,27.905171),(82.050212,27.905586),(82.02722,27.912406),(81.975905,27.916953),(81.946398,27.905352),(81.906091,27.863107),(81.883198,27.849051),(81.855654,27.850937),(81.827852,27.865639),(81.800154,27.884087),(81.750131,27.909667),(81.710392,27.94752),(81.688946,27.963204),(81.665433,27.9708),(81.615049,27.981239),(81.59536,27.994726),(81.59536,27.994778),(81.595102,27.994881),(81.582183,28.013278),(81.561925,28.025991),(81.473455,28.066402),(81.458211,28.07728),(81.454025,28.086607),(81.45294,28.097046),(81.448237,28.111412),(81.435267,28.129783),(81.417335,28.147017),(81.396044,28.160634),(81.373203,28.167843),(81.357907,28.165982),(81.351447,28.15681),(81.347262,28.144433),(81.338115,28.132728),(81.323697,28.126243),(81.307057,28.123814),(81.296205,28.12831),(81.299409,28.142521),(81.283079,28.146087),(81.276775,28.153787),(81.280754,28.161977),(81.295947,28.167455),(81.282356,28.191588),(81.224323,28.250783),(81.210732,28.278637),(81.190372,28.338116),(81.169701,28.361319),(81.146344,28.372249),(81.047066,28.389088),(81.000409,28.397002),(80.993175,28.407828),(80.991314,28.420256),(80.9878,28.430979),(80.976018,28.436922),(80.960515,28.432271),(80.941188,28.432684),(80.921344,28.436198),(80.905273,28.440849),(80.88667,28.452786),(80.881864,28.466842),(80.880365,28.48188),(80.872252,28.496866),(80.857989,28.502447),(80.81701,28.502551),(80.798406,28.505703),(80.781663,28.514746),(80.743526,28.549964),(80.727093,28.559679),(80.695777,28.567508),(80.67862,28.574717),(80.668182,28.586344),(80.648338,28.619753),(80.635625,28.627866),(80.598522,28.633783),(80.581365,28.638951),(80.563589,28.647038),(80.556871,28.655022),(80.557387,28.66435),(80.559041,28.673031),(80.555837,28.678948),(80.534444,28.679555),(80.517596,28.680033),(80.497546,28.670137),(80.487624,28.656469),(80.484937,28.639287),(80.493412,28.575647),(80.488451,28.562444),(80.468814,28.571849),(80.426543,28.616807),(80.408352,28.626342),(80.388302,28.627246),(80.369078,28.622647),(80.349751,28.620218),(80.329701,28.627479),(80.318332,28.640113),(80.291047,28.689671),(80.283399,28.695356),(80.265209,28.699283),(80.257044,28.702745),(80.249396,28.710213),(80.238957,28.726258),(80.233273,28.732718),(80.216426,28.741942),(80.181183,28.74729),(80.162063,28.753285),(80.147593,28.76331),(80.11421,28.802584),(80.081861,28.819353),(80.073054,28.820925),(80.054782,28.824185),(80.036386,28.837026),(80.030288,28.87767),(80.031115,28.897798),(80.033905,28.915936),(80.04052,28.932809),(80.052922,28.949113),(80.068425,28.959939),(80.085168,28.967484),(80.099431,28.977276),(80.107906,28.994588),(80.107906,28.994769),(80.104702,29.027609),(80.113073,29.072206),(80.132607,29.110214),(80.16351,29.123366),(80.180563,29.121324),(80.20144,29.121169),(80.220664,29.126079),(80.233066,29.139308),(80.230482,29.154733),(80.213739,29.196565),(80.218803,29.211086),(80.236063,29.213076),(80.248672,29.204394),(80.258181,29.202456),(80.278748,29.268085),(80.282779,29.291314),(80.280092,29.31015),(80.272754,29.315705),(80.263555,29.315318),(80.254977,29.316635),(80.249499,29.326997),(80.242161,29.367408),(80.220974,29.400119),(80.213739,29.416888),(80.217666,29.434639),(80.228312,29.441718),(80.257457,29.450064),(80.263452,29.459237),(80.266242,29.47213),(80.273064,29.478667),(80.282055,29.4843),(80.29115,29.494609),(80.29146,29.494738),(80.311511,29.508122),(80.320089,29.515822),(80.327221,29.52484),(80.327634,29.52993),(80.32505,29.535511),(80.323603,29.54166),(80.327221,29.548585),(80.332698,29.552461),(80.345101,29.558352),(80.350785,29.562073),(80.373316,29.58419),(80.385201,29.604835),(80.386752,29.626823),(80.377553,29.652946),(80.363911,29.679714),(80.354402,29.70488),(80.354299,29.730279),(80.368975,29.757926),(80.395227,29.776582),(80.454861,29.790586),(80.476152,29.80614),(80.527312,29.862416),(80.549533,29.89368),(80.562865,29.929699),(80.57134,29.946855),(80.586223,29.954142),(80.622293,29.958173),(80.641413,29.963444),(80.654126,29.970575),(80.680171,29.992072),(80.715827,30.013311),(80.725749,30.022768),(80.755721,30.064574),(80.769674,30.077287),(80.829825,30.117129),(80.849669,30.143381),(80.83644,30.170046),(80.850393,30.181931),(80.867911,30.200173),(80.883879,30.210405),(80.893646,30.198106),(80.903309,30.180433),(80.920828,30.17666),(80.988162,30.196556),(80.996017,30.196969),(81.006507,30.188908),(81.019426,30.172268),(81.030898,30.152734),(81.043663,30.12023),(81.066607,30.087157),(81.074203,30.071912),(81.084454,30.027876),(81.084849,30.026179),(81.097768,30.016929),(81.124588,30.022768),(81.148101,30.023233),(81.194506,30.004475),(81.21683,30.008195),(81.227269,30.022458),(81.225719,30.050467),(81.239516,30.058787),(81.257086,30.063541),(81.266801,30.069949),(81.267903,30.072053),(81.272021,30.079922),(81.275948,30.095373),(81.274501,30.102195),(81.266336,30.117749),(81.266956,30.125087),(81.277705,30.131857),(81.29326,30.132839),(81.309538,30.132064),(81.322405,30.133769),(81.33827,30.143536),(81.350052,30.15723),(81.357287,30.17356),(81.361834,30.204772),(81.374392,30.223118),(81.377854,30.232626),(81.376924,30.241204),(81.370516,30.257276),(81.369017,30.266061),(81.368036,30.301046),(81.37155,30.31691),(81.382143,30.331276),(81.387259,30.345126),(81.384882,30.360939),(81.387518,30.373909),(81.407413,30.37918),(81.42612,30.372514),(81.46281,30.341353),(81.483067,30.331896),(81.509371,30.328382),(81.520688,30.331948),(81.531953,30.370344),(81.536811,30.37856),(81.544252,30.382643),(81.563269,30.385588),(81.576705,30.390963),(81.581976,30.399438),(81.585077,30.408119),(81.591588,30.414269),(81.614015,30.416904),(81.635719,30.410961),(81.757366,30.362902),(81.779018,30.358045)] +Nauru [(166.938813,-0.490411),(166.955577,-0.497979),(166.958263,-0.517673),(166.951345,-0.539158),(166.938813,-0.551853),(166.916352,-0.54754),(166.906993,-0.524835),(166.913422,-0.500177),(166.938813,-0.490411)] +Poland [(19.002126,54.344916),(19.377208,54.377631),(19.459972,54.401028),(19.499278,54.406399),(19.531016,54.414944),(19.59254,54.452379),(19.609548,54.456732),(19.63077,54.446652),(19.680276,54.436678),(19.758256,54.434256),(19.964703,54.427842),(20.35207,54.415749),(20.640838,54.406784),(20.929606,54.397818),(21.287413,54.386759),(21.720772,54.373271),(21.998946,54.364667),(22.27712,54.356063),(22.510388,54.348777),(22.698387,54.342937),(22.76722,54.35627),(22.78603,54.36521),(22.811344,54.392633),(22.812695,54.394097),(22.837603,54.400918),(22.858894,54.399213),(22.918838,54.381126),(22.92969,54.380299),(22.952428,54.38309),(22.96266,54.381695),(22.973305,54.37539),(22.97899,54.367587),(22.983434,54.359784),(22.989738,54.353376),(23.001004,54.34888),(23.035317,54.346503),(23.041622,54.340974),(23.038004,54.331465),(23.032216,54.320148),(23.032113,54.309554),(23.050096,54.294827),(23.073041,54.294878),(23.096915,54.300821),(23.117069,54.303457),(23.135259,54.298289),(23.197271,54.267851),(23.235408,54.254157),(23.316023,54.236277),(23.33599,54.226294),(23.354471,54.217054),(23.364082,54.208269),(23.382273,54.187856),(23.391471,54.180105),(23.401806,54.175971),(23.423304,54.172508),(23.432502,54.169305),(23.449039,54.154938),(23.462991,54.13494),(23.473947,54.112564),(23.481595,54.091221),(23.496167,54.044558),(23.496477,54.021975),(23.481595,54.006627),(23.469502,54.000684),(23.464128,53.996757),(23.45927,53.992313),(23.45865,53.981616),(23.462888,53.972521),(23.470949,53.965286),(23.481595,53.960118),(23.487486,53.955622),(23.49038,53.95061),(23.48976,53.945132),(23.485625,53.939293),(23.486866,53.909992),(23.497201,53.885549),(23.51043,53.862502),(23.520662,53.837335),(23.52986,53.78416),(23.540402,53.763593),(23.56469,53.742457),(23.56469,53.742405),(23.564794,53.742405),(23.567068,53.681014),(23.590942,53.611251),(23.675795,53.455705),(23.722924,53.397104),(23.742974,53.365478),(23.782972,53.270936),(23.800645,53.242462),(23.818628,53.227967),(23.828447,53.213833),(23.836198,53.199286),(23.848084,53.183809),(23.865964,53.172001),(23.883121,53.163991),(23.893663,53.151951),(23.891389,53.127714),(23.882397,53.113297),(23.870305,53.101256),(23.860693,53.087484),(23.859349,53.067976),(23.867928,53.051027),(23.89821,53.02754),(23.909682,53.012734),(23.911336,53.00506),(23.908959,52.993046),(23.909062,52.986664),(23.917537,52.95881),(23.91795,52.9508),(23.914953,52.944625),(23.903894,52.931137),(23.901104,52.923257),(23.902034,52.912534),(23.905445,52.906539),(23.909476,52.901501),(23.912059,52.893853),(23.920426,52.772625),(23.922498,52.742596),(23.908752,52.699859),(23.868961,52.670042),(23.736153,52.614903),(23.569031,52.585887),(23.480458,52.554416),(23.392298,52.509638),(23.270548,52.395123),(23.230447,52.365074),(23.21205,52.347504),(23.165645,52.289393),(23.168746,52.288928),(23.176099,52.285136),(23.183525,52.281306),(23.19448,52.271462),(23.197684,52.25831),(23.189726,52.240533),(23.212257,52.231671),(23.284191,52.219734),(23.29959,52.223428),(23.312716,52.215289),(23.374831,52.200949),(23.395812,52.19958),(23.395812,52.193379),(23.388474,52.184154),(23.391368,52.182501),(23.405734,52.185911),(23.418239,52.182501),(23.427231,52.17679),(23.43674,52.175679),(23.450485,52.185911),(23.454413,52.181467),(23.464335,52.176351),(23.470949,52.171623),(23.487693,52.181622),(23.491517,52.174103),(23.488726,52.16214),(23.484695,52.158626),(23.512497,52.124442),(23.531928,52.120644),(23.579366,52.121548),(23.598177,52.11452),(23.604791,52.106769),(23.609856,52.09863),(23.61585,52.0923),(23.625255,52.089716),(23.637451,52.084471),(23.641482,52.072921),(23.642515,52.061397),(23.650783,52.048943),(23.664943,52.011168),(23.676415,51.994088),(23.660705,51.98688),(23.647579,51.97409),(23.628666,51.946339),(23.622155,51.927943),(23.621431,51.895567),(23.61492,51.88425),(23.618847,51.883268),(23.620604,51.883217),(23.621328,51.882028),(23.621845,51.877429),(23.609856,51.873269),(23.605721,51.851591),(23.594559,51.843297),(23.610269,51.825184),(23.628666,51.809759),(23.617504,51.786504),(23.59828,51.77467),(23.577299,51.766686),(23.56035,51.754542),(23.556319,51.747359),(23.552288,51.736636),(23.546604,51.713589),(23.550221,51.708421),(23.556939,51.701393),(23.559213,51.695166),(23.550014,51.692427),(23.546087,51.689637),(23.549291,51.683203),(23.555389,51.676304),(23.56035,51.671963),(23.547534,51.662067),(23.541436,51.659742),(23.532444,51.658967),(23.532444,51.6515),(23.543813,51.6438),(23.545157,51.63411),(23.539886,51.607109),(23.5434,51.592743),(23.552081,51.578817),(23.573992,51.555304),(23.567171,51.55489),(23.56035,51.555304),(23.572752,51.539672),(23.588668,51.535899),(23.602311,51.530783),(23.606238,51.517399),(23.608099,51.511224),(23.614817,51.49722),(23.630526,51.490424),(23.648613,51.486212),(23.662772,51.480192),(23.647166,51.460193),(23.648716,51.453966),(23.689437,51.416423),(23.697602,51.404435),(23.686027,51.40105),(23.678895,51.394073),(23.677655,51.38379),(23.683856,51.370276),(23.665563,51.365806),(23.647786,51.353998),(23.63404,51.339296),(23.628666,51.325964),(23.635177,51.304699),(23.650887,51.299609),(23.670214,51.299376),(23.687267,51.2924),(23.742664,51.216255),(23.765195,51.199021),(23.816045,51.178789),(23.863587,51.148274),(23.874749,51.13613),(23.858213,51.13073),(23.854492,51.121532),(23.869271,51.10174),(23.895523,51.076108),(23.904205,51.062724),(23.915987,51.020866),(23.915987,51.014665),(23.911749,51.00681),(23.919087,51.002728),(23.9318,50.999472),(23.943995,50.994201),(23.955054,50.983556),(23.957845,50.975339),(23.958878,50.966348),(23.964356,50.953222),(23.979342,50.937512),(24.046935,50.898031),(24.130237,50.868937),(24.143156,50.856432),(24.130857,50.839069),(24.100472,50.834986),(24.067295,50.834831),(24.046935,50.829095),(24.020477,50.838552),(23.992881,50.836226),(23.969937,50.825168),(23.957638,50.808011),(23.959498,50.788891),(23.974278,50.776178),(23.997946,50.769202),(24.025851,50.767032),(24.025851,50.76083),(24.012828,50.743312),(24.026884,50.728016),(24.05417,50.717164),(24.081041,50.712978),(24.074943,50.690189),(24.082798,50.669156),(24.108165,50.630287),(24.10843,50.629882),(24.085279,50.604406),(24.095407,50.556864),(24.102539,50.543634),(24.107706,50.540844),(24.106466,50.538622),(24.09396,50.52715),(24.075047,50.514282),(24.010658,50.492785),(24.007867,50.480744),(24.009418,50.461469),(24.007764,50.448498),(24.003217,50.437698),(23.981306,50.40478),(23.928699,50.390827),(23.747522,50.38938),(23.713002,50.382404),(23.695742,50.376771),(23.682203,50.368245),(23.671247,50.353568),(23.658677,50.327005),(23.658018,50.325611),(23.644169,50.312692),(23.565311,50.257812),(23.536372,50.242826),(23.536268,50.242826),(23.536165,50.242774),(23.536062,50.242774),(23.481595,50.215954),(23.436429,50.193475),(23.207916,50.03395),(23.177841,50.003977),(23.141254,49.985477),(23.101463,49.957107),(22.993046,49.854426),(22.951188,49.826624),(22.945917,49.818356),(22.937752,49.798202),(22.933101,49.79107),(22.924419,49.785438),(22.906746,49.7812),(22.897961,49.777428),(22.888246,49.769728),(22.826648,49.697381),(22.809801,49.686322),(22.798846,49.683273),(22.777348,49.680483),(22.766186,49.67423),(22.758951,49.6656),(22.741692,49.633664),(22.665831,49.567363),(22.640922,49.528761),(22.660146,49.493001),(22.666864,49.478376),(22.673065,49.435847),(22.676786,49.424478),(22.679576,49.418948),(22.692599,49.405513),(22.7142,49.39063),(22.719781,49.382982),(22.724225,49.367065),(22.737764,49.275391),(22.73394,49.26087),(22.717094,49.230433),(22.702934,49.195034),(22.687121,49.173382),(22.681747,49.161238),(22.687845,49.155915),(22.692496,49.157931),(22.705725,49.168835),(22.721434,49.1616),(22.720194,49.161186),(22.71637,49.160566),(22.748823,49.14558),(22.778072,49.12031),(22.796469,49.11137),(22.841324,49.094886),(22.853416,49.084757),(22.853519,49.076282),(22.844424,49.056697),(22.843184,49.043106),(22.847525,49.033701),(22.863751,49.015356),(22.865014,49.013237),(22.866955,49.009981),(22.855276,48.994013),(22.835019,48.999749),(22.812902,49.012875),(22.795022,49.019025),(22.783963,49.02135),(22.765463,49.038403),(22.755334,49.044708),(22.744482,49.045535),(22.721951,49.041039),(22.685778,49.042796),(22.664384,49.041452),(22.642886,49.043157),(22.618288,49.054216),(22.580771,49.08145),(22.560721,49.085532),(22.539637,49.0722),(22.505013,49.083413),(22.426775,49.085635),(22.390085,49.093025),(22.339442,49.12646),(22.318151,49.131989),(22.262858,49.130594),(22.215936,49.139999),(22.208494,49.144185),(22.20622,49.150489),(22.209011,49.156949),(22.208908,49.163977),(22.197952,49.171987),(22.189684,49.17302),(22.165706,49.171108),(22.155681,49.171522),(22.144105,49.174881),(22.111549,49.188627),(22.040752,49.197463),(22.012434,49.211054),(22.005819,49.242887),(21.99321,49.278182),(21.964478,49.308568),(21.928408,49.330788),(21.874561,49.348358),(21.837871,49.370424),(21.819577,49.377246),(21.799423,49.374817),(21.782164,49.364482),(21.768004,49.353474),(21.757566,49.348927),(21.742166,49.357092),(21.708576,49.390888),(21.69173,49.402154),(21.681808,49.404066),(21.666305,49.401792),(21.65876,49.402464),(21.648632,49.407063),(21.630028,49.418897),(21.6199,49.423341),(21.601193,49.426493),(21.529569,49.421222),(21.514422,49.417213),(21.496186,49.412386),(21.48151,49.415228),(21.444406,49.409905),(21.42787,49.409802),(21.330408,49.427785),(21.274391,49.447267),(21.260542,49.449438),(21.242455,49.441273),(21.211242,49.411094),(21.194086,49.400603),(21.172588,49.398278),(21.157292,49.405151),(21.143029,49.415538),(21.124943,49.423651),(21.10944,49.424581),(21.068822,49.419207),(21.053526,49.414453),(21.033269,49.399673),(21.045464,49.390578),(21.068512,49.381431),(21.080708,49.366342),(21.072543,49.357195),(21.054043,49.354766),(21.032959,49.354611),(21.017249,49.352441),(20.996682,49.339367),(20.964022,49.308103),(20.942422,49.295855),(20.91896,49.290326),(20.900564,49.2926),(20.884337,49.300299),(20.868007,49.31141),(20.849301,49.320505),(20.833591,49.322055),(20.816538,49.321383),(20.79411,49.323657),(20.778297,49.331202),(20.689517,49.4005),(20.673911,49.402309),(20.636084,49.39833),(20.614483,49.400448),(20.605284,49.400035),(20.595053,49.396263),(20.579136,49.383395),(20.567664,49.376367),(20.543996,49.370838),(20.522085,49.374352),(20.437543,49.402515),(20.421936,49.40019),(20.422143,49.382982),(20.370467,49.38169),(20.329539,49.391767),(20.317653,49.391612),(20.307422,49.386599),(20.303701,49.380398),(20.301634,49.371199),(20.296466,49.356937),(20.289335,49.343087),(20.284374,49.338643),(20.207169,49.334199),(20.191976,49.328618),(20.170169,49.311617),(20.16035,49.305622),(20.138336,49.307327),(20.135856,49.308878),(20.130171,49.303917),(20.111051,49.275856),(20.105367,49.263971),(20.098442,49.25286),(20.08604,49.243042),(20.080355,49.208109),(20.07002,49.183097),(20.050486,49.173227),(20.01731,49.183872),(19.965737,49.215653),(19.937935,49.22511),(19.905896,49.222785),(19.887809,49.214),(19.868292,49.200788),(19.854219,49.191262),(19.831998,49.185888),(19.785903,49.188162),(19.760685,49.194208),(19.747766,49.205887),(19.747787,49.205956),(19.751797,49.219064),(19.789624,49.259475),(19.794068,49.261852),(19.800476,49.263041),(19.806263,49.265263),(19.808641,49.270895),(19.80678,49.275236),(19.806415,49.275488),(19.798822,49.280714),(19.798563,49.281081),(19.796962,49.28335),(19.79686,49.283399),(19.783216,49.290016),(19.779702,49.293375),(19.779713,49.293453),(19.780322,49.297612),(19.78797,49.305105),(19.78952,49.309188),(19.783629,49.357557),(19.778565,49.374197),(19.769263,49.39311),(19.769056,49.393213),(19.760065,49.397658),(19.726578,49.388873),(19.706321,49.387529),(19.684514,49.389079),(19.627044,49.401868),(19.627097,49.402165),(19.62922,49.413936),(19.6286,49.429594),(19.63015,49.43502),(19.634801,49.441324),(19.594804,49.441583),(19.573926,49.445252),(19.55677,49.453882),(19.551602,49.461013),(19.535479,49.492846),(19.517289,49.543282),(19.505197,49.563384),(19.481735,49.573513),(19.474191,49.578732),(19.457344,49.598059),(19.44889,49.600313),(19.443392,49.60178),(19.437604,49.600126),(19.43378,49.595165),(19.347067,49.532998),(19.339522,49.528761),(19.325363,49.52504),(19.315027,49.523955),(19.284228,49.524162),(19.265005,49.521475),(19.248675,49.516255),(19.234102,49.507212),(19.220459,49.493001),(19.20444,49.460548),(19.206197,49.459411),(19.209401,49.456414),(19.211364,49.45166),(19.208987,49.444993),(19.204543,49.442823),(19.192244,49.442616),(19.18935,49.442203),(19.182322,49.422721),(19.179738,49.410267),(19.172504,49.402257),(19.141705,49.394195),(19.11659,49.39094),(19.106255,49.391405),(19.096643,49.394609),(19.076799,49.404066),(19.067601,49.406133),(19.045793,49.402774),(19.007139,49.388098),(18.981818,49.386806),(18.962284,49.389183),(18.956703,49.400448),(18.960837,49.433315),(18.958253,49.448146),(18.953396,49.461685),(18.952362,49.475948),(18.961147,49.492794),(18.932208,49.504318),(18.833196,49.510261),(18.837434,49.526952),(18.83454,49.547623),(18.820174,49.590256),(18.81573,49.599299),(18.803947,49.616766),(18.799297,49.626378),(18.792579,49.660794),(18.788444,49.668597),(18.773458,49.675832),(18.757852,49.674075),(18.742246,49.669683),(18.727673,49.668907),(18.715064,49.673817),(18.695427,49.688854),(18.682404,49.695779),(18.668142,49.69857),(18.637343,49.700327),(18.62401,49.706373),(18.617706,49.713866),(18.60768,49.74296),(18.584116,49.774379),(18.566753,49.804765),(18.566339,49.831585),(18.593831,49.852204),(18.567269,49.861454),(18.562929,49.873701),(18.565409,49.889049),(18.559208,49.907187),(18.544428,49.912975),(18.505051,49.896697),(18.481797,49.896645),(18.407486,49.923155),(18.368832,49.932044),(18.328524,49.92884),(18.330695,49.92884),(18.332452,49.928271),(18.333795,49.927135),(18.334932,49.925429),(18.306923,49.909668),(18.292454,49.907808),(18.27261,49.918298),(18.267029,49.925067),(18.260105,49.94057),(18.255867,49.946048),(18.243982,49.951732),(18.22052,49.954885),(18.208738,49.958295),(18.177216,49.975814),(18.162023,49.98124),(18.098151,49.989043),(18.085128,49.998758),(18.091639,50.017207),(18.033245,50.041805),(18.019074,50.044087),(18.002446,50.046765),(18.00689,50.024131),(18.012161,50.022684),(18.020119,50.024286),(18.028698,50.024131),(18.035726,50.017207),(18.037483,50.007233),(18.032418,50.00284),(17.999862,49.996588),(17.959761,49.995812),(17.941571,49.992764),(17.912116,49.975814),(17.875735,49.968682),(17.839355,49.973643),(17.774553,50.015191),(17.763287,50.025216),(17.755433,50.037154),(17.749852,50.049504),(17.74303,50.060563),(17.731971,50.06909),(17.722566,50.075136),(17.719466,50.080872),(17.72267,50.08635),(17.731971,50.091466),(17.732385,50.092189),(17.732592,50.092964),(17.732385,50.093894),(17.731971,50.094876),(17.717915,50.096788),(17.690734,50.10547),(17.677608,50.107744),(17.666963,50.106142),(17.658488,50.102989),(17.648359,50.101801),(17.632753,50.106348),(17.584177,50.145881),(17.58211,50.153167),(17.589448,50.163244),(17.600403,50.16681),(17.648669,50.167998),(17.675334,50.174716),(17.717915,50.191098),(17.738173,50.202363),(17.747578,50.217504),(17.731971,50.236005),(17.721429,50.242722),(17.719156,50.252799),(17.721119,50.261946),(17.731971,50.280653),(17.734245,50.283805),(17.734969,50.286802),(17.734452,50.28949),(17.731971,50.291763),(17.713575,50.30768),(17.707994,50.311039),(17.691044,50.315069),(17.684533,50.312382),(17.681949,50.305561),(17.676368,50.297396),(17.646705,50.271093),(17.629549,50.262101),(17.606398,50.258225),(17.516998,50.268354),(17.469352,50.265563),(17.44,50.242722),(17.434832,50.2405),(17.429561,50.239777),(17.424187,50.240552),(17.419122,50.242722),(17.409821,50.261326),(17.388013,50.272643),(17.365896,50.271558),(17.355044,50.253264),(17.341711,50.259724),(17.334786,50.270008),(17.332823,50.282668),(17.334063,50.295691),(17.329515,50.298223),(17.325381,50.301117),(17.321867,50.304476),(17.319077,50.308248),(17.337474,50.313002),(17.316803,50.318635),(17.269881,50.317757),(17.24611,50.322149),(17.210866,50.336412),(17.201048,50.343233),(17.195053,50.351915),(17.188852,50.364834),(17.185442,50.375686),(17.187612,50.378476),(17.175933,50.38075),(17.145444,50.376719),(17.131698,50.376823),(17.118882,50.381164),(17.095628,50.393669),(17.084672,50.397958),(16.98194,50.416355),(16.958789,50.414598),(16.944005,50.420267),(16.915794,50.431083),(16.892953,50.432943),(16.865771,50.422401),(16.865874,50.408449),(16.897914,50.378218),(16.909283,50.359925),(16.916724,50.338634),(16.926543,50.319255),(16.945249,50.306905),(16.969641,50.297758),(16.987831,50.284942),(16.998373,50.26701),(16.99982,50.242722),(17.012842,50.231664),(17.014806,50.218486),(17.008398,50.20996),(16.996306,50.212905),(16.98566,50.223137),(16.98101,50.229183),(16.975015,50.231819),(16.960339,50.231974),(16.957548,50.229235),(16.957755,50.217143),(16.955275,50.213474),(16.946283,50.21306),(16.927783,50.217298),(16.918998,50.217091),(16.907009,50.211768),(16.890369,50.196937),(16.880964,50.191563),(16.869762,50.189729),(16.857606,50.187739),(16.837556,50.188617),(16.817712,50.186757),(16.795284,50.174406),(16.777301,50.15694),(16.766449,50.1434),(16.754253,50.13229),(16.732033,50.121955),(16.701233,50.094928),(16.660616,50.093016),(16.618654,50.10702),(16.584238,50.127432),(16.566668,50.142212),(16.557263,50.154718),(16.545894,50.188824),(16.535042,50.207738),(16.50476,50.227995),(16.492047,50.242722),(16.477578,50.255332),(16.452153,50.284994),(16.437787,50.297965),(16.415566,50.307938),(16.371021,50.318377),(16.353244,50.333518),(16.35066,50.342251),(16.351487,50.351346),(16.350764,50.360648),(16.343736,50.36995),(16.334227,50.371862),(16.288649,50.371862),(16.27697,50.369433),(16.269839,50.365454),(16.2625,50.36442),(16.249685,50.371035),(16.24493,50.376823),(16.232011,50.402609),(16.199559,50.406278),(16.190153,50.424158),(16.198008,50.440023),(16.217955,50.437129),(16.216095,50.440178),(16.211237,50.451289),(16.217335,50.45165),(16.226534,50.455371),(16.232011,50.456766),(16.247411,50.464983),(16.264981,50.471649),(16.279967,50.479866),(16.287719,50.492785),(16.303428,50.49604),(16.335468,50.490356),(16.352624,50.492785),(16.362029,50.501208),(16.382596,50.514179),(16.391175,50.521827),(16.388384,50.521258),(16.388281,50.52715),(16.389624,50.534849),(16.391175,50.539914),(16.395516,50.545701),(16.398306,50.548492),(16.398306,50.551799),(16.394482,50.559344),(16.425901,50.567561),(16.416806,50.586629),(16.331644,50.644042),(16.300948,50.6551),(16.268288,50.660423),(16.232011,50.660888),(16.219092,50.659131),(16.211754,50.649106),(16.204519,50.636342),(16.192324,50.626575),(16.175477,50.624095),(16.160284,50.628642),(16.128658,50.644042),(16.086491,50.64678),(16.024479,50.608592),(15.982001,50.603631),(15.979934,50.606628),(15.97921,50.60978),(15.980037,50.612984),(15.982001,50.61624),(15.996367,50.623681),(15.998641,50.635567),(15.993163,50.649364),(15.984481,50.662904),(15.971459,50.678613),(15.958023,50.686881),(15.941486,50.68838),(15.882265,50.674221),(15.854567,50.673704),(15.848159,50.675151),(15.797619,50.729773),(15.794415,50.735871),(15.792245,50.742692),(15.76744,50.744191),(15.684345,50.731426),(15.673803,50.733545),(15.666464,50.738093),(15.653235,50.75096),(15.641866,50.755766),(15.441775,50.800208),(15.400124,50.797986),(15.390822,50.790648),(15.381314,50.780002),(15.370255,50.772613),(15.368579,50.772949),(15.356096,50.775455),(15.349688,50.783723),(15.350515,50.793232),(15.353305,50.803257),(15.352995,50.812972),(15.341006,50.83173),(15.325813,50.839689),(15.307727,50.844753),(15.28778,50.854881),(15.277134,50.865734),(15.265352,50.88227),(15.25605,50.899892),(15.253053,50.914103),(15.260081,50.932499),(15.268763,50.94299),(15.269796,50.952653),(15.253776,50.969035),(15.227111,50.977406),(15.170164,50.977975),(15.160759,50.992651),(15.156108,51.007844),(15.144429,51.011564),(15.13151,51.005828),(15.122518,50.992754),(15.122518,50.992651),(15.119211,50.982471),(15.107946,50.981024),(15.09389,50.985416),(15.082107,50.992754),(15.073632,51.002624),(15.02299,51.009652),(15.003973,51.020685),(15.001182,51.012443),(14.996531,51.007844),(14.982062,51.001177),(14.976377,51.000402),(14.970693,50.998697),(14.965629,50.996062),(14.961081,50.992651),(14.960978,50.992651),(14.965215,50.981334),(14.981442,50.973221),(14.996635,50.959216),(14.997771,50.930174),(14.994671,50.92511),(14.984852,50.918082),(14.982062,50.914671),(14.981132,50.90909),(14.981752,50.905266),(14.982889,50.902424),(14.984129,50.867697),(14.982062,50.859067),(14.867857,50.86439),(14.831683,50.857982),(14.810393,50.858447),(14.810496,50.877051),(14.824655,50.89183),(14.860209,50.916842),(14.910645,50.992651),(14.955293,51.064042),(14.958291,51.075514),(14.958497,51.094738),(14.960254,51.104582),(14.965629,51.111507),(14.97338,51.116132),(14.979995,51.122798),(14.982062,51.13564),(14.983199,51.160909),(14.991364,51.18897),(15.004903,51.215609),(15.022059,51.23677),(15.017925,51.239561),(15.014308,51.242661),(15.019476,51.271678),(15.004903,51.291289),(14.982269,51.308006),(14.963768,51.328393),(14.960978,51.335291),(14.956637,51.353223),(14.956637,51.354153),(14.950648,51.396539),(14.946922,51.422909),(14.955397,51.435415),(14.945061,51.449186),(14.926561,51.46133),(14.910955,51.468978),(14.888321,51.475748),(14.841399,51.48443),(14.818558,51.492595),(14.818558,51.492698),(14.797474,51.502103),(14.732155,51.515823),(14.710037,51.530241),(14.70677,51.540828),(14.704559,51.547992),(14.712724,51.567422),(14.732155,51.58662),(14.743937,51.606644),(14.742283,51.632974),(14.732465,51.658347),(14.719546,51.675632),(14.67097,51.700773),(14.648439,51.717206),(14.638103,51.742631),(14.634176,51.769012),(14.620327,51.780536),(14.60224,51.788313),(14.585807,51.803893),(14.58281,51.825081),(14.595936,51.842418),(14.653296,51.878617),(14.671693,51.893888),(14.687093,51.911897),(14.695568,51.931457),(14.699082,51.992512),(14.704456,52.002227),(14.726057,52.026438),(14.730294,52.035895),(14.732155,52.045067),(14.735359,52.054033),(14.743007,52.062534),(14.761403,52.076667),(14.696394,52.106691),(14.686369,52.121032),(14.692467,52.146973),(14.703216,52.165163),(14.70704,52.179452),(14.69257,52.193379),(14.69257,52.19958),(14.712104,52.215444),(14.712414,52.235908),(14.696911,52.253478),(14.668903,52.260997),(14.640481,52.265054),(14.606581,52.275751),(14.584153,52.291228),(14.590148,52.309418),(14.569167,52.338512),(14.545396,52.382153),(14.539815,52.421866),(14.591595,52.449797),(14.615779,52.473284),(14.632316,52.496745),(14.627665,52.507416),(14.609061,52.517803),(14.616813,52.541032),(14.644821,52.576921),(14.613712,52.592527),(14.607965,52.596463),(14.549943,52.636194),(14.490102,52.650638),(14.46137,52.674564),(14.442353,52.679964),(14.431915,52.686088),(14.397705,52.727119),(14.382202,52.738152),(14.275955,52.78572),(14.24867,52.794582),(14.21601,52.817992),(14.19596,52.823366),(14.173739,52.824348),(14.152758,52.828327),(14.135395,52.836595),(14.123923,52.850651),(14.150485,52.86463),(14.16082,52.876748),(14.164954,52.895661),(14.16268,52.908167),(14.150485,52.943643),(14.14449,52.953694),(14.14449,52.959921),(14.192859,52.981651),(14.253734,53.000875),(14.312645,53.029219),(14.343341,53.048624),(14.356777,53.066684),(14.359568,53.075056),(14.38954,53.131668),(14.387473,53.146137),(14.381478,53.160296),(14.377861,53.176549),(14.380651,53.189855),(14.387783,53.202077),(14.397705,53.210991),(14.408247,53.214402),(14.415585,53.22099),(14.44163,53.251841),(14.428607,53.259076),(14.42468,53.264657),(14.409384,53.272434),(14.403286,53.27879),(14.400185,53.288609),(14.399565,53.306747),(14.398015,53.315222),(14.391261,53.334017),(14.370316,53.392298),(14.359878,53.444077),(14.338897,53.465213),(14.328458,53.48609),(14.30417,53.508518),(14.296936,53.529137),(14.296212,53.551306),(14.298899,53.587893),(14.297039,53.597763),(14.276058,53.636624),(14.260969,53.656209),(14.265103,53.671764),(14.263863,53.699876),(14.263901,53.699976),(14.263927,53.699978),(14.273692,53.700629),(14.291677,53.705268),(14.304861,53.712551),(14.306163,53.720689),(14.288585,53.727973),(14.29835,53.731431),(14.301606,53.734849),(14.29835,53.738267),(14.288585,53.741645),(14.2942,53.749091),(14.304047,53.743883),(14.318044,53.739732),(14.330414,53.734198),(14.342052,53.714911),(14.356212,53.708441),(14.383556,53.700629),(14.403575,53.687812),(14.414561,53.682359),(14.458669,53.677883),(14.51238,53.666449),(14.531016,53.657782),(14.546235,53.644761),(14.579112,53.607245),(14.590587,53.598375),(14.595876,53.601304),(14.597016,53.617336),(14.601573,53.626654),(14.610037,53.632758),(14.62379,53.639228),(14.623057,53.643012),(14.622813,53.646959),(14.62379,53.652818),(14.613048,53.65469),(14.587413,53.656073),(14.575938,53.659654),(14.544932,53.704047),(14.551443,53.726142),(14.575938,53.769517),(14.587413,53.763495),(14.597341,53.765204),(14.608246,53.769029),(14.62379,53.769517),(14.61671,53.794745),(14.620372,53.814846),(14.627289,53.832709),(14.630626,53.851508),(14.62379,53.851508),(14.621349,53.839545),(14.613536,53.83161),(14.58961,53.817328),(14.595876,53.810492),(14.587087,53.812649),(14.580089,53.815334),(14.574474,53.819078),(14.569102,53.824164),(14.574229,53.827094),(14.583263,53.834215),(14.58961,53.837836),(14.575857,53.854804),(14.552094,53.862779),(14.441173,53.869615),(14.425548,53.879828),(14.438162,53.899319),(14.434906,53.901313),(14.434093,53.901597),(14.433767,53.902411),(14.431895,53.906155),(14.422048,53.896145),(14.414236,53.894721),(14.405772,53.897406),(14.393809,53.899319),(14.385102,53.897284),(14.378266,53.89232),(14.371593,53.885891),(14.363048,53.879381),(14.392914,53.875963),(14.40919,53.871568),(14.417654,53.865139),(14.415701,53.853013),(14.405284,53.844184),(14.392589,53.840725),(14.383556,53.844672),(14.356212,53.834459),(14.342621,53.831855),(14.328298,53.831),(14.328298,53.824164),(14.342052,53.82099),(14.341319,53.818915),(14.328298,53.817328),(14.318858,53.818183),(14.303071,53.823065),(14.291352,53.824164),(14.274669,53.830797),(14.226573,53.871975),(14.203136,53.878323),(14.200857,53.87816),(14.200819,53.878157),(14.192756,53.893766),(14.175289,53.906478),(14.184798,53.908132),(14.193066,53.911491),(14.210076,53.938457),(14.226573,53.934027),(14.237478,53.928656),(14.268077,53.92182),(14.367035,53.916978),(14.406749,53.92182),(14.445567,53.934027),(14.517345,53.965237),(14.781912,54.034613),(15.010102,54.06981),(15.288341,54.138861),(15.468516,54.167141),(15.665782,54.198432),(15.859711,54.249986),(16.020844,54.261786),(16.131521,54.283515),(16.118907,54.276028),(16.069347,54.263007),(16.091075,54.253974),(16.17921,54.263007),(16.17921,54.269192),(16.172374,54.269192),(16.172374,54.276597),(16.220063,54.276597),(16.219574,54.28148),(16.218516,54.282375),(16.216645,54.28205),(16.213227,54.283515),(16.21518,54.299628),(16.192149,54.300279),(16.137706,54.290269),(16.17213,54.300238),(16.213552,54.316107),(16.275401,54.358588),(16.262869,54.343695),(16.240489,54.330024),(16.231781,54.322577),(16.240896,54.32453),(16.259044,54.326728),(16.274913,54.330471),(16.288829,54.340237),(16.323904,54.349921),(16.336762,54.358588),(16.32488,54.373114),(16.305024,54.373481),(16.296235,54.367255),(16.281586,54.358588),(16.323985,54.401313),(16.439789,54.488267),(16.439789,54.482123),(16.434418,54.472357),(16.444509,54.469875),(16.460623,54.473456),(16.473399,54.482123),(16.479747,54.495551),(16.473888,54.499661),(16.460948,54.496487),(16.446056,54.488267),(16.466563,54.512152),(16.501313,54.532416),(16.569591,54.557196),(16.778494,54.575141),(16.85963,54.59394),(16.902192,54.598131),(16.939952,54.606024),(17.035818,54.66706),(17.337413,54.74901),(17.715668,54.790432),(17.885427,54.824123),(18.152354,54.838324),(18.316905,54.838324),(18.339529,54.833482),(18.375824,54.815131),(18.389171,54.811103),(18.410167,54.808295),(18.75172,54.69009),(18.813975,54.643215),(18.824067,54.632229),(18.834321,54.616685),(18.835297,54.603095),(18.817638,54.598131),(18.813243,54.601549),(18.80836,54.608832),(18.802257,54.616034),(18.784028,54.623521),(18.771821,54.642279),(18.755382,54.654486),(18.707774,54.701239),(18.698497,54.703803),(18.663422,54.707994),(18.654552,54.71015),(18.64503,54.71955),(18.61671,54.725246),(18.556977,54.74901),(18.49822,54.765367),(18.48878,54.773179),(18.456309,54.787665),(18.447765,54.789984),(18.435557,54.786811),(18.42921,54.781684),(18.41505,54.753119),(18.413097,54.746527),(18.413097,54.73192),(18.418468,54.728217),(18.442393,54.721991),(18.447765,54.718248),(18.459809,54.706041),(18.474457,54.687567),(18.473888,54.679918),(18.470063,54.673285),(18.470388,54.666734),(18.481944,54.659613),(18.475922,54.640082),(18.487315,54.631781),(18.506358,54.634101),(18.52296,54.646552),(18.5171,54.62995),(18.525157,54.616685),(18.537608,54.605455),(18.562836,54.560004),(18.570649,54.55036),(18.566742,54.527411),(18.567556,54.48786),(18.574067,54.450385),(18.588064,54.433661),(18.60377,54.430609),(18.634288,54.416938),(18.649913,54.413804),(18.663341,54.412991),(18.680024,54.40998),(18.694347,54.404527),(18.70045,54.395819),(18.717296,54.382025),(18.885916,54.350165),(18.923188,54.348538),(18.954356,54.358588),(18.962901,54.353502),(18.97462,54.349758),(19.002126,54.344916)] +Paraguay [(-58.158797,-20.165125),(-58.158332,-20.181144),(-58.152337,-20.184658),(-58.144069,-20.183521),(-58.137041,-20.185588),(-58.12991,-20.192513),(-58.120505,-20.203882),(-58.118541,-20.214424),(-58.155283,-20.226413),(-58.162672,-20.243156),(-58.156316,-20.261656),(-58.137041,-20.274369),(-58.130943,-20.272818),(-58.126241,-20.267031),(-58.120039,-20.261346),(-58.109756,-20.260726),(-58.10309,-20.264447),(-58.09508,-20.272198),(-58.090325,-20.281707),(-58.099937,-20.309199),(-58.097715,-20.334623),(-58.090791,-20.359428),(-58.082987,-20.376171),(-58.067123,-20.393534),(-58.045625,-20.409347),(-58.023146,-20.420716),(-58.004181,-20.42516),(-57.989401,-20.433119),(-57.99214,-20.450895),(-58.007902,-20.479834),(-58.01002,-20.500091),(-58.008935,-20.525723),(-58.004749,-20.549804),(-57.993329,-20.573782),(-57.992554,-20.585047),(-57.993639,-20.606751),(-57.990952,-20.620601),(-57.977826,-20.640134),(-57.973123,-20.651193),(-57.973588,-20.661942),(-57.981082,-20.681165),(-57.980616,-20.692741),(-57.974415,-20.704006),(-57.96501,-20.711034),(-57.95638,-20.709898),(-57.947182,-20.675068),(-57.934004,-20.66742),(-57.918088,-20.669797),(-57.90429,-20.678995),(-57.900208,-20.685196),(-57.894472,-20.699976),(-57.890648,-20.706384),(-57.884343,-20.711965),(-57.868944,-20.722197),(-57.86021,-20.730258),(-57.857678,-20.73987),(-57.865275,-20.747415),(-57.877005,-20.752376),(-57.898761,-20.756613),(-57.906667,-20.762194),(-57.917933,-20.77408),(-57.933074,-20.784622),(-57.940412,-20.793613),(-57.933953,-20.799711),(-57.908011,-20.801985),(-57.887651,-20.805912),(-57.870701,-20.816454),(-57.859642,-20.831647),(-57.85711,-20.849734),(-57.867393,-20.860069),(-57.908683,-20.881567),(-57.917933,-20.894382),(-57.914832,-20.905648),(-57.908011,-20.910505),(-57.901138,-20.912366),(-57.898089,-20.914846),(-57.893025,-20.914846),(-57.869925,-20.932726),(-57.847033,-20.955981),(-57.840315,-20.955981),(-57.836026,-20.938514),(-57.817577,-20.953604),(-57.816027,-20.975411),(-57.82538,-20.998562),(-57.852459,-21.037836),(-57.851735,-21.051996),(-57.836026,-21.082485),(-57.829876,-21.12703),(-57.833959,-21.173849),(-57.84786,-21.216223),(-57.870701,-21.247643),(-57.899019,-21.267176),(-57.90429,-21.274928),(-57.90491,-21.287433),(-57.89995,-21.295081),(-57.893645,-21.300352),(-57.890648,-21.305934),(-57.882328,-21.316372),(-57.866308,-21.32092),(-57.855559,-21.330738),(-57.863311,-21.356886),(-57.929922,-21.453108),(-57.94527,-21.487214),(-57.949145,-21.508298),(-57.948112,-21.530519),(-57.939792,-21.548193),(-57.921602,-21.555427),(-57.912093,-21.564006),(-57.919328,-21.583953),(-57.932144,-21.60669),(-57.939017,-21.623744),(-57.934831,-21.640693),(-57.924341,-21.658677),(-57.911783,-21.673043),(-57.901138,-21.678934),(-57.895609,-21.688442),(-57.939017,-21.755312),(-57.938448,-21.774639),(-57.934779,-21.792932),(-57.93571,-21.812053),(-57.948939,-21.83386),(-57.955915,-21.85112),(-57.946665,-21.865486),(-57.932764,-21.881919),(-57.925374,-21.904967),(-57.929922,-21.917369),(-57.953228,-21.958193),(-57.962633,-21.966978),(-57.964855,-21.976694),(-57.986818,-22.035295),(-57.988368,-22.049041),(-57.988006,-22.06413),(-57.986249,-22.074465),(-57.973134,-22.081048),(-57.972865,-22.081183),(-57.961393,-22.090072),(-57.952453,-22.105988),(-57.939999,-22.11839),(-57.906254,-22.128932),(-57.895505,-22.128932),(-57.878194,-22.122111),(-57.871372,-22.121181),(-57.862846,-22.125832),(-57.848686,-22.140301),(-57.843881,-22.143712),(-57.831788,-22.141128),(-57.815769,-22.128312),(-57.805485,-22.128622),(-57.795305,-22.130999),(-57.787502,-22.129656),(-57.775409,-22.123971),(-57.777786,-22.122318),(-57.777425,-22.117047),(-57.775616,-22.111156),(-57.773652,-22.107745),(-57.769932,-22.107435),(-57.760268,-22.110742),(-57.756186,-22.110639),(-57.736342,-22.103714),(-57.723268,-22.104748),(-57.709935,-22.108469),(-57.689626,-22.109295),(-57.678516,-22.106401),(-57.670816,-22.102371),(-57.663685,-22.100614),(-57.654486,-22.104541),(-57.638932,-22.144539),(-57.627201,-22.165106),(-57.614075,-22.176991),(-57.596712,-22.181022),(-57.572734,-22.177715),(-57.564001,-22.174408),(-57.55997,-22.171617),(-57.554699,-22.170274),(-57.542297,-22.171514),(-57.534597,-22.174408),(-57.511188,-22.188774),(-57.472482,-22.180299),(-57.463955,-22.180402),(-57.443182,-22.187947),(-57.432278,-22.18867),(-57.41786,-22.193838),(-57.384994,-22.213268),(-57.378638,-22.213372),(-57.37502,-22.207274),(-57.366649,-22.209134),(-57.351249,-22.217196),(-57.339932,-22.216989),(-57.334816,-22.211718),(-57.333059,-22.205414),(-57.331767,-22.202416),(-57.316316,-22.203657),(-57.271667,-22.213785),(-57.252444,-22.210581),(-57.227484,-22.191254),(-57.21379,-22.188154),(-57.209449,-22.192081),(-57.2064,-22.207481),(-57.199527,-22.212855),(-57.189967,-22.213578),(-57.183611,-22.210891),(-57.177926,-22.207377),(-57.170382,-22.205724),(-57.154155,-22.207997),(-57.124183,-22.218539),(-57.115036,-22.22288),(-57.114623,-22.225051),(-57.113279,-22.229391),(-57.108473,-22.233525),(-57.090748,-22.236419),(-57.085064,-22.238073),(-57.079224,-22.23859),(-57.071628,-22.235696),(-57.059484,-22.232699),(-57.027651,-22.235076),(-57.011167,-22.233836),(-56.986465,-22.24138),(-56.975717,-22.24169),(-56.964554,-22.234869),(-56.965485,-22.250889),(-56.960524,-22.254816),(-56.9521,-22.253576),(-56.942592,-22.253989),(-56.924944,-22.262361),(-56.91479,-22.262878),(-56.90368,-22.236936),(-56.892001,-22.252232),(-56.881717,-22.277244),(-56.879547,-22.289956),(-56.85606,-22.29316),(-56.842856,-22.289026),(-56.84284,-22.28901),(-56.819654,-22.265462),(-56.813142,-22.25616),(-56.811902,-22.249649),(-56.808285,-22.247995),(-56.794565,-22.252542),(-56.786994,-22.251819),(-56.754361,-22.242621),(-56.74679,-22.243964),(-56.745601,-22.248408),(-56.743534,-22.250372),(-56.733199,-22.244067),(-56.728548,-22.237453),(-56.720538,-22.21947),(-56.715371,-22.215439),(-56.698602,-22.2235),(-56.664573,-22.259984),(-56.648811,-22.263498),(-56.644135,-22.255436),(-56.654703,-22.23735),(-56.648346,-22.231355),(-56.637184,-22.228254),(-56.629174,-22.22474),(-56.59574,-22.201486),(-56.584965,-22.190531),(-56.567912,-22.162315),(-56.565302,-22.159938),(-56.558016,-22.156424),(-56.554605,-22.152083),(-56.549076,-22.13627),(-56.545975,-22.130069),(-56.530679,-22.109089),(-56.521636,-22.09989),(-56.5113,-22.091415),(-56.493834,-22.086558),(-56.421797,-22.074465),(-56.407637,-22.075809),(-56.397302,-22.086248),(-56.370844,-22.147329),(-56.347331,-22.180402),(-56.316842,-22.207687),(-56.261083,-22.23859),(-56.231524,-22.265358),(-56.214264,-22.275383),(-56.196798,-22.279311),(-56.024715,-22.287372),(-56.011357,-22.283858),(-55.998567,-22.277244),(-55.985234,-22.283238),(-55.970868,-22.293884),(-55.955262,-22.301325),(-55.89294,-22.306803),(-55.874388,-22.317345),(-55.872011,-22.310213),(-55.86103,-22.289543),(-55.810775,-22.353105),(-55.770157,-22.381423),(-55.760235,-22.391965),(-55.751579,-22.416253),(-55.748298,-22.500899),(-55.74127,-22.537176),(-55.723932,-22.569629),(-55.697913,-22.595571),(-55.664685,-22.612727),(-55.644351,-22.619548),(-55.631199,-22.626783),(-55.62368,-22.638669),(-55.620476,-22.659339),(-55.62151,-22.667091),(-55.627013,-22.683627),(-55.627788,-22.692102),(-55.62567,-22.700784),(-55.619184,-22.716907),(-55.618332,-22.725692),(-55.628589,-22.758971),(-55.645927,-22.78791),(-55.659001,-22.818296),(-55.656572,-22.85571),(-55.6343,-22.932811),(-55.634351,-22.950071),(-55.639984,-22.983764),(-55.637814,-23.000714),(-55.611459,-23.029136),(-55.600684,-23.044535),(-55.595232,-23.064069),(-55.600142,-23.100553),(-55.599392,-23.117089),(-55.588669,-23.130112),(-55.560867,-23.145925),(-55.557147,-23.15471),(-55.535236,-23.229124),(-55.535649,-23.245867),(-55.559007,-23.291342),(-55.562159,-23.307879),(-55.555596,-23.330306),(-55.524875,-23.360485),(-55.513868,-23.379399),(-55.515547,-23.410198),(-55.542471,-23.465802),(-55.539913,-23.500528),(-55.533796,-23.530444),(-55.533066,-23.534015),(-55.533892,-23.569981),(-55.530533,-23.603468),(-55.51131,-23.629409),(-55.466971,-23.673231),(-55.445319,-23.735449),(-55.430178,-23.928564),(-55.420669,-23.954506),(-55.398035,-23.97683),(-55.367184,-23.989646),(-55.304346,-23.99409),(-55.27272,-24.000394),(-55.272668,-24.000498),(-55.272565,-24.000498),(-55.27241,-24.000601),(-55.272358,-24.000601),(-55.23683,-24.012693),(-55.200864,-24.019515),(-55.165439,-24.016827),(-55.131281,-24.000601),(-55.131204,-24.000601),(-55.131075,-24.000601),(-55.131075,-24.000394),(-55.105572,-23.988509),(-55.042294,-23.989026),(-55.011495,-23.980551),(-54.994571,-23.973109),(-54.961059,-23.971766),(-54.943644,-23.969182),(-54.926746,-23.95988),(-54.904887,-23.933008),(-54.891916,-23.920606),(-54.827424,-23.887016),(-54.696838,-23.845158),(-54.679784,-23.836683),(-54.654592,-23.811465),(-54.639218,-23.804437),(-54.612553,-23.811155),(-54.443158,-23.899935),(-54.422901,-23.913785),(-54.367607,-23.984685),(-54.273608,-24.036465),(-54.24575,-24.050393),(-54.245289,-24.050624),(-54.266218,-24.06592),(-54.301048,-24.089898),(-54.324767,-24.118217),(-54.334637,-24.148912),(-54.331847,-24.165036),(-54.318979,-24.196765),(-54.314122,-24.234179),(-54.306267,-24.246684),(-54.282651,-24.275313),(-54.274331,-24.298257),(-54.26105,-24.32947),(-54.262187,-24.358512),(-54.271696,-24.389415),(-54.284098,-24.411325),(-54.322907,-24.464345),(-54.334534,-24.496695),(-54.334792,-24.527287),(-54.320685,-24.595914),(-54.321305,-24.628366),(-54.358429,-24.731422),(-54.371121,-24.766653),(-54.39975,-24.80479),(-54.407294,-24.821223),(-54.453286,-25.002814),(-54.462278,-25.03723),(-54.46419,-25.055937),(-54.463312,-25.072784),(-54.455199,-25.092111),(-54.429722,-25.130558),(-54.426621,-25.149472),(-54.435665,-25.167042),(-54.46941,-25.195464),(-54.48145,-25.21324),(-54.503568,-25.278663),(-54.528476,-25.314319),(-54.547079,-25.336644),(-54.575656,-25.360311),(-54.597981,-25.397518),(-54.609814,-25.432762),(-54.61183,-25.444027),(-54.61245,-25.465525),(-54.608523,-25.487642),(-54.598497,-25.505832),(-54.591469,-25.524746),(-54.594156,-25.54862),(-54.599944,-25.572702),(-54.600203,-25.574945),(-54.602218,-25.592442),(-54.58625,-25.624688),(-54.583356,-25.644842),(-54.598497,-25.653834),(-54.633715,-25.652077),(-54.642887,-25.661585),(-54.643146,-25.68794),(-54.62493,-25.740237),(-54.622062,-25.759977),(-54.617152,-25.773516),(-54.594518,-25.798734),(-54.587904,-25.810827),(-54.589557,-25.832944),(-54.599221,-25.850721),(-54.610073,-25.866534),(-54.61524,-25.882863),(-54.607334,-25.927925),(-54.606404,-25.946632),(-54.61524,-25.961722),(-54.62369,-25.964306),(-54.647952,-25.965649),(-54.656194,-25.969163),(-54.662266,-25.979912),(-54.661594,-25.989937),(-54.658261,-26.000376),(-54.653326,-26.030761),(-54.642526,-26.062801),(-54.643146,-26.085228),(-54.663816,-26.149204),(-54.659941,-26.164397),(-54.641854,-26.184034),(-54.638288,-26.196953),(-54.644696,-26.208218),(-54.656194,-26.222998),(-54.664333,-26.236227),(-54.664974,-26.238863),(-54.666142,-26.243668),(-54.663661,-26.263305),(-54.663661,-26.308367),(-54.679061,-26.33989),(-54.68043,-26.345264),(-54.683402,-26.350845),(-54.693065,-26.411927),(-54.697664,-26.428153),(-54.706475,-26.441796),(-54.737171,-26.473215),(-54.765309,-26.494092),(-54.780347,-26.510422),(-54.789829,-26.528509),(-54.78877,-26.542565),(-54.783499,-26.556724),(-54.780347,-26.575224),(-54.781277,-26.598169),(-54.784946,-26.622767),(-54.793059,-26.644987),(-54.807012,-26.661214),(-54.817321,-26.665761),(-54.822825,-26.663281),(-54.827424,-26.658113),(-54.834969,-26.654393),(-54.879359,-26.654393),(-54.903337,-26.65987),(-54.919899,-26.674133),(-54.930725,-26.693977),(-54.943877,-26.739969),(-54.951137,-26.757539),(-54.961007,-26.772318),(-54.97527,-26.787821),(-54.991781,-26.794642),(-55.040744,-26.798466),(-55.060898,-26.805184),(-55.125778,-26.863579),(-55.132677,-26.880632),(-55.118879,-26.920009),(-55.122315,-26.941714),(-55.138361,-26.953702),(-55.161564,-26.95732),(-55.2012,-26.955459),(-55.216651,-26.951222),(-55.235177,-26.94223),(-55.256545,-26.934582),(-55.2806,-26.934272),(-55.329409,-26.958457),(-55.376228,-26.963831),(-55.39633,-26.969309),(-55.414003,-26.979851),(-55.43085,-26.996387),(-55.442761,-27.015508),(-55.448833,-27.035868),(-55.451313,-27.082067),(-55.461855,-27.097983),(-55.486402,-27.10005),(-55.513997,-27.097466),(-55.533841,-27.09943),(-55.545365,-27.115243),(-55.549524,-27.13581),(-55.555338,-27.153794),(-55.571745,-27.161545),(-55.598281,-27.16754),(-55.598979,-27.182629),(-55.574872,-27.223557),(-55.570583,-27.235339),(-55.568671,-27.245984),(-55.570712,-27.256423),(-55.58407,-27.276784),(-55.583243,-27.283501),(-55.580763,-27.291666),(-55.581641,-27.305516),(-55.591331,-27.328357),(-55.60748,-27.345513),(-55.628719,-27.356365),(-55.653627,-27.360086),(-55.681713,-27.379413),(-55.717499,-27.417343),(-55.754732,-27.443698),(-55.815167,-27.41414),(-55.842091,-27.407422),(-55.854157,-27.40122),(-55.862787,-27.391092),(-55.877851,-27.353575),(-55.892837,-27.334868),(-55.913094,-27.32784),(-55.936374,-27.328253),(-55.960662,-27.331561),(-55.966094,-27.331723),(-55.984847,-27.332284),(-56.006887,-27.328253),(-56.006894,-27.328251),(-56.073756,-27.304896),(-56.074246,-27.304811),(-56.098948,-27.300555),(-56.124554,-27.298901),(-56.149979,-27.31182),(-56.168892,-27.324739),(-56.205428,-27.362153),(-56.22801,-27.371248),(-56.256768,-27.378276),(-56.279842,-27.389645),(-56.285319,-27.411349),(-56.281469,-27.438634),(-56.285319,-27.460958),(-56.296998,-27.480905),(-56.31648,-27.500439),(-56.335988,-27.525657),(-56.349657,-27.556353),(-56.367537,-27.580641),(-56.399731,-27.586842),(-56.400299,-27.586636),(-56.431357,-27.57537),(-56.461484,-27.553873),(-56.487323,-27.527208),(-56.50621,-27.500129),(-56.54644,-27.455067),(-56.546933,-27.455003),(-56.613,-27.446386),(-56.638016,-27.452912),(-56.683125,-27.464679),(-56.734233,-27.500439),(-56.771155,-27.506744),(-56.771511,-27.506548),(-56.807458,-27.486797),(-56.869263,-27.431503),(-56.904351,-27.418687),(-56.904447,-27.418696),(-56.94099,-27.422098),(-56.977318,-27.435327),(-57.076227,-27.484006),(-57.10899,-27.490621),(-57.148161,-27.488967),(-57.156687,-27.487727),(-57.180097,-27.487313),(-57.180453,-27.487214),(-57.191207,-27.484213),(-57.200406,-27.478942),(-57.227071,-27.458685),(-57.237096,-27.45424),(-57.237588,-27.45412),(-57.283026,-27.443015),(-57.292493,-27.440701),(-57.302983,-27.435534),(-57.310116,-27.429208),(-57.326289,-27.414863),(-57.335229,-27.409489),(-57.356466,-27.404343),(-57.360396,-27.403391),(-57.386699,-27.403494),(-57.487675,-27.416413),(-57.513358,-27.41414),(-57.519938,-27.412099),(-57.535682,-27.407215),(-57.697791,-27.333524),(-57.698183,-27.333398),(-57.709367,-27.329804),(-57.811583,-27.310683),(-57.811913,-27.310583),(-57.854784,-27.297557),(-57.855088,-27.297499),(-57.899504,-27.288961),(-57.913385,-27.286292),(-57.94403,-27.274613),(-57.944356,-27.274551),(-58.003664,-27.263303),(-58.021958,-27.259834),(-58.022046,-27.259831),(-58.053532,-27.259007),(-58.113993,-27.268929),(-58.128824,-27.269652),(-58.238223,-27.257043),(-58.510765,-27.278437),(-58.600165,-27.312957),(-58.604196,-27.316264),(-58.604135,-27.315548),(-58.599907,-27.266138),(-58.60156,-27.245674),(-58.614014,-27.226657),(-58.638716,-27.210121),(-58.652358,-27.198029),(-58.658404,-27.18511),(-58.653289,-27.156274),(-58.638819,-27.135914),(-58.616133,-27.123821),(-58.56549,-27.115966),(-58.560529,-27.105528),(-58.56239,-27.090128),(-58.562183,-27.072145),(-58.559703,-27.06336),(-58.556395,-27.055505),(-58.551693,-27.048167),(-58.54544,-27.041036),(-58.536259,-27.036294),(-58.536035,-27.036178),(-58.530505,-27.040519),(-58.528025,-27.047754),(-58.528025,-27.051681),(-58.527043,-27.054161),(-58.520032,-27.058368),(-58.519808,-27.058502),(-58.51154,-27.060156),(-58.507561,-27.055092),(-58.506734,-27.038452),(-58.504874,-27.031527),(-58.50136,-27.023672),(-58.492368,-27.00972),(-58.47454,-26.990083),(-58.466633,-26.975923),(-58.481619,-26.963831),(-58.483686,-26.950602),(-58.47547,-26.937993),(-58.459812,-26.928174),(-58.415525,-26.917529),(-58.393873,-26.909674),(-58.384674,-26.897065),(-58.374701,-26.887557),(-58.328916,-26.884146),(-58.31579,-26.874121),(-58.322146,-26.856758),(-58.340388,-26.844459),(-58.352377,-26.830506),(-58.340026,-26.808595),(-58.323335,-26.803841),(-58.305506,-26.809112),(-58.288556,-26.811489),(-58.27481,-26.798363),(-58.278479,-26.790198),(-58.286541,-26.778726),(-58.287936,-26.768598),(-58.2714,-26.764257),(-58.259256,-26.764463),(-58.251763,-26.763223),(-58.247939,-26.758159),(-58.2452,-26.680231),(-58.240652,-26.661214),(-58.235536,-26.649845),(-58.232281,-26.648605),(-58.227165,-26.652015),(-58.195694,-26.657493),(-58.18386,-26.65677),(-58.178641,-26.650672),(-58.181379,-26.641577),(-58.187167,-26.633619),(-58.192076,-26.624627),(-58.192283,-26.612845),(-58.188511,-26.609744),(-58.171509,-26.598582),(-58.164946,-26.592278),(-58.170527,-26.5868),(-58.179312,-26.57264),(-58.18541,-26.564992),(-58.207993,-26.550213),(-58.213367,-26.544529),(-58.217346,-26.527579),(-58.214194,-26.512386),(-58.208716,-26.496883),(-58.205926,-26.479416),(-58.202722,-26.471561),(-58.188666,-26.462053),(-58.18541,-26.451718),(-58.209595,-26.431254),(-58.213057,-26.418645),(-58.206184,-26.402728),(-58.172698,-26.349295),(-58.167633,-26.335032),(-58.164946,-26.318599),(-58.170011,-26.28656),(-58.169959,-26.270333),(-58.161846,-26.263305),(-58.145981,-26.260101),(-58.123295,-26.251523),(-58.105983,-26.239534),(-58.106604,-26.226098),(-58.121228,-26.216693),(-58.137144,-26.209459),(-58.148927,-26.19933),(-58.151304,-26.18145),(-58.141175,-26.184757),(-58.133217,-26.188995),(-58.127636,-26.194679),(-58.124019,-26.201914),(-58.115234,-26.190958),(-58.106293,-26.170288),(-58.096682,-26.136698),(-58.086501,-26.12719),(-58.021596,-26.105692),(-57.988213,-26.088536),(-57.872716,-26.010298),(-57.859694,-25.994278),(-57.85959,-25.980945),(-57.905841,-25.968646),(-57.898244,-25.953557),(-57.863311,-25.927615),(-57.85711,-25.919864),(-57.851374,-25.908392),(-57.852407,-25.897953),(-57.875352,-25.890202),(-57.878194,-25.883174),(-57.875352,-25.876146),(-57.854216,-25.868911),(-57.833235,-25.858782),(-57.819662,-25.849779),(-57.812823,-25.845243),(-57.801868,-25.831394),(-57.817061,-25.797494),(-57.820626,-25.77827),(-57.805588,-25.769899),(-57.787243,-25.764111),(-57.767916,-25.750675),(-57.75107,-25.734862),(-57.740373,-25.72215),(-57.751121,-25.719566),(-57.760578,-25.715639),(-57.768485,-25.709954),(-57.774582,-25.701686),(-57.753705,-25.672747),(-57.741251,-25.661895),(-57.719909,-25.653834),(-57.708695,-25.652903),(-57.698205,-25.653627),(-57.688335,-25.652697),(-57.678981,-25.647012),(-57.67526,-25.639261),(-57.670041,-25.616937),(-57.668077,-25.612286),(-57.638777,-25.6158),(-57.623067,-25.615386),(-57.616298,-25.609185),(-57.611647,-25.585931),(-57.600691,-25.578799),(-57.587152,-25.575699),(-57.575318,-25.564433),(-57.570047,-25.546657),(-57.556921,-25.45984),(-57.55811,-25.44351),(-57.565293,-25.430385),(-57.578729,-25.416742),(-57.640792,-25.37261),(-57.641206,-25.360518),(-57.671488,-25.290135),(-57.671976,-25.289831),(-57.702339,-25.270911),(-57.721769,-25.246106),(-57.754067,-25.180891),(-57.766004,-25.167868),(-57.79732,-25.153916),(-57.81241,-25.143684),(-57.85649,-25.096762),(-57.870701,-25.085289),(-57.890493,-25.078675),(-57.969764,-25.078468),(-57.983769,-25.074231),(-57.989866,-25.064102),(-57.993639,-25.052733),(-58.00046,-25.044362),(-58.009814,-25.042501),(-58.032138,-25.045085),(-58.04206,-25.044362),(-58.111513,-25.012322),(-58.124019,-25.012942),(-58.133889,-24.997853),(-58.224064,-24.941216),(-58.242513,-24.941732),(-58.259152,-24.952998),(-58.287264,-24.979766),(-58.299305,-24.987724),(-58.311966,-24.993615),(-58.323283,-24.995269),(-58.335995,-24.991858),(-58.341318,-24.986174),(-58.344367,-24.978319),(-58.350568,-24.968604),(-58.414802,-24.903078),(-58.438521,-24.872796),(-58.450769,-24.861737),(-58.473403,-24.851299),(-58.694216,-24.812024),(-58.699384,-24.80727),(-58.701916,-24.799312),(-58.708117,-24.795075),(-58.715972,-24.791871),(-58.723258,-24.786703),(-58.737469,-24.782776),(-58.788474,-24.781639),(-58.809196,-24.776781),(-59.000916,-24.644179),(-59.032697,-24.637048),(-59.042412,-24.630537),(-59.062463,-24.612347),(-59.072178,-24.606766),(-59.078327,-24.605629),(-59.097189,-24.605422),(-59.116981,-24.598807),(-59.154395,-24.576277),(-59.177908,-24.568732),(-59.206485,-24.550232),(-59.248084,-24.537209),(-59.257644,-24.530181),(-59.263122,-24.523463),(-59.27046,-24.518192),(-59.285601,-24.516125),(-59.295058,-24.512921),(-59.308081,-24.498762),(-59.340973,-24.4876),(-59.357406,-24.468996),(-59.377766,-24.433546),(-59.387094,-24.423831),(-59.426032,-24.392515),(-59.450268,-24.382387),(-59.453808,-24.374532),(-59.456289,-24.365437),(-59.459725,-24.358512),(-59.4659,-24.353551),(-59.487656,-24.344766),(-59.51042,-24.332674),(-59.521143,-24.325026),(-59.53202,-24.31407),(-59.539979,-24.308799),(-59.558427,-24.305389),(-59.575403,-24.29588),(-59.600518,-24.292883),(-59.610517,-24.289576),(-59.617726,-24.283478),(-59.635322,-24.261464),(-59.67364,-24.225394),(-60.033669,-24.007009),(-60.05173,-24.002875),(-60.072375,-24.004839),(-60.119297,-24.020238),(-60.143249,-24.025199),(-60.218128,-24.027369),(-60.296418,-24.016414),(-60.328018,-24.017964),(-60.337372,-24.016414),(-60.348043,-24.010833),(-60.367577,-23.99471),(-60.378351,-23.988509),(-60.38742,-23.987165),(-60.423051,-23.988509),(-60.484882,-23.977347),(-60.517723,-23.955746),(-60.535964,-23.947581),(-60.57175,-23.946031),(-60.577538,-23.94417),(-60.593584,-23.912234),(-60.594617,-23.90655),(-60.603841,-23.90469),(-60.621153,-23.895801),(-60.63216,-23.892287),(-60.64371,-23.891357),(-60.689676,-23.893631),(-60.699417,-23.891254),(-60.719855,-23.875027),(-60.729286,-23.872133),(-60.787776,-23.873445),(-60.816852,-23.874097),(-60.837625,-23.871823),(-60.866358,-23.855907),(-60.899947,-23.830482),(-60.936663,-23.813842),(-60.974826,-23.824074),(-61.006349,-23.805471),(-61.015806,-23.796686),(-61.030224,-23.77462),(-61.036244,-23.768832),(-61.038053,-23.755396),(-61.04999,-23.734726),(-61.066216,-23.715709),(-61.092519,-23.70186),(-61.10965,-23.675608),(-61.118849,-23.66641),(-61.109754,-23.649977),(-61.10624,-23.627239),(-61.109857,-23.606982),(-61.122233,-23.598197),(-61.139493,-23.592719),(-61.154454,-23.580317),(-61.167812,-23.566571),(-61.18024,-23.557166),(-61.187733,-23.556235),(-61.20768,-23.557579),(-61.214398,-23.557166),(-61.223571,-23.551275),(-61.242924,-23.533084),(-61.251941,-23.52926),(-61.272612,-23.523576),(-61.282947,-23.509933),(-61.288967,-23.49412),(-61.296951,-23.481408),(-61.36178,-23.454743),(-61.384853,-23.453709),(-61.398677,-23.450092),(-61.408728,-23.443581),(-61.42051,-23.433659),(-61.435703,-23.423737),(-61.451929,-23.417433),(-61.4703,-23.414125),(-61.491849,-23.413195),(-61.501073,-23.407821),(-61.510375,-23.38436),(-61.526343,-23.374748),(-61.525465,-23.364723),(-61.520788,-23.35325),(-61.51606,-23.344982),(-61.533965,-23.344569),(-61.545773,-23.342605),(-61.554636,-23.338368),(-61.60515,-23.289275),(-61.619619,-23.282867),(-61.666851,-23.282867),(-61.680313,-23.27925),(-61.688762,-23.274496),(-61.70442,-23.258372),(-61.718528,-23.249277),(-61.732997,-23.243386),(-61.744263,-23.234808),(-61.74881,-23.217341),(-61.749482,-23.198841),(-61.752273,-23.187059),(-61.758474,-23.177447),(-61.769274,-23.165562),(-61.780023,-23.15688),(-61.802657,-23.144994),(-61.814284,-23.135176),(-61.83697,-23.104687),(-61.84498,-23.097245),(-61.956446,-23.034407),(-61.992051,-22.99813),(-62.0059,-22.978906),(-62.006055,-22.974359),(-62.008949,-22.969708),(-62.003782,-22.94635),(-62.006055,-22.936842),(-62.017166,-22.921752),(-62.035821,-22.884855),(-62.050446,-22.864495),(-62.071633,-22.843928),(-62.080831,-22.832352),(-62.084604,-22.820156),(-62.089358,-22.81995),(-62.099228,-22.813748),(-62.107858,-22.806514),(-62.108788,-22.803),(-62.115868,-22.799796),(-62.119744,-22.792148),(-62.122534,-22.783156),(-62.126151,-22.775715),(-62.153488,-22.747809),(-62.159741,-22.737164),(-62.164082,-22.725899),(-62.1708,-22.71732),(-62.184184,-22.713703),(-62.188267,-22.708329),(-62.175916,-22.684867),(-62.195036,-22.673602),(-62.194623,-22.66058),(-62.187646,-22.638565),(-62.192969,-22.62823),(-62.196586,-22.626473),(-62.202529,-22.627197),(-62.214932,-22.624303),(-62.239736,-22.613761),(-62.25281,-22.603632),(-62.252965,-22.591126),(-62.238858,-22.57304),(-62.233225,-22.556296),(-62.241183,-22.538416),(-62.263352,-22.514439),(-62.26883,-22.512992),(-62.2756,-22.513508),(-62.281387,-22.512061),(-62.283816,-22.504827),(-62.28361,-22.493768),(-62.28454,-22.488704),(-62.287227,-22.483949),(-62.294513,-22.479815),(-62.305727,-22.476715),(-62.341357,-22.472261),(-62.348722,-22.47134),(-62.368256,-22.464416),(-62.43807,-22.419664),(-62.454969,-22.403851),(-62.461945,-22.388761),(-62.470575,-22.381837),(-62.510727,-22.370158),(-62.523388,-22.364887),(-62.547624,-22.335328),(-62.564678,-22.321996),(-62.588294,-22.316414),(-62.599611,-22.315174),(-62.61315,-22.311454),(-62.625294,-22.305046),(-62.632684,-22.295951),(-62.630824,-22.287682),(-62.624209,-22.278897),(-62.620282,-22.268459),(-62.626431,-22.255023),(-62.61961,-22.255023),(-62.624829,-22.247271),(-62.631805,-22.24076),(-62.640384,-22.236213),(-62.650357,-22.234456),(-62.627516,-22.184536),(-62.599404,-22.089865),(-62.572843,-22.000775),(-62.529228,-21.865073),(-62.492796,-21.751798),(-62.446184,-21.606897),(-62.411974,-21.500857),(-62.37549,-21.384482),(-62.340402,-21.272861),(-62.307898,-21.169301),(-62.275703,-21.066568),(-62.271879,-21.000939),(-62.271886,-21.000424),(-62.273791,-20.854798),(-62.275031,-20.75868),(-62.276168,-20.670727),(-62.277305,-20.579776),(-62.26883,-20.553111),(-62.232398,-20.501021),(-62.210573,-20.471305),(-62.189662,-20.442834),(-62.144962,-20.382062),(-62.10021,-20.321187),(-62.05551,-20.260416),(-62.01081,-20.199541),(-61.99417,-20.175667),(-61.977582,-20.151792),(-61.960942,-20.128021),(-61.94425,-20.104146),(-61.931383,-20.078308),(-61.92474,-20.065128),(-61.918412,-20.052573),(-61.905545,-20.026735),(-61.892574,-20.000897),(-61.892522,-20.000897),(-61.86441,-19.927413),(-61.836298,-19.853826),(-61.808186,-19.780342),(-61.780074,-19.706961),(-61.761213,-19.657765),(-61.753203,-19.64588),(-61.737235,-19.639575),(-61.648222,-19.62676),(-61.626725,-19.623659),(-61.579544,-19.616838),(-61.532286,-19.610016),(-61.51084,-19.606916),(-61.17236,-19.537463),(-60.833931,-19.467906),(-60.495476,-19.398453),(-60.156995,-19.329),(-60.006384,-19.298097),(-59.924322,-19.297064),(-59.735858,-19.29479),(-59.547498,-19.292413),(-59.359085,-19.290139),(-59.170725,-19.287762),(-59.089541,-19.286729),(-59.069646,-19.291483),(-59.039673,-19.311637),(-59.011096,-19.330964),(-58.96066,-19.360523),(-58.867436,-19.4153),(-58.774108,-19.470077),(-58.680832,-19.52475),(-58.587504,-19.579424),(-58.49428,-19.634201),(-58.401004,-19.688875),(-58.30778,-19.743652),(-58.214452,-19.798325),(-58.175282,-19.821373),(-58.164429,-19.832949),(-58.161174,-19.847211),(-58.164223,-19.880284),(-58.162207,-19.912324),(-58.145154,-19.969581),(-58.141847,-20.000897),(-58.144482,-20.023118),(-58.143139,-20.065286),(-58.144741,-20.086163),(-58.15952,-20.13908),(-58.158797,-20.165125)] +Qatar [(51.215258,24.62585),(51.147451,24.576279),(51.095465,24.560182),(51.038879,24.559872),(50.978883,24.567726),(50.928602,24.587208),(50.881008,24.636404),(50.807872,24.746649),(50.826671,24.748684),(50.852794,24.770006),(50.85963,24.7956),(50.851085,24.890815),(50.842784,24.916083),(50.799978,24.988756),(50.796641,25.003607),(50.807384,25.031643),(50.809744,25.051215),(50.808604,25.069159),(50.802419,25.076972),(50.775727,25.091864),(50.768403,25.1258),(50.766938,25.162584),(50.757823,25.186225),(50.764985,25.204291),(50.763438,25.225287),(50.759044,25.247504),(50.757823,25.269355),(50.765798,25.323554),(50.765147,25.344468),(50.750987,25.419623),(50.762462,25.462714),(50.763845,25.482408),(50.750987,25.494696),(50.778005,25.527045),(50.797093,25.529896),(50.808484,25.517239),(50.811648,25.498887),(50.820508,25.491293),(50.820486,25.471829),(50.847179,25.467353),(50.831309,25.507799),(50.827891,25.525051),(50.826671,25.543118),(50.828624,25.554348),(50.832205,25.566148),(50.832856,25.578518),(50.826671,25.590888),(50.818533,25.595771),(50.79656,25.599595),(50.785004,25.60456),(50.796397,25.617255),(50.809581,25.620592),(50.823497,25.622138),(50.836925,25.628811),(50.84018,25.634508),(50.846528,25.649848),(50.850597,25.652981),(50.857188,25.650824),(50.863536,25.641425),(50.870942,25.639309),(50.87615,25.631781),(50.874278,25.614936),(50.867686,25.587836),(50.867686,25.567043),(50.868663,25.559556),(50.87672,25.540595),(50.881521,25.535142),(50.888682,25.529486),(50.898692,25.532213),(50.900727,25.534857),(50.900076,25.53974),(50.904145,25.563137),(50.904796,25.587063),(50.90919,25.597724),(50.920584,25.608344),(50.927501,25.60517),(50.93572,25.598334),(50.949555,25.597724),(50.955903,25.604682),(50.9699,25.633857),(50.97755,25.646145),(50.94988,25.636461),(50.924327,25.63231),(50.903168,25.640123),(50.888682,25.666653),(50.887543,25.680894),(50.894867,25.728095),(50.897309,25.732571),(50.906993,25.739936),(50.90919,25.745103),(50.90797,25.749254),(50.902843,25.755276),(50.901703,25.759467),(50.901703,25.789537),(50.915538,25.786444),(50.920258,25.794379),(50.923595,25.805162),(50.932872,25.810614),(50.939708,25.807196),(50.945567,25.798489),(50.949229,25.787014),(50.949555,25.775295),(50.963715,25.783881),(50.972992,25.797512),(50.975922,25.813788),(50.970714,25.830512),(50.963878,25.823676),(50.949392,25.837958),(50.951182,25.85928),(50.977306,25.916449),(50.981456,25.935858),(50.984223,25.98135),(50.992524,25.975735),(50.995616,25.972846),(50.998546,25.967027),(51.004731,25.967027),(51.027354,26.026923),(51.047374,26.053046),(51.075938,26.06391),(51.091075,26.066962),(51.133149,26.082099),(51.141856,26.087795),(51.147227,26.103095),(51.170584,26.124579),(51.176117,26.139594),(51.194347,26.133531),(51.214854,26.13935),(51.251231,26.160102),(51.33074,26.121161),(51.346853,26.104885),(51.348481,26.085639),(51.346365,26.060696),(51.347179,26.039008),(51.357677,26.029731),(51.376638,26.022895),(51.382498,26.006171),(51.383474,25.985582),(51.388438,25.967027),(51.403982,25.954088),(51.416515,25.952094),(51.424327,25.950873),(51.46754,25.954047),(51.491954,25.95189),(51.511974,25.946112),(51.52947,25.937323),(51.546072,25.926093),(51.559418,25.913764),(51.570323,25.898383),(51.577485,25.880845),(51.594737,25.771877),(51.594493,25.758246),(51.591563,25.746649),(51.583507,25.741767),(51.577647,25.745063),(51.572032,25.759508),(51.563324,25.762885),(51.555431,25.758694),(51.54835,25.748847),(51.544607,25.737372),(51.546072,25.728095),(51.555024,25.720649),(51.56365,25.721625),(51.570323,25.727484),(51.573985,25.734931),(51.590099,25.7119),(51.576834,25.688666),(51.556814,25.681627),(51.552908,25.707587),(51.539317,25.703925),(51.505138,25.687161),(51.519705,25.681708),(51.534923,25.673245),(51.54713,25.663153),(51.552908,25.652981),(51.54949,25.631171),(51.535899,25.622382),(51.518809,25.61872),(51.505138,25.612006),(51.498302,25.615912),(51.491384,25.618232),(51.493663,25.565823),(51.491547,25.550645),(51.491384,25.549302),(51.48585,25.540513),(51.47755,25.531073),(51.471934,25.521389),(51.474294,25.512112),(51.510997,25.454291),(51.516938,25.440172),(51.518809,25.426215),(51.515717,25.382839),(51.511974,25.330227),(51.513194,25.308254),(51.518809,25.297065),(51.531261,25.292182),(51.590017,25.283759),(51.599132,25.274888),(51.607595,25.255113),(51.611095,25.237535),(51.614594,25.219794),(51.616547,25.137193),(51.605724,25.034247),(51.611013,25.022366),(51.602306,25.013821),(51.586925,24.953437),(51.574067,24.934394),(51.539399,24.898871),(51.528819,24.874416),(51.520844,24.870592),(51.511729,24.867865),(51.505138,24.864081),(51.500255,24.855373),(51.474213,24.764472),(51.47283,24.759426),(51.46754,24.748684),(51.455821,24.740668),(51.450369,24.721666),(51.443614,24.679755),(51.430431,24.664496),(51.389985,24.642483),(51.381521,24.635077),(51.37615,24.611884),(51.363536,24.59634),(51.349783,24.583808),(51.340587,24.569892),(51.328949,24.584784),(51.332693,24.598863),(51.341645,24.614691),(51.346853,24.635077),(51.339122,24.646186),(51.321137,24.648179),(51.285981,24.645006),(51.284434,24.662502),(51.278087,24.662991),(51.267914,24.656195),(51.254568,24.651801),(51.23699,24.650051),(51.220958,24.644232),(51.212576,24.633694),(51.214854,24.627183),(51.215258,24.62585)] +Romania [(26.722379,48.259769),(26.733127,48.27075),(26.744031,48.255583),(26.76372,48.252741),(26.804906,48.25827),(26.821908,48.252534),(26.844749,48.23331),(26.855497,48.237832),(26.897665,48.208971),(26.90397,48.201452),(26.908001,48.184528),(26.917716,48.187964),(26.929085,48.199049),(26.938128,48.204811),(26.950582,48.197524),(26.955646,48.186),(26.963088,48.175381),(26.997607,48.16657),(26.997607,48.15794),(26.986239,48.150421),(26.966602,48.149594),(26.966602,48.143367),(26.99399,48.132412),(27.012697,48.128123),(27.025099,48.135048),(27.033678,48.132386),(27.042773,48.127296),(27.048044,48.122232),(27.047955,48.121409),(27.047424,48.116496),(27.036882,48.107349),(27.034298,48.101768),(27.041739,48.077273),(27.059206,48.05805),(27.083184,48.043658),(27.109332,48.033503),(27.109332,48.026088),(27.088971,48.019809),(27.090005,48.015623),(27.091452,48.011851),(27.093364,48.00844),(27.095793,48.005598),(27.121476,48.013194),(27.134602,48.000456),(27.143748,47.986839),(27.157184,47.991955),(27.16876,47.983067),(27.169793,47.973791),(27.162869,47.965006),(27.150983,47.957797),(27.171964,47.946429),(27.178268,47.944129),(27.178268,47.942096),(27.178268,47.937928),(27.160698,47.921727),(27.17155,47.912632),(27.194185,47.904054),(27.212375,47.889507),(27.211548,47.885011),(27.213202,47.854134),(27.212375,47.847933),(27.222813,47.842662),(27.234906,47.840208),(27.245809,47.83659),(27.253406,47.828089),(27.219196,47.813775),(27.231082,47.807083),(27.244879,47.792588),(27.256196,47.77755),(27.260847,47.769075),(27.264671,47.764553),(27.282448,47.755691),(27.287512,47.752332),(27.288114,47.75068),(27.29113,47.74241),(27.289579,47.731687),(27.295057,47.724427),(27.295057,47.718174),(27.272009,47.71497),(27.281104,47.693007),(27.304049,47.666549),(27.369161,47.60831),(27.397066,47.589086),(27.428382,47.581024),(27.429404,47.57813),(27.431342,47.572638),(27.435824,47.55994),(27.438976,47.553713),(27.440268,47.550096),(27.440061,47.541027),(27.442128,47.536634),(27.446056,47.534877),(27.456908,47.533896),(27.459491,47.533224),(27.466726,47.506352),(27.473134,47.491779),(27.483676,47.485423),(27.492564,47.484545),(27.497525,47.482426),(27.501453,47.479945),(27.50724,47.477982),(27.532975,47.477413),(27.534526,47.477982),(27.548168,47.474261),(27.563154,47.468344),(27.575867,47.460412),(27.582998,47.450671),(27.574782,47.446252),(27.569356,47.438553),(27.565531,47.428269),(27.562534,47.416538),(27.580311,47.405996),(27.572353,47.375197),(27.586409,47.368764),(27.588724,47.367389),(27.599948,47.360728),(27.624029,47.321428),(27.636948,47.306674),(27.6447,47.303987),(27.671727,47.299853),(27.68232,47.295254),(27.689865,47.290887),(27.697823,47.287502),(27.722835,47.283317),(27.733273,47.275617),(27.753634,47.251432),(27.752393,47.238926),(27.763039,47.226317),(27.788309,47.204277),(27.800349,47.176966),(27.802106,47.176346),(27.804793,47.168492),(27.807687,47.162471),(27.805879,47.158234),(27.794665,47.155831),(27.80655,47.144617),(27.849855,47.12852),(27.849855,47.121724),(27.843757,47.114386),(27.848202,47.111415),(27.85771,47.109322),(27.867012,47.104645),(27.897604,47.081417),(27.925923,47.068756),(27.938429,47.061056),(27.938739,47.046638),(27.96313,47.043383),(27.986591,47.033228),(28.008295,47.026304),(28.028036,47.03297),(28.037027,47.016459),(28.038146,47.015483),(28.069067,46.988503),(28.082709,46.971527),(28.102295,46.935121),(28.104994,46.920185),(28.105447,46.91768),(28.096869,46.902616),(28.11356,46.894761),(28.114335,46.883393),(28.113095,46.87143),(28.124257,46.861637),(28.124257,46.854195),(28.122615,46.84227),(28.121518,46.8343),(28.137796,46.80624),(28.178156,46.758646),(28.178104,46.739836),(28.234121,46.662424),(28.24425,46.635372),(28.245085,46.631451),(28.24735,46.620825),(28.247144,46.607156),(28.240529,46.596382),(28.230504,46.583902),(28.225439,46.569562),(28.234121,46.553129),(28.224768,46.548736),(28.221099,46.541191),(28.219032,46.503726),(28.221099,46.495768),(28.234121,46.478069),(28.2381,46.475588),(28.242338,46.476518),(28.2458,46.475511),(28.247144,46.467191),(28.247247,46.436185),(28.246058,46.427865),(28.240219,46.420268),(28.22606,46.415359),(28.233294,46.401768),(28.228643,46.39611),(28.226796,46.395548),(28.219548,46.393345),(28.212934,46.388694),(28.207146,46.358153),(28.202392,46.353916),(28.190351,46.351074),(28.187922,46.343787),(28.191953,46.323504),(28.192883,46.311231),(28.191333,46.307769),(28.177794,46.287047),(28.165753,46.27883),(28.156296,46.275368),(28.144928,46.272939),(28.135212,46.269322),(28.131078,46.262397),(28.134489,46.245344),(28.132112,46.239918),(28.120846,46.237851),(28.108961,46.23413),(28.110976,46.225603),(28.129321,46.204674),(28.135626,46.198835),(28.141517,46.191962),(28.144721,46.183229),(28.133249,46.159974),(28.127358,46.135325),(28.110506,46.101491),(28.107823,46.096103),(28.100796,46.081995),(28.092838,46.078377),(28.090151,46.073365),(28.090461,46.06799),(28.096558,46.065045),(28.096869,46.05967),(28.084466,46.024582),(28.082709,46.014712),(28.08612,46.000552),(28.110511,45.950426),(28.112371,45.939213),(28.114852,45.933218),(28.120846,45.926293),(28.124981,45.918387),(28.12281,45.910791),(28.118779,45.903142),(28.117436,45.895236),(28.120226,45.887846),(28.129115,45.875134),(28.131078,45.871361),(28.128184,45.8664),(28.114955,45.859734),(28.110511,45.854308),(28.113302,45.825369),(28.128908,45.795035),(28.146478,45.771161),(28.154953,45.761807),(28.163738,45.661503),(28.161774,45.645432),(28.167975,45.632461),(28.153713,45.6275),(28.120846,45.627707),(28.107721,45.6244),(28.091184,45.615976),(28.074751,45.604866),(28.062142,45.593601),(28.118004,45.572723),(28.140949,45.560218),(28.157743,45.538927),(28.161567,45.532726),(28.164048,45.530607),(28.165391,45.528282),(28.165908,45.494589),(28.172936,45.484357),(28.199498,45.461774),(28.212934,45.450198),(28.215146,45.450365),(28.237635,45.452059),(28.266884,45.440483),(28.286418,45.421725),(28.281198,45.401829),(28.310809,45.347827),(28.330239,45.322919),(28.353287,45.312429),(28.370237,45.309225),(28.40517,45.295066),(28.494157,45.278891),(28.577046,45.248092),(28.710061,45.226956),(28.747371,45.23047),(28.778687,45.23109),(28.7914,45.234966),(28.802665,45.244165),(28.774295,45.253363),(28.767267,45.257755),(28.762564,45.265145),(28.75967,45.274189),(28.761531,45.281837),(28.79016,45.292069),(28.788609,45.307106),(28.789746,45.321421),(28.816308,45.326072),(28.831811,45.322299),(28.858114,45.30907),(28.880852,45.306176),(28.893616,45.29982),(28.910049,45.287366),(28.929893,45.279098),(28.952837,45.285092),(28.957384,45.292017),(28.960433,45.311292),(28.96648,45.319871),(28.973663,45.323695),(28.982448,45.325503),(29.004617,45.326072),(29.018156,45.330878),(29.069522,45.360798),(29.110295,45.369066),(29.127503,45.374544),(29.141869,45.385086),(29.150138,45.387877),(29.174322,45.388962),(29.179386,45.391856),(29.183107,45.398987),(29.191582,45.40617),(29.206672,45.41542),(29.228169,45.42374),(29.244602,45.424205),(29.260828,45.422035),(29.281809,45.422293),(29.290491,45.424619),(29.299276,45.428908),(29.307027,45.434127),(29.312815,45.439346),(29.322117,45.443842),(29.332969,45.442137),(29.343924,45.438106),(29.353743,45.435936),(29.430637,45.430406),(29.569699,45.394956),(29.616362,45.365346),(29.628145,45.360798),(29.650262,45.346122),(29.667109,45.311861),(29.672276,45.272948),(29.659254,45.244165),(29.66499,45.23786),(29.666488,45.230625),(29.664215,45.223184),(29.659079,45.215887),(29.659075,45.215881),(29.659028,45.215888),(29.650157,45.217231),(29.623871,45.216498),(29.623871,45.210273),(29.638845,45.195624),(29.64975,45.177802),(29.667003,45.164211),(29.699555,45.161811),(29.676524,45.144599),(29.664399,45.116929),(29.656261,45.028957),(29.650727,45.012112),(29.637543,44.98371),(29.634939,44.96955),(29.633637,44.953355),(29.63087,44.938666),(29.623871,44.929104),(29.630382,44.90766),(29.605154,44.880032),(29.617849,44.861477),(29.611176,44.849311),(29.603201,44.845404),(29.593761,44.844306),(29.583507,44.840277),(29.569347,44.824897),(29.561778,44.820258),(29.542003,44.827826),(29.531098,44.826239),(29.520518,44.822496),(29.510997,44.820502),(29.315929,44.798774),(29.192068,44.792873),(29.156098,44.78441),(29.055837,44.735175),(29.026378,44.714667),(29.000743,44.68891),(28.993907,44.696357),(28.994884,44.711127),(28.981293,44.729438),(28.974946,44.74494),(28.997325,44.751614),(29.021495,44.754706),(29.058279,44.768297),(29.098155,44.775377),(29.120616,44.786566),(29.138682,44.804023),(29.144705,44.826646),(29.138845,44.839179),(29.125987,44.852484),(29.096365,44.875067),(29.101817,44.859117),(29.103363,44.851304),(29.10377,44.840277),(29.087901,44.842719),(29.073497,44.835435),(29.060313,44.832343),(29.048595,44.847154),(29.044119,44.865546),(29.041759,44.925686),(29.052094,44.944648),(29.098806,44.956977),(29.110606,44.970038),(29.101736,44.980292),(29.058279,45.000963),(29.045177,45.004828),(29.014415,45.004828),(28.983246,45.012274),(28.97283,45.010972),(28.969249,45.005845),(28.966075,44.996568),(28.960216,44.987698),(28.949229,44.98371),(28.927013,44.982611),(28.91684,44.979682),(28.880056,44.954779),(28.869395,44.943345),(28.863536,44.922309),(28.865082,44.916571),(28.87436,44.911566),(28.876638,44.904853),(28.874685,44.899115),(28.870128,44.89643),(28.865489,44.89468),(28.863536,44.891547),(28.866466,44.882636),(28.873546,44.874986),(28.881521,44.869696),(28.904063,44.862738),(28.952403,44.826646),(28.939708,44.816881),(28.934093,44.814195),(28.924978,44.813056),(28.934418,44.807522),(28.938731,44.80622),(28.938731,44.798774),(28.92628,44.792955),(28.925466,44.783677),(28.932953,44.773505),(28.946137,44.765204),(28.936371,44.759955),(28.923839,44.757799),(28.879405,44.756578),(28.868826,44.753567),(28.808442,44.726874),(28.79835,44.720201),(28.788829,44.706244),(28.78712,44.693305),(28.793712,44.687893),(28.80836,44.696357),(28.80421,44.684231),(28.785411,44.679674),(28.781016,44.665269),(28.784028,44.649237),(28.792491,44.644721),(28.845551,44.651557),(28.869477,44.661811),(28.891368,44.677191),(28.911957,44.696357),(28.897716,44.716783),(28.967459,44.700995),(28.983409,44.692613),(28.987559,44.675279),(28.97934,44.655341),(28.962087,44.63939),(28.938731,44.634263),(28.956391,44.651109),(28.972667,44.670233),(28.975352,44.686835),(28.952403,44.696357),(28.952403,44.68891),(28.959972,44.681952),(28.957774,44.678778),(28.938731,44.675238),(28.924164,44.682074),(28.918224,44.682685),(28.913829,44.679918),(28.909434,44.675198),(28.904552,44.668402),(28.885427,44.658108),(28.854177,44.634345),(28.836274,44.627427),(28.787852,44.609605),(28.774181,44.600775),(28.791515,44.623847),(28.794688,44.634263),(28.779796,44.63581),(28.766938,44.633734),(28.757823,44.626776),(28.753673,44.613756),(28.766775,44.613756),(28.76059,44.603705),(28.764415,44.595893),(28.774425,44.590155),(28.787852,44.586493),(28.748057,44.577786),(28.732677,44.567857),(28.732677,44.552314),(28.737153,44.557074),(28.743907,44.561998),(28.746918,44.565985),(28.761078,44.560207),(28.774181,44.552314),(28.765636,44.538886),(28.753429,44.513495),(28.745616,44.486151),(28.750255,44.466702),(28.758474,44.465277),(28.766368,44.472602),(28.771983,44.48371),(28.778331,44.507392),(28.788097,44.515367),(28.80836,44.525051),(28.838145,44.554023),(28.855642,44.567694),(28.873546,44.573432),(28.892426,44.577053),(28.906261,44.587714),(28.914887,44.601386),(28.924978,44.620551),(28.918468,44.60102),(28.909679,44.584215),(28.844005,44.49372),(28.796723,44.467922),(28.706554,44.381049),(28.6963,44.358344),(28.693126,44.346137),(28.680186,44.353339),(28.664399,44.348375),(28.651215,44.340033),(28.64088,44.328559),(28.635102,44.316392),(28.632335,44.302436),(28.631033,44.26435),(28.635265,44.252021),(28.651215,44.23078),(28.665212,44.199286),(28.668142,44.184312),(28.664887,44.175605),(28.671723,44.168687),(28.658376,44.174465),(28.645844,44.172024),(28.636241,44.164293),(28.63087,44.154486),(28.637462,44.135891),(28.654145,44.054918),(28.671235,44.003323),(28.671723,43.997382),(28.669119,43.989163),(28.660004,43.979804),(28.654959,43.961371),(28.64088,43.932196),(28.637706,43.918647),(28.61378,43.884182),(28.609386,43.874498),(28.593516,43.819525),(28.587657,43.810248),(28.584483,43.800849),(28.589203,43.791327),(28.584809,43.782416),(28.58253,43.772366),(28.581879,43.761705),(28.583018,43.751044),(28.57838,43.741278),(28.434574,43.735213),(28.221254,43.761981),(28.014806,43.830039),(27.98101,43.84934),(27.935845,43.964398),(27.912074,43.993233),(27.912074,43.993336),(27.85647,43.988634),(27.787327,43.960419),(27.721698,43.94874),(27.682515,43.987256),(27.676119,43.993543),(27.656275,44.023877),(27.633434,44.029768),(27.574523,44.016281),(27.383837,44.015092),(27.372882,44.020725),(27.353555,44.045271),(27.341669,44.053074),(27.285342,44.072453),(27.26431,44.089765),(27.269012,44.112399),(27.252662,44.121519),(27.251132,44.122373),(27.226741,44.120719),(27.205553,44.129246),(27.100237,44.14449),(27.027476,44.177046),(27.001535,44.165109),(26.884126,44.156531),(26.789455,44.115965),(26.753695,44.10811),(26.708685,44.10811),(26.697212,44.106094),(26.677317,44.097051),(26.667808,44.095087),(26.647758,44.093382),(26.614168,44.084855),(26.415791,44.063789),(26.332335,44.054926),(26.310518,44.052609),(26.231453,44.027495),(26.150734,44.012405),(26.116214,43.998866),(26.079317,43.969049),(26.061644,43.949773),(26.054306,43.934322),(25.934003,43.870321),(25.924495,43.858616),(25.916433,43.844379),(25.869304,43.800893),(25.839332,43.788439),(25.806259,43.763661),(25.804399,43.759914),(25.781144,43.732009),(25.739596,43.718935),(25.732948,43.718781),(25.671384,43.717359),(25.653503,43.708134),(25.637897,43.697282),(25.616503,43.687748),(25.593869,43.680668),(25.575059,43.677387),(25.556558,43.670359),(25.533821,43.668679),(25.488759,43.67054),(25.48245,43.669715),(25.467417,43.667749),(25.426075,43.654391),(25.403131,43.65005),(25.35962,43.654287),(25.323033,43.669713),(25.28872,43.688962),(25.285405,43.690391),(25.252339,43.704646),(25.211308,43.711881),(25.0816,43.718935),(24.963675,43.749605),(24.752628,43.738804),(24.705603,43.743765),(24.661763,43.755657),(24.500137,43.799498),(24.466341,43.802418),(24.431201,43.794176),(24.375494,43.763867),(24.358234,43.760017),(24.336705,43.759251),(24.159383,43.752938),(24.149606,43.75472),(23.799922,43.818463),(23.742871,43.8427),(23.720753,43.845826),(23.636107,43.832158),(23.620854,43.83401),(23.592699,43.837429),(23.484695,43.880604),(23.325151,43.886592),(23.234478,43.877297),(23.196961,43.86275),(23.161924,43.857324),(23.131849,43.847945),(23.052551,43.84282),(22.919562,43.834225),(22.888763,43.839522),(22.863441,43.855412),(22.851039,43.874352),(22.850522,43.896986),(22.874707,43.972046),(22.885869,43.994525),(22.905816,44.003982),(22.926486,44.006152),(22.966277,44.015557),(22.988085,44.017676),(23.023018,44.031629),(23.040071,44.062325),(23.030976,44.093072),(23.008307,44.100446),(22.988085,44.107025),(22.942609,44.111469),(22.906436,44.122889),(22.69164,44.228435),(22.690739,44.228878),(22.685364,44.243657),(22.689498,44.291716),(22.68154,44.305307),(22.662523,44.311663),(22.621182,44.315901),(22.582838,44.328406),(22.549352,44.348974),(22.522687,44.37507),(22.505117,44.404061),(22.50398,44.411709),(22.506357,44.427522),(22.505427,44.435015),(22.500983,44.44194),(22.480002,44.455789),(22.477005,44.463954),(22.477212,44.476976),(22.479795,44.490412),(22.484136,44.499766),(22.491061,44.50421),(22.500363,44.50638),(22.535503,44.507517),(22.548422,44.511703),(22.55669,44.52147),(22.55979,44.538781),(22.565578,44.555421),(22.580461,44.565498),(22.600305,44.569787),(22.621182,44.569219),(22.642163,44.563121),(22.678543,44.545551),(22.700144,44.54183),(22.719367,44.544362),(22.741692,44.551855),(22.759262,44.564671),(22.765153,44.58281),(22.714716,44.623065),(22.700144,44.63061),(22.621182,44.637432),(22.587489,44.649369),(22.553279,44.669161),(22.483723,44.72399),(22.468943,44.730191),(22.450547,44.732981),(22.426052,44.733653),(22.41551,44.727814),(22.38068,44.700528),(22.361146,44.692054),(22.319702,44.685336),(22.304922,44.677377),(22.299031,44.661668),(22.185136,44.515113),(22.172114,44.505347),(22.148239,44.500902),(22.126639,44.502659),(22.104314,44.509636),(22.086951,44.52178),(22.076306,44.550718),(22.067107,44.55723),(22.055739,44.562139),(22.045197,44.569219),(22.039822,44.576867),(22.036174,44.589489),(22.034243,44.596168),(22.032174,44.603325),(22.004269,44.651539),(21.994347,44.658567),(21.962411,44.662288),(21.871977,44.695981),(21.855441,44.698461),(21.838284,44.695206),(21.801697,44.683889),(21.756842,44.677274),(21.705166,44.677067),(21.65628,44.687661),(21.619693,44.713913),(21.610288,44.731948),(21.604293,44.749983),(21.595612,44.765951),(21.578042,44.777681),(21.558405,44.78166),(21.49722,44.778043),(21.41216,44.784813),(21.395934,44.790239),(21.378571,44.816645),(21.360587,44.826412),(21.359841,44.826644),(21.3598,44.826657),(21.342811,44.831942),(21.346428,44.845636),(21.355523,44.856591),(21.368545,44.86486),(21.395314,44.871629),(21.453398,44.869562),(21.48151,44.872611),(21.522128,44.880776),(21.536287,44.889302),(21.539078,44.908474),(21.531016,44.924649),(21.51634,44.933899),(21.48151,44.943563),(21.456499,44.952348),(21.40844,44.958342),(21.385185,44.969504),(21.384565,44.97493),(21.387046,44.981545),(21.383945,44.986661),(21.366995,44.987281),(21.353456,44.989813),(21.351389,44.998236),(21.356143,45.008572),(21.363378,45.01653),(21.3733,45.020096),(21.398828,45.021387),(21.409266,45.023971),(21.421875,45.031413),(21.425079,45.036219),(21.425596,45.043247),(21.429524,45.057303),(21.432521,45.061488),(21.440996,45.068723),(21.443786,45.072909),(21.444406,45.07787),(21.444406,45.08526),(21.443786,45.091461),(21.442443,45.092908),(21.449987,45.101021),(21.458566,45.107325),(21.469004,45.111046),(21.48151,45.111563),(21.494119,45.119314),(21.49784,45.131872),(21.493292,45.145101),(21.484388,45.152702),(21.459393,45.17404),(21.433761,45.188819),(21.405546,45.199671),(21.299299,45.223184),(21.257131,45.224114),(21.239251,45.229385),(21.206075,45.245922),(21.189745,45.259564),(21.155638,45.295169),(21.139412,45.303696),(21.12918,45.301887),(21.113057,45.28933),(21.103342,45.286074),(21.09156,45.288089),(21.082775,45.293671),(21.0743,45.300544),(21.063964,45.30628),(21.016668,45.321482),(20.981489,45.33279),(20.966193,45.341575),(20.927642,45.37749),(20.863047,45.418728),(20.830387,45.452524),(20.816021,45.462859),(20.799484,45.468544),(20.781604,45.472574),(20.767135,45.479344),(20.760727,45.493348),(20.783155,45.506061),(20.797624,45.516499),(20.800208,45.530504),(20.787392,45.553655),(20.75804,45.58926),(20.754423,45.605589),(20.762174,45.630601),(20.773233,45.648894),(20.777264,45.657524),(20.779951,45.671684),(20.779124,45.72367),(20.781604,45.733954),(20.785532,45.743411),(20.785739,45.752557),(20.77747,45.762324),(20.765171,45.766768),(20.754113,45.763564),(20.745328,45.754986),(20.739436,45.743411),(20.726827,45.736176),(20.713392,45.733334),(20.700059,45.735401),(20.68807,45.7431),(20.678562,45.75664),(20.655617,45.77731),(20.645902,45.788731),(20.64349,45.795141),(20.642285,45.798343),(20.640114,45.818703),(20.636704,45.827023),(20.629676,45.833276),(20.612312,45.841492),(20.605284,45.846143),(20.572108,45.887691),(20.556709,45.89844),(20.538002,45.903711),(20.499865,45.906656),(20.481674,45.912703),(20.429068,45.946706),(20.410258,45.955594),(20.370984,45.96779),(20.35393,45.976678),(20.338634,45.992801),(20.317653,46.038586),(20.305665,46.053572),(20.242826,46.108091),(20.283237,46.1438),(20.444157,46.1469),(20.468549,46.174134),(20.509373,46.167674),(20.548957,46.15615),(20.578103,46.137547),(20.588025,46.132844),(20.600117,46.12964),(20.607558,46.129485),(20.663989,46.137753),(20.683523,46.144678),(20.698819,46.15646),(20.704193,46.16633),(20.704368,46.168526),(20.70533,46.180645),(20.710291,46.188086),(20.717836,46.189998),(20.727137,46.187725),(20.736646,46.186691),(20.744707,46.192272),(20.744811,46.200282),(20.735509,46.222503),(20.734992,46.231908),(20.739333,46.237489),(20.778504,46.260072),(20.787369,46.26339),(20.798658,46.267616),(20.819638,46.271699),(20.839689,46.271079),(20.848991,46.267771),(20.866974,46.257126),(20.875139,46.254387),(20.885061,46.255007),(20.899737,46.260692),(20.906558,46.26219),(20.924438,46.259555),(20.961748,46.248341),(20.981489,46.248858),(20.990584,46.251597),(20.999162,46.251597),(21.007017,46.248858),(21.013942,46.24307),(21.033475,46.231339),(21.051459,46.236094),(21.099208,46.27635),(21.105616,46.278675),(21.134865,46.27852),(21.144476,46.283739),(21.155949,46.298932),(21.164527,46.318259),(21.168661,46.362753),(21.17879,46.384457),(21.195636,46.398099),(21.21517,46.402905),(21.257544,46.404171),(21.280695,46.416393),(21.274391,46.438355),(21.245142,46.47688),(21.247623,46.497473),(21.261679,46.513338),(21.278938,46.528401),(21.291341,46.546721),(21.295268,46.585039),(21.300953,46.603926),(21.316249,46.616639),(21.337643,46.620411),(21.374436,46.618448),(21.396037,46.626354),(21.416811,46.645216),(21.423539,46.658231),(21.425493,46.662011),(21.436241,46.673741),(21.463527,46.677049),(21.483577,46.684852),(21.501767,46.703507),(21.505178,46.723247),(21.478203,46.735934),(21.475206,46.737846),(21.472622,46.740197),(21.470451,46.743014),(21.471381,46.749034),(21.473655,46.754873),(21.477066,46.760222),(21.48151,46.764976),(21.502904,46.80531),(21.51572,46.821588),(21.536597,46.835023),(21.573081,46.841767),(21.583416,46.847943),(21.591788,46.860707),(21.591477,46.871533),(21.588067,46.882204),(21.587137,46.8944),(21.588687,46.906182),(21.589927,46.908869),(21.594371,46.910006),(21.640053,46.935689),(21.648528,46.942976),(21.667545,46.992378),(21.671369,46.99336),(21.670749,46.994394),(21.661757,47.006072),(21.654833,47.009948),(21.645221,47.01124),(21.636643,47.014082),(21.63427,47.019422),(21.632819,47.022686),(21.671886,47.054726),(21.69421,47.069169),(21.74351,47.091597),(21.763767,47.105214),(21.770485,47.114025),(21.775446,47.131672),(21.77989,47.140741),(21.789398,47.150301),(21.811516,47.164693),(21.819887,47.172729),(21.825985,47.185054),(21.825675,47.194278),(21.823298,47.203321),(21.823608,47.214923),(21.827742,47.226007),(21.839318,47.240839),(21.844589,47.249934),(21.856061,47.285745),(21.862159,47.297424),(21.900813,47.335742),(21.919003,47.349669),(21.936986,47.357162),(21.981531,47.366102),(22.001582,47.393827),(22.000238,47.427184),(21.991453,47.461807),(21.988869,47.492942),(22.007886,47.517411),(22.037445,47.539322),(22.09956,47.570948),(22.148549,47.579345),(22.154177,47.582213),(22.162089,47.586244),(22.16736,47.593789),(22.167608,47.594862),(22.169117,47.601385),(22.16984,47.608775),(22.172837,47.615389),(22.197642,47.639315),(22.200743,47.647945),(22.204153,47.666291),(22.207874,47.673732),(22.215212,47.679933),(22.232162,47.688253),(22.23981,47.693472),(22.261721,47.715848),(22.27309,47.723755),(22.29159,47.730705),(22.309366,47.735046),(22.322079,47.735873),(22.368278,47.73117),(22.382644,47.732023),(22.395873,47.735692),(22.407345,47.743082),(22.423675,47.782563),(22.454371,47.787394),(22.528475,47.761039),(22.562994,47.757215),(22.601235,47.760936),(22.637719,47.771555),(22.666967,47.78879),(22.691669,47.8107),(22.703864,47.817186),(22.724225,47.82349),(22.745826,47.824989),(22.75182,47.827676),(22.760295,47.838916),(22.758331,47.846228),(22.753267,47.852687),(22.752854,47.86124),(22.763602,47.874753),(22.779622,47.882298),(22.819723,47.892323),(22.836053,47.902452),(22.861167,47.933819),(22.877601,47.946739),(22.897858,47.950976),(22.915841,47.959193),(22.924213,47.972732),(22.915738,47.992989),(22.924109,48.004823),(22.939302,48.00565),(22.957079,48.00012),(22.972478,47.992886),(22.988188,47.986374),(23.004415,47.983067),(23.020331,47.984721),(23.063119,48.007458),(23.076555,48.024512),(23.098982,48.071227),(23.118619,48.091536),(23.139083,48.098125),(23.161718,48.095903),(23.231377,48.079728),(23.248637,48.071227),(23.289772,48.038206),(23.337521,48.010869),(23.360052,47.993144),(23.367286,47.991206),(23.374728,47.99056),(23.382169,47.991129),(23.390127,47.993067),(23.391574,47.993454),(23.393021,47.993583),(23.394468,47.993454),(23.396019,47.993067),(23.460821,47.971337),(23.481595,47.972163),(23.485476,47.974234),(23.488519,47.975858),(23.494307,47.980535),(23.499371,47.986219),(23.503712,47.992886),(23.514461,47.998983),(23.525623,48.00118),(23.563243,48.005753),(23.581744,48.001567),(23.646132,47.996606),(23.687267,47.987253),(23.710521,47.985083),(23.780078,47.987511),(23.796511,47.981982),(23.848394,47.949658),(23.855215,47.934233),(23.876609,47.93444),(23.977275,47.962293),(24.008798,47.961208),(24.025231,47.95325),(24.074943,47.944181),(24.094787,47.937928),(24.131167,47.914544),(24.148737,47.912115),(24.150184,47.912916),(24.209302,47.897594),(24.231006,47.897026),(24.297876,47.919789),(24.347175,47.920875),(24.386242,47.94369),(24.409187,47.952061),(24.428514,47.952526),(24.485564,47.943199),(24.542098,47.943819),(24.561632,47.940537),(24.569808,47.937289),(24.608451,47.921934),(24.633669,47.908291),(24.649275,47.895217),(24.655993,47.879301),(24.656923,47.866201),(24.661471,47.853876),(24.679144,47.84013),(24.712837,47.825919),(24.793659,47.804473),(24.808232,47.79574),(24.820738,47.784087),(24.854431,47.743133),(24.877789,47.718742),(24.896599,47.710061),(24.928858,47.713938),(24.94238,47.715563),(25.017418,47.724582),(25.079947,47.742927),(25.08005,47.743082),(25.080257,47.743133),(25.121908,47.770315),(25.218956,47.878474),(25.261744,47.898576),(25.752516,47.934595),(25.818351,47.952578),(25.870958,47.957022),(25.90124,47.965962),(25.918087,47.968158),(25.965732,47.964903),(26.029294,47.977796),(26.10253,47.978267),(26.125723,47.978416),(26.173058,47.993144),(26.18267,48.003273),(26.204788,48.037379),(26.217087,48.048024),(26.243235,48.062907),(26.255327,48.072338),(26.270727,48.093603),(26.286953,48.124712),(26.297495,48.156338),(26.296152,48.178998),(26.30349,48.212045),(26.311758,48.20972),(26.330258,48.208506),(26.347311,48.212097),(26.380488,48.223207),(26.397437,48.226205),(26.44467,48.227729),(26.461309,48.230391),(26.5874,48.249356),(26.617889,48.258968),(26.665741,48.274212),(26.688531,48.274832),(26.711475,48.261319),(26.722379,48.259769)] +Rwanda [(30.471786,-1.066837),(30.463856,-1.075127),(30.456156,-1.086082),(30.453004,-1.097348),(30.456311,-1.108097),(30.470884,-1.118122),(30.474191,-1.131764),(30.472072,-1.137656),(30.4683,-1.14334),(30.465613,-1.149334),(30.467266,-1.155329),(30.476051,-1.16122),(30.48401,-1.15998),(30.490521,-1.156466),(30.494655,-1.155329),(30.506954,-1.164217),(30.511191,-1.170418),(30.515119,-1.196257),(30.521217,-1.210829),(30.539407,-1.241008),(30.545298,-1.261369),(30.5546,-1.273461),(30.556615,-1.281626),(30.555633,-1.284727),(30.553359,-1.289067),(30.550982,-1.294959),(30.549949,-1.3024),(30.555323,-1.31842),(30.568242,-1.328135),(30.597698,-1.340331),(30.60824,-1.347772),(30.623226,-1.362035),(30.632424,-1.367616),(30.698467,-1.39211),(30.718104,-1.394901),(30.737534,-1.406683),(30.743219,-1.432831),(30.741358,-1.458876),(30.738258,-1.470658),(30.732935,-1.476446),(30.738878,-1.489469),(30.755414,-1.511586),(30.767817,-1.524815),(30.772261,-1.532463),(30.781976,-1.56843),(30.791588,-1.590961),(30.807246,-1.60326),(30.831017,-1.594165),(30.838303,-1.615352),(30.837476,-1.641087),(30.824557,-1.719946),(30.824247,-1.730694),(30.826521,-1.735862),(30.835409,-1.749504),(30.83789,-1.758703),(30.826418,-1.786195),(30.829932,-1.796737),(30.83789,-1.836838),(30.832412,-1.853788),(30.822232,-1.868774),(30.816599,-1.884173),(30.824247,-1.902053),(30.808021,-1.914766),(30.801923,-1.921277),(30.796962,-1.929338),(30.826934,-1.934093),(30.829932,-1.960551),(30.816754,-2.018739),(30.835461,-2.014708),(30.853496,-2.0237),(30.868741,-2.038996),(30.879438,-2.053465),(30.887809,-2.082507),(30.853393,-2.193818),(30.844711,-2.237847),(30.848949,-2.306266),(30.844711,-2.326627),(30.834376,-2.345334),(30.821353,-2.354739),(30.804559,-2.36218),(30.789107,-2.371069),(30.775155,-2.374479),(30.76792,-2.378613),(30.758825,-2.381094),(30.75066,-2.37913),(30.698467,-2.353395),(30.687718,-2.349985),(30.674799,-2.351742),(30.663327,-2.360733),(30.649064,-2.387605),(30.63785,-2.39701),(30.616921,-2.398147),(30.595217,-2.391946),(30.573927,-2.389259),(30.5546,-2.400628),(30.521733,-2.399387),(30.488454,-2.383781),(30.434142,-2.339236),(30.428406,-2.331381),(30.423238,-2.317325),(30.418484,-2.311847),(30.415073,-2.313088),(30.383447,-2.305543),(30.37859,-2.303062),(30.362518,-2.307817),(30.352752,-2.316912),(30.34861,-2.322352),(30.344018,-2.328384),(30.331151,-2.340269),(30.316785,-2.347608),(30.297974,-2.353705),(30.278854,-2.357633),(30.262731,-2.358356),(30.250329,-2.355566),(30.219116,-2.340373),(30.207489,-2.339236),(30.203923,-2.345954),(30.203407,-2.355359),(30.20134,-2.362387),(30.156174,-2.419024),(30.139121,-2.430807),(30.116797,-2.43153),(30.093853,-2.422642),(30.072975,-2.408792),(30.056542,-2.394426),(30.025536,-2.357736),(30.013341,-2.348331),(30.00192,-2.3443),(29.992308,-2.34399),(29.983885,-2.344817),(29.976134,-2.34368),(29.95852,-2.328533),(29.956781,-2.327038),(29.949934,-2.321149),(29.941924,-2.316602),(29.931692,-2.316912),(29.928798,-2.322493),(29.928901,-2.331795),(29.92239,-2.382954),(29.929573,-2.459849),(29.907921,-2.5354),(29.903726,-2.637947),(29.90327,-2.649088),(29.897896,-2.671102),(29.888387,-2.692909),(29.876191,-2.71358),(29.862859,-2.731667),(29.842395,-2.752441),(29.823585,-2.763499),(29.803379,-2.767324),(29.778523,-2.7666),(29.756199,-2.759882),(29.744727,-2.759985),(29.737285,-2.769287),(29.733978,-2.790268),(29.729637,-2.79957),(29.719922,-2.805461),(29.697546,-2.808251),(29.678684,-2.805357),(29.637087,-2.791629),(29.626388,-2.788097),(29.619256,-2.787684),(29.589491,-2.798433),(29.582049,-2.80298),(29.574091,-2.806081),(29.563756,-2.805667),(29.541845,-2.808561),(29.523138,-2.820447),(29.504121,-2.826855),(29.480867,-2.813729),(29.444675,-2.806989),(29.425366,-2.803394),(29.407435,-2.805461),(29.364285,-2.824168),(29.339687,-2.826441),(29.33085,-2.807424),(29.329661,-2.794919),(29.32036,-2.774145),(29.318086,-2.762569),(29.321497,-2.752131),(29.335346,-2.735181),(29.337516,-2.723812),(29.331418,-2.71141),(29.309714,-2.691049),(29.309481,-2.690127),(29.306045,-2.67658),(29.307337,-2.664797),(29.306614,-2.660147),(29.294418,-2.651052),(29.276125,-2.640613),(29.254989,-2.635549),(29.212769,-2.630278),(29.190445,-2.623456),(29.129725,-2.596998),(29.113447,-2.594621),(29.05526,-2.598445),(29.032574,-2.620666),(29.015365,-2.720711),(29.000121,-2.703658),(28.979605,-2.69353),(28.949736,-2.690326),(28.936404,-2.685055),(28.899093,-2.660663),(28.891342,-2.652705),(28.89806,-2.576327),(28.891342,-2.553073),(28.881058,-2.542634),(28.869845,-2.53726),(28.860956,-2.531162),(28.857236,-2.518346),(28.860853,-2.505221),(28.878216,-2.489718),(28.874702,-2.477522),(28.864574,-2.459435),(28.860853,-2.439592),(28.858838,-2.418198),(28.866331,-2.391946),(28.880387,-2.379854),(28.907258,-2.370552),(28.928136,-2.364454),(28.945447,-2.354222),(28.959658,-2.339753),(28.971234,-2.321666),(28.978779,-2.306783),(28.982189,-2.296034),(28.983378,-2.287353),(28.993661,-2.277741),(29.002136,-2.274744),(29.03092,-2.275674),(29.075413,-2.263892),(29.10983,-2.23671),(29.134841,-2.197746),(29.150551,-2.15041),(29.156339,-2.108656),(29.154272,-2.072689),(29.12771,-1.915696),(29.12554,-1.879109),(29.130501,-1.843349),(29.149311,-1.799321),(29.18664,-1.739618),(29.212253,-1.698655),(29.233337,-1.658657),(29.245429,-1.640984),(29.293695,-1.600986),(29.303823,-1.587861),(29.331212,-1.53143),(29.342787,-1.516547),(29.358497,-1.509933),(29.434926,-1.506832),(29.437407,-1.506212),(29.439629,-1.504765),(29.441696,-1.502595),(29.445065,-1.497287),(29.46433,-1.466938),(29.498747,-1.431074),(29.538641,-1.402342),(29.577915,-1.38839),(29.618119,-1.39056),(29.6391,-1.38901),(29.657703,-1.383945),(29.678322,-1.37237),(29.693774,-1.361208),(29.710517,-1.352526),(29.734805,-1.348185),(29.74669,-1.350872),(29.767981,-1.363792),(29.774906,-1.366272),(29.783174,-1.361414),(29.789168,-1.341674),(29.798212,-1.330925),(29.807462,-1.325138),(29.816143,-1.322554),(29.825024,-1.323881),(29.825135,-1.323897),(29.836091,-1.329478),(29.864203,-1.370303),(29.868647,-1.391283),(29.871024,-1.432418),(29.880739,-1.453605),(29.897896,-1.469625),(29.917429,-1.475206),(29.938462,-1.472932),(29.960424,-1.464767),(30.028327,-1.427147),(30.038662,-1.424977),(30.047757,-1.403169),(30.06078,-1.389733),(30.065984,-1.386945),(30.095506,-1.37113),(30.136331,-1.355213),(30.147183,-1.345085),(30.15235,-1.329892),(30.158448,-1.291135),(30.165579,-1.277492),(30.173434,-1.272841),(30.181392,-1.271497),(30.189351,-1.270877),(30.19674,-1.268707),(30.212192,-1.259509),(30.256685,-1.217237),(30.269759,-1.200494),(30.280508,-1.182407),(30.28242,-1.175793),(30.284642,-1.161427),(30.287536,-1.155432),(30.29095,-1.152621),(30.294564,-1.149644),(30.311307,-1.1421),(30.317405,-1.137035),(30.322572,-1.121843),(30.329032,-1.080501),(30.337455,-1.066239),(30.352752,-1.060761),(30.369288,-1.063241),(30.386341,-1.068202),(30.403188,-1.070373),(30.418897,-1.066445),(30.432023,-1.060554),(30.445614,-1.058694),(30.460829,-1.063428),(30.471786,-1.066837)] +Western Sahara [(-8.752562,27.661439),(-8.682385,27.661439),(-8.682385,27.567414),(-8.682385,27.473466),(-8.682385,27.379467),(-8.682385,27.285416),(-8.682282,27.27167),(-8.68223,27.232706),(-8.68223,27.172141),(-8.682075,27.093696),(-8.68192,27.000834),(-8.681817,26.897171),(-8.681662,26.786325),(-8.681558,26.671913),(-8.681455,26.55745),(-8.6813,26.446604),(-8.681145,26.342993),(-8.681042,26.250182),(-8.680938,26.171634),(-8.680861,26.111121),(-8.680861,26.072208),(-8.680809,26.058411),(-8.680809,26.013142),(-8.687656,26.000016),(-8.707216,25.995004),(-8.792043,25.995004),(-8.892863,25.994952),(-8.993581,25.994952),(-9.094246,25.994952),(-9.195015,25.994952),(-9.295733,25.994952),(-9.39645,25.994952),(-9.497168,25.994952),(-9.597885,25.994952),(-9.698654,25.994952),(-9.799371,25.994952),(-9.900037,25.994952),(-10.000806,25.994952),(-10.101523,25.994952),(-10.202292,25.994952),(-10.302958,25.994952),(-10.403675,25.994952),(-10.504445,25.994952),(-10.605162,25.994952),(-10.705879,25.994952),(-10.806597,25.994952),(-10.907314,25.994952),(-11.008083,25.994952),(-11.108749,25.994952),(-11.209518,25.994952),(-11.310235,25.994952),(-11.410953,25.994952),(-11.511722,25.994952),(-11.612439,25.994952),(-11.713208,25.994952),(-11.813822,25.994952),(-11.914591,25.994952),(-12.015308,25.9949),(-12.015308,25.919246),(-12.015308,25.843695),(-12.015308,25.768092),(-12.015308,25.69249),(-12.015308,25.616939),(-12.015308,25.541336),(-12.015308,25.465734),(-12.015308,25.390183),(-12.015308,25.31458),(-12.015308,25.238926),(-12.015308,25.163323),(-12.015308,25.087798),(-12.015308,25.012247),(-12.015308,24.936619),(-12.015308,24.861016),(-12.015308,24.785465),(-12.015308,24.709862),(-12.015308,24.63426),(-12.015308,24.558631),(-12.015308,24.48308),(-12.015308,24.407478),(-12.015308,24.331901),(-12.015308,24.256298),(-12.015308,24.180696),(-12.015308,24.105093),(-12.015308,24.029542),(-12.015308,23.95394),(-12.015308,23.878311),(-12.015308,23.802734),(-12.015308,23.727106),(-12.015308,23.651477),(-12.015308,23.575926),(-12.015308,23.495182),(-12.019339,23.460998),(-12.032723,23.444978),(-12.134578,23.419347),(-12.353892,23.322479),(-12.389911,23.312532),(-12.558376,23.290285),(-12.619432,23.270829),(-12.682219,23.230754),(-12.789938,23.161869),(-12.915098,23.082055),(-13.015247,23.018002),(-13.034342,22.995213),(-13.034342,22.995161),(-13.119892,22.88354),(-13.152293,22.820004),(-13.165497,22.752695),(-13.15498,22.688797),(-13.106353,22.560226),(-13.09333,22.495476),(-13.076833,22.245439),(-13.060335,21.995403),(-13.032093,21.581939),(-13.026177,21.49533),(-13.015247,21.333428),(-13.161724,21.333428),(-13.203091,21.333376),(-13.319854,21.333376),(-13.501419,21.333376),(-13.736909,21.333324),(-14.015496,21.333273),(-14.295598,21.333226),(-14.326485,21.333221),(-14.658971,21.333169),(-15.002258,21.333169),(-15.345544,21.333066),(-15.678082,21.333066),(-15.989019,21.333014),(-16.26771,21.332911),(-16.503148,21.332911),(-16.684636,21.332911),(-16.801425,21.332859),(-16.842817,21.332859),(-16.958831,21.332859),(-16.968339,21.324591),(-16.985703,21.237826),(-17.004926,21.141915),(-17.047378,21.0274),(-17.054019,20.995464),(-17.077428,20.904513),(-17.081175,20.874748),(-17.056874,20.766913),(-17.068349,20.792467),(-17.100209,20.837592),(-17.104644,20.862494),(-17.101389,20.876166),(-17.092275,20.899888),(-17.090403,20.914008),(-17.090403,20.961819),(-17.086293,20.979315),(-17.06786,21.030911),(-17.026763,21.328925),(-17.017445,21.365058),(-17.015248,21.379828),(-17.013743,21.419971),(-16.950149,21.429753),(-16.729956,21.469802),(-16.580043,21.48055),(-16.189886,21.48055),(-16.040024,21.500084),(-15.919876,21.500084),(-15.749964,21.490317),(-15.609818,21.469802),(-15.45993,21.450268),(-15.289992,21.450268),(-15.149872,21.440501),(-14.970167,21.440501),(-14.839813,21.450268),(-14.749974,21.500084),(-14.669875,21.599665),(-14.640109,21.679763),(-14.609827,21.750069),(-14.620085,21.820375),(-14.629852,21.860424),(-14.580036,21.91024),(-14.519988,21.990338),(-14.459914,22.040103),(-14.439915,22.080152),(-14.379841,22.120201),(-14.310052,22.190507),(-14.270003,22.240297),(-14.220187,22.309647),(-14.209955,22.370186),(-14.189904,22.450259),(-14.189904,22.589914),(-14.169906,22.759852),(-14.140088,22.870181),(-14.120089,22.960047),(-14.100065,23.099676),(-14.039991,23.33992),(-14.019992,23.410252),(-13.979943,23.519599),(-13.930127,23.620187),(-13.890129,23.690493),(-13.839797,23.750076),(-13.769982,23.790125),(-13.660118,23.830123),(-13.580045,23.870198),(-13.479948,23.910221),(-13.390108,23.940504),(-13.31001,23.980553),(-13.279753,24.019594),(-13.229963,24.0899),(-13.160122,24.219815),(-13.120099,24.299862),(-13.060025,24.400476),(-12.990184,24.4698),(-12.94688,24.496748),(-12.946879,24.496749),(-12.910137,24.51959),(-12.819781,24.570388),(-12.709943,24.629971),(-12.629845,24.679761),(-12.56003,24.730533),(-12.499982,24.7696),(-12.430141,24.830165),(-12.399884,24.879955),(-12.359835,24.969795),(-12.310019,25.110432),(-12.26997,25.259803),(-12.229946,25.42),(-12.200155,25.51958),(-12.169873,25.639728),(-12.129849,25.730549),(-12.100058,25.830156),(-12.080059,25.870205),(-12.080059,25.919969),(-12.060009,25.990301),(-12.055823,25.99583),(-12.055823,25.99583),(-12.029752,26.03035),(-11.959911,26.049884),(-11.879864,26.070399),(-11.753877,26.086006),(-11.717239,26.103576),(-11.698222,26.162177),(-11.683546,26.212975),(-11.63621,26.294985),(-11.582983,26.360408),(-11.55221,26.400457),(-11.510688,26.469807),(-11.469709,26.519597),(-11.398912,26.583081),(-11.3369,26.632897),(-11.315868,26.683644),(-11.315868,26.744208),(-11.36031,26.793043),(-11.391574,26.882908),(-11.262641,26.910219),(-11.149366,26.940501),(-11.045859,26.969802),(-10.921835,27.009825),(-10.829076,27.009825),(-10.756781,27.019592),(-10.653273,27.000058),(-10.550282,26.990292),(-10.477986,26.960035),(-10.353963,26.900478),(-10.250455,26.860429),(-10.188443,26.860429),(-10.122039,26.879962),(-10.065867,26.908281),(-10.031709,26.910219),(-9.979929,26.889729),(-9.899365,26.84968),(-9.816864,26.84968),(-9.734362,26.860429),(-9.672351,26.910219),(-9.568843,26.990292),(-9.486315,27.049875),(-9.412056,27.08796),(-9.352008,27.097727),(-9.284622,27.097727),(-9.207469,27.099691),(-9.083446,27.089924),(-9.000919,27.089924),(-8.888109,27.103566),(-8.793903,27.12018),(-8.752872,27.150463),(-8.752872,27.190486),(-8.773387,27.250069),(-8.795841,27.307688),(-8.801706,27.360424),(-8.788012,27.416054),(-8.773387,27.46003),(-8.783619,27.530362),(-8.81292,27.613354),(-8.818449,27.659398),(-8.817035,27.661464),(-8.817034,27.661465),(-8.816537,27.661465),(-8.752562,27.661439)] +Scarborough Reef [(117.753887,15.154369),(117.755692,15.151887),(117.753887,15.150082),(117.751856,15.151887),(117.753887,15.154369)] +South Sudan [(33.96912,9.838341),(33.904886,9.7107),(33.883905,9.619853),(33.877704,9.543424),(33.881425,9.499215),(33.888711,9.470818),(33.892019,9.464281),(33.894809,9.459475),(33.897755,9.456582),(33.900855,9.45529),(34.070698,9.454592),(34.083096,9.205117),(34.097473,8.915836),(34.11185,8.626555),(34.107251,8.601531),(34.103169,8.579322),(34.090249,8.556507),(34.069579,8.533615),(33.970774,8.445377),(33.95031,8.433207),(33.931706,8.428143),(33.875172,8.427936),(33.840859,8.423983),(33.824116,8.419487),(33.808096,8.412614),(33.797658,8.405612),(33.756213,8.370136),(33.751872,8.368793),(33.74102,8.367087),(33.695545,8.372875),(33.671309,8.400289),(33.651672,8.434499),(33.620407,8.460699),(33.600099,8.463955),(33.585371,8.458115),(33.57116,8.450131),(33.552143,8.446824),(33.537053,8.453206),(33.521964,8.465324),(33.505117,8.474884),(33.484757,8.474006),(33.490338,8.466513),(33.489924,8.462921),(33.480519,8.45765),(33.413133,8.449718),(33.400162,8.452638),(33.392101,8.451862),(33.384608,8.448013),(33.370862,8.437393),(33.361353,8.434293),(33.25273,8.458167),(33.23516,8.455635),(33.206427,8.430572),(33.207358,8.426593),(33.210355,8.420779),(33.202913,8.414113),(33.187824,8.411038),(33.174078,8.404475),(33.16953,8.397421),(33.167877,8.389722),(33.16798,8.372823),(33.166843,8.368276),(33.161882,8.361506),(33.161159,8.356106),(33.163329,8.352954),(33.172321,8.34652),(33.174078,8.343058),(33.171804,8.330888),(33.163123,8.312052),(33.161159,8.304585),(33.164363,8.292777),(33.171391,8.283113),(33.178419,8.275672),(33.185757,8.26451),(33.194852,8.259239),(33.208288,8.253683),(33.206893,8.240738),(33.199865,8.235519),(33.190511,8.232419),(33.181623,8.225726),(33.173975,8.21459),(33.169944,8.205495),(33.16829,8.195392),(33.16798,8.181362),(33.171081,8.175962),(33.184723,8.166247),(33.187824,8.160898),(33.185137,8.14108),(33.177282,8.127102),(33.164776,8.117051),(33.147516,8.109067),(33.117544,8.104158),(33.11341,8.099093),(33.111343,8.090644),(33.106589,8.08049),(33.100594,8.071033),(33.043853,8.013465),(33.031141,7.996309),(33.026077,7.986284),(33.021633,7.965251),(33.016775,7.958327),(33.012021,7.953314),(33.007569,7.944058),(33.006801,7.942462),(32.993572,7.928148),(32.9898,7.917244),(33.015018,7.850633),(33.023493,7.835078),(33.040753,7.824846),(33.044629,7.816423),(33.047677,7.807277),(33.051295,7.801127),(33.058323,7.797975),(33.085401,7.794978),(33.107519,7.785211),(33.120851,7.783299),(33.126949,7.791567),(33.132117,7.793944),(33.164518,7.801127),(33.172941,7.799628),(33.201467,7.788156),(33.233919,7.783195),(33.242394,7.780715),(33.257794,7.767434),(33.273503,7.749192),(33.29159,7.733069),(33.347142,7.718961),(33.359803,7.719272),(33.384401,7.735446),(33.393289,7.739735),(33.436491,7.748572),(33.462329,7.749502),(33.479537,7.743146),(33.488477,7.73617),(33.506823,7.73095),(33.516796,7.726093),(33.526511,7.717101),(33.540361,7.698911),(33.550851,7.691315),(33.572297,7.685217),(33.637202,7.691315),(33.647744,7.688627),(33.675029,7.670851),(33.706552,7.661859),(33.71606,7.657156),(33.729445,7.642119),(33.761071,7.598142),(33.811507,7.560987),(33.821429,7.558403),(33.842099,7.555922),(33.852538,7.553545),(33.882407,7.536079),(34.006534,7.409936),(34.02369,7.382445),(34.030615,7.3487),(34.031132,7.255372),(34.033612,7.250256),(34.04002,7.247259),(34.085909,7.211499),(34.113194,7.177548),(34.132417,7.163388),(34.151124,7.167471),(34.167764,7.175377),(34.181407,7.167212),(34.190915,7.149539),(34.195773,7.129023),(34.195773,7.09774),(34.195773,7.086959),(34.198253,7.064376),(34.206005,7.054506),(34.213756,7.051974),(34.219957,7.046134),(34.229879,7.03337),(34.270807,7.003398),(34.275665,6.997403),(34.280729,6.980092),(34.287653,6.975286),(34.294475,6.972237),(34.297575,6.968568),(34.439169,6.934875),(34.503661,6.89002),(34.512343,6.876842),(34.519061,6.861649),(34.523298,6.844183),(34.524745,6.824572),(34.522575,6.821781),(34.513273,6.815296),(34.511102,6.814314),(34.512136,6.808268),(34.516683,6.798062),(34.517924,6.793824),(34.524745,6.752871),(34.53632,6.743078),(34.553994,6.739254),(34.596679,6.739202),(34.618486,6.736541),(34.635539,6.729823),(34.703545,6.684916),(34.709643,6.674012),(34.714501,6.655667),(34.726593,6.641947),(34.733518,6.637606),(34.743543,6.596808),(34.753878,6.556423),(34.776099,6.499449),(34.784264,6.44183),(34.792739,6.421676),(34.832633,6.353541),(34.839041,6.327599),(34.839764,6.268688),(34.844725,6.248689),(34.879969,6.187634),(34.898882,6.13867),(34.915522,6.119705),(34.934436,6.102368),(34.951489,6.08118),(34.959447,6.061724),(34.967964,6.008131),(34.969782,5.996689),(34.95924,5.975502),(34.955726,5.964211),(34.955313,5.952558),(34.960377,5.941706),(34.97681,5.924032),(34.979911,5.912844),(34.977741,5.898659),(34.974537,5.887239),(34.972676,5.876257),(34.974433,5.863106),(34.984355,5.841014),(35.06528,5.726447),(35.079543,5.699782),(35.088225,5.64175),(35.098663,5.622474),(35.143312,5.58966),(35.22341,5.542996),(35.261961,5.511887),(35.269299,5.491785),(35.27364,5.479873),(35.267645,5.468556),(35.258964,5.458143),(35.251832,5.447369),(35.250695,5.435147),(35.254623,5.425923),(35.287489,5.374092),(35.302372,5.357374),(35.320769,5.348719),(35.344953,5.352362),(35.367484,5.368046),(35.408205,5.412565),(35.430219,5.427215),(35.448203,5.430755),(35.469287,5.430755),(35.490164,5.428042),(35.508044,5.423417),(35.530782,5.410084),(35.57388,5.375332),(35.598168,5.368743),(35.621939,5.373782),(35.639819,5.382076),(35.658319,5.386417),(35.683641,5.379595),(35.749373,5.339158),(35.80415,5.318023),(35.809111,5.309109),(35.782033,5.26986),(35.775315,5.24658),(35.778415,5.22715),(35.798259,5.189271),(35.807147,5.165267),(35.807354,5.144674),(35.799189,5.124624),(35.760949,5.076332),(35.755884,5.063439),(35.751647,4.854356),(35.760018,4.805728),(35.784513,4.764181),(35.920835,4.619332),(35.856536,4.619603),(35.781222,4.619922),(35.778439,4.678338),(35.739402,4.681127),(35.711518,4.661608),(35.705939,4.619962),(35.705846,4.619447),(35.700365,4.589111),(35.61214,4.619497),(35.610641,4.620014),(35.562607,4.707137),(35.52218,4.780461),(35.570836,4.904313),(35.49564,4.926429),(35.396117,4.926429),(35.433715,5.003836),(35.411598,5.030376),(35.333563,4.987281),(35.263419,4.948545),(35.245726,4.98172),(35.176189,4.955564),(35.094298,4.924761),(35.00272,4.890314),(34.920829,4.859511),(34.844751,4.830895),(34.763589,4.800366),(34.666277,4.76498),(34.598159,4.73092),(34.529156,4.696419),(34.459674,4.660609),(34.381188,4.620158),(34.280109,4.520061),(34.179133,4.419912),(34.078157,4.319841),(33.977078,4.219692),(33.896049,4.138353),(33.813677,4.056033),(33.701901,3.944076),(33.606196,3.848087),(33.532609,3.774293),(33.527716,3.771431),(33.490648,3.749746),(33.447343,3.744372),(33.286526,3.752537),(33.19542,3.757059),(33.164466,3.763053),(33.143486,3.774086),(33.01724,3.87718),(32.997241,3.885526),(32.979568,3.879196),(32.9189,3.83416),(32.840352,3.794291),(32.756429,3.769022),(32.599281,3.756283),(32.415571,3.741297),(32.371801,3.731065),(32.187782,3.61916),(32.175948,3.605595),(32.174863,3.59265),(32.179203,3.556864),(32.178997,3.541361),(32.175929,3.527234),(32.174552,3.520897),(32.16799,3.512242),(32.155846,3.511776),(32.093007,3.524463),(32.076161,3.53317),(32.060864,3.548958),(32.054226,3.559572),(32.041537,3.57986),(32.030168,3.585932),(32.022236,3.58642),(31.943662,3.591255),(31.93002,3.59836),(31.923095,3.615284),(31.920046,3.661302),(31.916274,3.680267),(31.901908,3.704297),(31.830697,3.783879),(31.80703,3.803722),(31.801107,3.806472),(31.780985,3.815815),(31.777884,3.816435),(31.775714,3.810699),(31.696132,3.721273),(31.68683,3.712824),(31.668537,3.70502),(31.564771,3.689802),(31.547201,3.680991),(31.535522,3.666444),(31.53452,3.665563),(31.523739,3.656083),(31.505446,3.659855),(31.377702,3.729308),(31.29502,3.774189),(31.255745,3.786669),(31.214818,3.792354),(31.167585,3.792405),(31.141489,3.785119),(31.104408,3.756175),(31.077668,3.735303),(31.068677,3.731737),(31.04966,3.727991),(31.040358,3.724218),(31.009559,3.699775),(30.995968,3.693522),(30.985788,3.692127),(30.965996,3.692618),(30.955505,3.689001),(30.944447,3.679286),(30.939382,3.668408),(30.936282,3.656858),(30.931734,3.645102),(30.865692,3.548958),(30.843781,3.505911),(30.839543,3.490202),(30.827658,3.511105),(30.837683,3.562678),(30.823214,3.580429),(30.792105,3.592702),(30.779082,3.602598),(30.772261,3.617558),(30.76916,3.651845),(30.765129,3.661716),(30.746939,3.674867),(30.731333,3.663498),(30.714642,3.64381),(30.693351,3.63195),(30.665394,3.632053),(30.653767,3.630606),(30.636455,3.624095),(30.604932,3.60668),(30.592427,3.603528),(30.572635,3.601047),(30.562248,3.601358),(30.553463,3.60451),(30.543024,3.612907),(30.543438,3.617868),(30.549329,3.624095),(30.55491,3.636394),(30.562248,3.675332),(30.562868,3.694866),(30.53889,3.84155),(30.525247,3.867543),(30.515532,3.87085),(30.505507,3.869765),(30.495482,3.867078),(30.48587,3.865579),(30.465716,3.866096),(30.456828,3.867595),(30.418949,3.879713),(30.33792,3.927875),(30.270948,3.94945),(30.205887,3.95038),(30.189351,3.95609),(30.182116,3.965521),(30.180462,3.97565),(30.180359,3.986218),(30.178085,3.997096),(30.171574,4.00818),(30.147493,4.036654),(30.138501,4.059702),(30.133023,4.082801),(30.122688,4.102464),(30.099795,4.115099),(30.057782,4.123651),(30.0429,4.133108),(30.027913,4.15445),(30.004762,4.19928),(29.989363,4.21778),(29.966005,4.23181),(29.954171,4.233825),(29.942647,4.233774),(29.932157,4.236151),(29.924147,4.245582),(29.923217,4.257752),(29.929315,4.268371),(29.93686,4.278319),(29.940115,4.288344),(29.930348,4.308653),(29.908489,4.329194),(29.882703,4.344025),(29.860689,4.347281),(29.814852,4.346764),(29.787825,4.368804),(29.776198,4.405624),(29.776766,4.449342),(29.785654,4.479366),(29.786998,4.489675),(29.785448,4.498564),(29.778523,4.5151),(29.777696,4.523859),(29.783691,4.533833),(29.788295,4.539366),(29.793302,4.545383),(29.796713,4.556028),(29.784621,4.563288),(29.774492,4.5675),(29.751755,4.581272),(29.74514,4.583907),(29.722919,4.578197),(29.715323,4.57967),(29.700802,4.5883),(29.671863,4.613983),(29.660287,4.622122),(29.618533,4.641578),(29.606751,4.643904),(29.576675,4.644446),(29.546392,4.657365),(29.535024,4.660699),(29.528822,4.659872),(29.513268,4.652146),(29.508462,4.65535),(29.498127,4.665608),(29.494096,4.668295),(29.472599,4.672197),(29.457612,4.669535),(29.449241,4.657055),(29.44676,4.622122),(29.44366,4.604707),(29.44459,4.594475),(29.44273,4.583442),(29.423919,4.566053),(29.417305,4.555485),(29.410897,4.532283),(29.402629,4.512077),(29.390226,4.493758),(29.33886,4.449549),(29.328938,4.434924),(29.318706,4.411076),(29.303927,4.387149),(29.28739,4.383584),(29.267443,4.387873),(29.242845,4.387356),(29.23158,4.375548),(29.228686,4.356712),(29.221296,4.340692),(29.19613,4.337075),(29.173495,4.348004),(29.10983,4.412367),(29.098564,4.420532),(29.058877,4.437689),(29.055983,4.4365),(29.053193,4.450789),(29.042341,4.455336),(28.994075,4.487453),(28.98622,4.495928),(28.925552,4.480813),(28.903641,4.478591),(28.856202,4.482467),(28.825713,4.478384),(28.815274,4.478281),(28.789953,4.48859),(28.785095,4.507995),(28.783648,4.530371),(28.769179,4.549775),(28.755433,4.553987),(28.746855,4.54931),(28.738173,4.540887),(28.72453,4.533988),(28.704067,4.533988),(28.695178,4.532593),(28.653734,4.452701),(28.638644,4.432082),(28.623658,4.422367),(28.58242,4.412626),(28.570535,4.405107),(28.566711,4.394126),(28.564282,4.382602),(28.557306,4.373533),(28.54821,4.37082),(28.538495,4.371827),(28.52878,4.373843),(28.519272,4.374411),(28.496844,4.369011),(28.482426,4.358986),(28.443927,4.308498),(28.425427,4.290824),(28.404137,4.277828),(28.381502,4.275296),(28.357421,4.282866),(28.349101,4.292349),(28.345846,4.306379),(28.336854,4.327489),(28.303161,4.352242),(28.261045,4.350382),(28.216965,4.342036),(28.177587,4.347229),(28.158725,4.360794),(28.140225,4.37932),(28.112371,4.414641),(28.108341,4.433994),(28.101726,4.442133),(28.085551,4.443322),(28.076301,4.437689),(28.059765,4.420067),(28.04974,4.419137),(28.019044,4.462752),(28.014186,4.472209),(28.011241,4.480141),(28.009587,4.488383),(28.008915,4.499081),(28.012119,4.521766),(28.01708,4.539052),(28.014031,4.550033),(27.96251,4.557449),(27.951244,4.55595),(27.944526,4.557294),(27.934294,4.568172),(27.92923,4.569981),(27.920342,4.565278),(27.916104,4.562152),(27.917861,4.560756),(27.917035,4.558431),(27.916414,4.553573),(27.914037,4.54931),(27.907939,4.54869),(27.89099,4.555847),(27.885512,4.556674),(27.856935,4.552462),(27.849132,4.553212),(27.83766,4.559981),(27.819469,4.579567),(27.809238,4.58799),(27.801383,4.590574),(27.776888,4.595741),(27.772444,4.595819),(27.765209,4.612071),(27.760765,4.635997),(27.758801,4.677157),(27.766863,4.735449),(27.763142,4.757101),(27.759215,4.766273),(27.7526,4.777668),(27.744229,4.787848),(27.734823,4.793197),(27.725832,4.792784),(27.706505,4.787435),(27.699063,4.787435),(27.685938,4.797899),(27.679736,4.814488),(27.671882,4.855906),(27.658756,4.879652),(27.640979,4.890943),(27.552716,4.900529),(27.532562,4.907583),(27.514578,4.92244),(27.509204,4.932439),(27.505018,4.953859),(27.501349,4.96329),(27.492823,4.973031),(27.461558,4.99688),(27.45453,4.999799),(27.447864,5.003468),(27.441818,5.007964),(27.43634,5.013158),(27.443058,5.05778),(27.441301,5.070725),(27.431173,5.083618),(27.402131,5.104496),(27.385801,5.143847),(27.358516,5.166766),(27.30131,5.205187),(27.280898,5.23056),(27.264465,5.260145),(27.2378,5.32319),(27.233665,5.33828),(27.228239,5.387605),(27.220126,5.413082),(27.218059,5.42551),(27.220126,5.440883),(27.260744,5.550257),(27.258884,5.559972),(27.261054,5.577593),(27.257127,5.586068),(27.247515,5.592605),(27.240073,5.591985),(27.234596,5.588833),(27.231082,5.587593),(27.227309,5.586714),(27.222607,5.584363),(27.217336,5.585397),(27.211341,5.594879),(27.210669,5.601623),(27.215165,5.616144),(27.216716,5.633456),(27.219196,5.639993),(27.218369,5.645315),(27.201109,5.656968),(27.196407,5.661464),(27.194288,5.667304),(27.193823,5.676321),(27.190774,5.691824),(27.182351,5.707456),(27.170413,5.72035),(27.156254,5.727481),(27.136307,5.734018),(27.131449,5.741459),(27.130933,5.752131),(27.123801,5.768745),(27.11481,5.775282),(27.072745,5.791224),(27.063547,5.790862),(27.045356,5.784919),(27.036055,5.785126),(27.029543,5.78988),(27.021999,5.805099),(27.003499,5.819284),(26.99182,5.847706),(26.981071,5.859204),(26.937456,5.848507),(26.916475,5.849644),(26.903763,5.866982),(26.894255,5.889667),(26.882059,5.891941),(26.865316,5.885973),(26.842165,5.884267),(26.81891,5.894628),(26.810849,5.912379),(26.805061,5.957183),(26.794364,5.970489),(26.776329,5.981884),(26.705016,6.009789),(26.634322,6.006482),(26.602179,6.010616),(26.543578,6.030847),(26.527972,6.043172),(26.51805,6.061156),(26.509885,6.082679),(26.498827,6.099836),(26.48105,6.104951),(26.440639,6.076995),(26.424826,6.072447),(26.421312,6.09366),(26.42927,6.113091),(26.4456,6.130221),(26.46534,6.144303),(26.48353,6.154457),(26.500067,6.167971),(26.509472,6.186394),(26.508955,6.205462),(26.495829,6.221146),(26.4795,6.225073),(26.464927,6.224402),(26.455625,6.230474),(26.455315,6.254451),(26.452008,6.28029),(26.436195,6.29171),(26.394647,6.300547),(26.375837,6.312587),(26.351755,6.344368),(26.335219,6.360595),(26.315789,6.371576),(26.300699,6.377829),(26.28964,6.387208),(26.282819,6.407853),(26.285093,6.425888),(26.290674,6.444672),(26.289124,6.459426),(26.27021,6.465653),(26.277031,6.477358),(26.286436,6.484179),(26.296462,6.489527),(26.30504,6.496917),(26.324367,6.537199),(26.356096,6.579496),(26.372323,6.609804),(26.379867,6.619778),(26.379224,6.631362),(26.378007,6.65329),(26.329741,6.680575),(26.270623,6.702486),(26.236207,6.72003),(26.219464,6.737523),(26.178743,6.765919),(26.147634,6.804702),(26.131821,6.81173),(26.113734,6.816458),(26.091203,6.830334),(26.080971,6.842348),(26.077354,6.85333),(26.0757,6.864647),(26.071566,6.877462),(26.071152,6.88356),(26.073116,6.88971),(26.073633,6.895136),(26.069189,6.899063),(26.063401,6.899063),(26.05689,6.89741),(26.050585,6.896686),(26.045418,6.899683),(26.035806,6.922266),(26.032292,6.974097),(26.026091,6.99668),(25.981132,7.000297),(25.969453,7.003553),(25.966766,7.009857),(25.966249,7.017454),(25.960461,7.024482),(25.950436,7.028564),(25.930386,7.03151),(25.920257,7.034145),(25.888735,7.05187),(25.884084,7.061069),(25.881707,7.079827),(25.877469,7.087734),(25.860726,7.095537),(25.815767,7.099774),(25.800781,7.104942),(25.791686,7.121117),(25.791583,7.134398),(25.786209,7.142666),(25.7613,7.143751),(25.750242,7.146542),(25.734429,7.162406),(25.724507,7.166695),(25.705077,7.166385),(25.697015,7.168607),(25.672727,7.187831),(25.65402,7.195376),(25.592422,7.211241),(25.576609,7.219819),(25.53165,7.260695),(25.516768,7.269945),(25.500335,7.272787),(25.481163,7.266173),(25.455118,7.278213),(25.416154,7.307772),(25.360033,7.335574),(25.346804,7.345031),(25.335952,7.359604),(25.330577,7.374125),(25.32417,7.402908),(25.316211,7.417223),(25.3097,7.422029),(25.292957,7.427196),(25.285102,7.431589),(25.279211,7.438358),(25.269599,7.454223),(25.263295,7.461044),(25.249962,7.469984),(25.190431,7.501197),(25.169037,7.551168),(25.164593,7.567343),(25.165213,7.5799),(25.186504,7.600106),(25.252546,7.62243),(25.274974,7.641964),(25.279418,7.659482),(25.276421,7.674261),(25.270633,7.688162),(25.266809,7.703097),(25.270633,7.746143),(25.269909,7.760768),(25.264535,7.777718),(25.249652,7.804331),(25.23942,7.835957),(25.229705,7.851615),(25.216889,7.864069),(25.191568,7.872389),(25.18547,7.877918),(25.180509,7.884016),(25.173171,7.888564),(25.148573,7.892594),(25.134414,7.892543),(25.103408,7.885773),(25.089559,7.884895),(25.059173,7.896108),(25.029304,7.918846),(24.981245,7.972331),(24.972666,7.976982),(24.964812,7.982615),(24.958094,7.989178),(24.952616,7.996567),(24.950549,8.014396),(24.930085,8.035454),(24.927811,8.070956),(24.917993,8.087027),(24.832107,8.16573),(24.800171,8.180277),(24.742293,8.18684),(24.710564,8.204307),(24.69041,8.206632),(24.670876,8.206839),(24.614859,8.217148),(24.544682,8.206115),(24.51285,8.207149),(24.481327,8.226657),(24.471508,8.22893),(24.464274,8.233194),(24.458899,8.239757),(24.454869,8.248671),(24.431097,8.271408),(24.396578,8.267817),(24.332085,8.245725),(24.326814,8.248567),(24.310278,8.261564),(24.302733,8.26544),(24.295498,8.266525),(24.281029,8.266525),(24.263186,8.268505),(24.257051,8.269186),(24.222428,8.277196),(24.206615,8.283268),(24.17995,8.297712),(24.152872,8.317891),(24.131374,8.343058),(24.121556,8.372307),(24.125173,8.404889),(24.137162,8.438866),(24.193179,8.532426),(24.203204,8.543459),(24.243719,8.570176),(24.25054,8.579632),(24.245579,8.591802),(24.218397,8.613041),(24.211266,8.627071),(24.21509,8.64136),(24.233487,8.667767),(24.235761,8.682003),(24.217674,8.691512),(24.180467,8.690711),(24.170328,8.689327),(24.174782,8.695646),(24.176953,8.709857),(24.182999,8.717919),(24.240566,8.761534),(24.270849,8.775719),(24.380093,8.844216),(24.402882,8.848893),(24.493833,8.858349),(24.542874,8.874653),(24.552795,8.880079),(24.558377,8.886746),(24.558377,8.993354),(24.559307,8.999865),(24.565353,9.014851),(24.655993,9.167297),(24.659869,9.176986),(24.660954,9.182283),(24.680178,9.373357),(24.686999,9.391366),(24.694957,9.402916),(24.723948,9.429219),(24.785236,9.497509),(24.792522,9.520402),(24.794383,9.532184),(24.792677,9.798369),(24.796398,9.818859),(24.799809,9.825215),(24.803685,9.829169),(24.807302,9.830047),(24.816759,9.830745),(24.827611,9.832683),(24.836292,9.836636),(24.844819,9.841674),(24.879287,9.869915),(24.913859,9.890715),(24.926933,9.90521),(24.954373,9.942237),(24.967861,9.955957),(24.976284,9.967351),(24.984965,9.985593),(24.990702,10.00306),(25.016901,10.056752),(25.027754,10.086155),(25.028994,10.092047),(25.029304,10.098248),(25.028684,10.103906),(25.025583,10.114164),(25.017367,10.133),(25.015816,10.138039),(25.013646,10.149072),(25.014421,10.157366),(25.017057,10.168011),(25.067028,10.27493),(25.07695,10.286867),(25.084081,10.293223),(25.090282,10.295755),(25.105992,10.300354),(25.120564,10.30609),(25.131261,10.308287),(25.156893,10.306245),(25.168365,10.308132),(25.19255,10.317433),(25.198286,10.317588),(25.209965,10.316116),(25.216631,10.316968),(25.225623,10.320611),(25.232754,10.322317),(25.239575,10.323014),(25.251512,10.320999),(25.25699,10.319216),(25.267067,10.314798),(25.272803,10.313015),(25.278694,10.312007),(25.28474,10.311852),(25.290166,10.313093),(25.299778,10.316658),(25.305359,10.317123),(25.316211,10.315573),(25.321999,10.315651),(25.327425,10.316581),(25.346029,10.325262),(25.351145,10.326813),(25.362927,10.32813),(25.369335,10.328208),(25.381272,10.329448),(25.391504,10.332652),(25.400961,10.336993),(25.415844,10.342031),(25.427212,10.344124),(25.439305,10.345209),(25.479509,10.343814),(25.490826,10.345597),(25.503383,10.349163),(25.506484,10.349628),(25.58033,10.375311),(25.623324,10.385853),(25.629061,10.386706),(25.661358,10.387016),(25.684148,10.390685),(25.699961,10.395026),(25.705748,10.395956),(25.745901,10.394405),(25.753962,10.395336),(25.762799,10.397739),(25.78378,10.407893),(25.82848,10.419546),(25.839332,10.420554),(25.843053,10.417815),(25.886512,10.364304),(25.891628,10.355984),(25.893644,10.351333),(25.894884,10.34583),(25.90093,10.191059),(25.902791,10.185529),(25.905426,10.181266),(25.911937,10.174212),(25.919689,10.167856),(25.955707,10.146901),(25.9709,10.140312),(25.998082,10.132458),(26.000872,10.131062),(26.007229,10.125998),(26.010794,10.122691),(26.016685,10.114862),(26.076423,10.01771),(26.088206,10.002827),(26.102313,9.988163),(26.102623,9.987841),(26.179466,9.95898),(26.368163,9.739717),(26.556859,9.520454),(26.600887,9.49198),(26.625744,9.480663),(26.683621,9.476012),(26.694318,9.476942),(27.080393,9.606831),(27.33924,9.612799),(27.385129,9.60479),(27.528066,9.605358),(27.609301,9.595178),(27.615089,9.595798),(27.635915,9.601379),(27.641496,9.601947),(27.769602,9.583318),(27.868355,9.588511),(27.884788,9.591379),(27.895072,9.59541),(27.997076,9.38493),(28.04511,9.331407),(28.44383,9.327981),(28.84255,9.324556),(28.843841,9.324545),(28.831489,9.349248),(28.827372,9.38493),(28.828745,9.427474),(28.84933,9.465901),(28.913833,9.529031),(28.989476,9.58709),(29.009474,9.603239),(29.132258,9.667731),(29.252354,9.711165),(29.483089,9.761679),(29.567321,9.841364),(29.613882,9.914461),(29.615432,10.058147),(29.64587,10.081711),(29.700957,10.115017),(29.967814,10.243329),(30.012979,10.270485),(30.248779,10.121257),(30.484578,9.972028),(30.749265,9.735763),(30.765284,9.724291),(30.779082,9.719873),(30.793035,9.728012),(30.804817,9.738942),(30.824092,9.746176),(30.83696,9.749354),(30.94991,9.752446),(30.950234,9.752455),(31.164382,9.764005),(31.234817,9.792323),(31.449816,10.003279),(31.664816,10.214236),(31.774215,10.348775),(31.801965,10.376241),(31.864184,10.472127),(31.929865,10.636923),(31.942887,10.655552),(32.17848,10.853202),(32.414073,11.050851),(32.430713,11.082193),(32.435363,11.107023),(32.364153,11.240013),(32.348754,11.30758),(32.345705,11.41163),(32.359812,11.573481),(32.354852,11.675774),(32.352991,11.687376),(32.34834,11.703163),(32.34524,11.709106),(32.082207,11.999811),(32.414434,12.001271),(32.746662,12.002731),(32.748213,12.026812),(32.747592,12.039525),(32.745577,12.051126),(32.73302,12.085982),(32.725733,12.132336),(32.725268,12.145255),(32.726198,12.157941),(32.730074,12.181893),(32.730384,12.194864),(32.729712,12.201065),(32.728524,12.206853),(32.728834,12.211917),(32.731779,12.216155),(33.209218,12.210367),(33.203017,12.128098),(33.144984,11.934673),(33.146018,11.81866),(33.132427,11.686213),(33.129016,11.67549),(33.115994,11.646939),(33.104573,11.630583),(33.091447,11.614796),(33.087727,11.608853),(33.083231,11.599164),(33.082921,11.584565),(33.132504,11.213903),(33.182088,10.843241),(33.178367,10.824534),(33.174646,10.812287),(33.14824,10.766036),(33.141418,10.750818),(33.140023,10.739036),(33.15072,10.730974),(33.370603,10.650901),(33.3813,10.645785),(33.389827,10.639248),(33.468995,10.543905),(33.685545,10.367973),(33.902096,10.192041),(33.916978,10.174522),(33.961782,10.064038),(33.966794,10.047269),(33.968345,10.020811),(33.96726,10.000269),(33.956097,9.933994),(33.959818,9.904203),(33.96726,9.884514),(33.973254,9.861776),(33.973254,9.854852),(33.972376,9.848883),(33.96912,9.838341)] +Senegal [(-14.912496,16.640639),(-14.882007,16.647667),(-14.711216,16.635782),(-14.699692,16.637125),(-14.665896,16.645652),(-14.655974,16.64591),(-14.647189,16.643533),(-14.619077,16.630666),(-14.60807,16.628805),(-14.597011,16.629167),(-14.555128,16.640587),(-14.544456,16.640846),(-14.503916,16.632681),(-14.49309,16.632474),(-14.482393,16.633663),(-14.471954,16.636402),(-14.462058,16.640794),(-14.435832,16.655987),(-14.426247,16.659604),(-14.406635,16.660793),(-14.343254,16.63666),(-14.335529,16.631544),(-14.331343,16.624103),(-14.331756,16.613147),(-14.337027,16.59413),(-14.335322,16.586482),(-14.325968,16.5824),(-14.28765,16.585707),(-14.277961,16.581263),(-14.274576,16.573511),(-14.273258,16.555631),(-14.268065,16.54788),(-14.257652,16.543177),(-14.233674,16.541575),(-14.22228,16.539612),(-14.214166,16.534961),(-14.197191,16.513463),(-14.190085,16.507107),(-14.166392,16.490881),(-14.13244,16.45264),(-14.073038,16.400654),(-14.039836,16.382102),(-14.033066,16.376056),(-14.0156,16.35585),(-14.006711,16.350269),(-13.987049,16.34288),(-13.97785,16.33797),(-13.971856,16.331201),(-13.971158,16.324224),(-13.977463,16.308825),(-13.979323,16.30035),(-13.977282,16.293839),(-13.967437,16.281385),(-13.963045,16.272393),(-13.962683,16.26397),(-13.967799,16.246038),(-13.964078,16.23007),(-13.947051,16.22113),(-13.907829,16.210019),(-13.899586,16.205317),(-13.883825,16.193741),(-13.877236,16.186868),(-13.872275,16.178755),(-13.863826,16.151832),(-13.859072,16.142272),(-13.852767,16.133487),(-13.844835,16.126045),(-13.835766,16.120568),(-13.827317,16.1185),(-13.819203,16.119276),(-13.811323,16.122066),(-13.794941,16.131213),(-13.778818,16.143202),(-13.771997,16.150437),(-13.754246,16.175345),(-13.746701,16.182373),(-13.738226,16.187127),(-13.729416,16.189504),(-13.72014,16.189969),(-13.71058,16.188884),(-13.712621,16.176068),(-13.718306,16.159288),(-13.722775,16.146096),(-13.719571,16.135605),(-13.714843,16.132763),(-13.704482,16.128836),(-13.69996,16.125632),(-13.698849,16.123926),(-13.697299,16.120361),(-13.696007,16.118914),(-13.693578,16.117519),(-13.687454,16.115245),(-13.68469,16.113798),(-13.678127,16.108217),(-13.675931,16.106925),(-13.668954,16.105736),(-13.662417,16.107442),(-13.635029,16.121601),(-13.629267,16.12279),(-13.610482,16.122893),(-13.606968,16.123255),(-13.599398,16.125477),(-13.569064,16.138189),(-13.516405,16.149041),(-13.502789,16.154416),(-13.497259,16.156069),(-13.491549,16.156276),(-13.484934,16.154984),(-13.4831,16.141031),(-13.499869,16.110646),(-13.501703,16.095143),(-13.491549,16.088425),(-13.455091,16.102222),(-13.440028,16.101861),(-13.435067,16.096538),(-13.427031,16.08305),(-13.422096,16.077211),(-13.394578,16.059279),(-13.388558,16.052096),(-13.386052,16.044396),(-13.385044,16.026878),(-13.383674,16.019178),(-13.369774,15.985485),(-13.36334,15.975098),(-13.355795,15.965538),(-13.34701,15.956753),(-13.321766,15.93815),(-13.315927,15.93045),(-13.31373,15.92213),(-13.314351,15.913603),(-13.318175,15.896705),(-13.318175,15.888489),(-13.31603,15.881771),(-13.311767,15.875776),(-13.293654,15.855312),(-13.284766,15.839913),(-13.27996,15.82286),(-13.279676,15.803533),(-13.281898,15.795109),(-13.285231,15.786634),(-13.287453,15.778159),(-13.286135,15.769633),(-13.280968,15.762812),(-13.273965,15.757489),(-13.258669,15.748807),(-13.250659,15.742761),(-13.243941,15.735785),(-13.232547,15.71961),(-13.228258,15.71129),(-13.227121,15.703952),(-13.228878,15.696614),(-13.243993,15.673721),(-13.247662,15.665608),(-13.248747,15.65672),(-13.2473,15.648297),(-13.237844,15.62344),(-13.222806,15.623854),(-13.192808,15.62897),(-13.178235,15.628194),(-13.171052,15.625352),(-13.152552,15.612407),(-13.145239,15.609539),(-13.122218,15.603493),(-13.109712,15.596413),(-13.099015,15.586879),(-13.091806,15.575123),(-13.089455,15.561041),(-13.095087,15.523421),(-13.094958,15.514713),(-13.093098,15.506212),(-13.089584,15.49704),(-13.083845,15.49275),(-13.05323,15.485102),(-13.038889,15.486885),(-13.023774,15.495954),(-13.010545,15.50629),(-12.995843,15.514222),(-12.980185,15.516289),(-12.96432,15.509158),(-12.958016,15.501742),(-12.954941,15.493061),(-12.95091,15.465414),(-12.947603,15.458618),(-12.937552,15.445777),(-12.933056,15.438284),(-12.93117,15.430532),(-12.931015,15.397046),(-12.927217,15.380742),(-12.918974,15.365368),(-12.90683,15.352682),(-12.847273,15.313278),(-12.834535,15.30023),(-12.828049,15.283874),(-12.83345,15.269999),(-12.850038,15.26739),(-12.884196,15.270826),(-12.894376,15.263359),(-12.888356,15.250879),(-12.865489,15.228684),(-12.856782,15.221992),(-12.847893,15.218943),(-12.838333,15.218762),(-12.816965,15.223077),(-12.806397,15.223077),(-12.79632,15.220287),(-12.787225,15.214163),(-12.78198,15.20729),(-12.779474,15.199616),(-12.779267,15.191399),(-12.784667,15.166026),(-12.783995,15.158146),(-12.780921,15.149076),(-12.779758,15.146389),(-12.754566,15.13856),(-12.746639,15.131136),(-12.717049,15.10342),(-12.690306,15.092387),(-12.689585,15.092479),(-12.679273,15.093783),(-12.647647,15.103162),(-12.632273,15.105436),(-12.622946,15.102258),(-12.615065,15.094609),(-12.602146,15.078771),(-12.547059,15.047171),(-12.529592,15.034355),(-12.518973,15.028283),(-12.495563,15.023012),(-12.484892,15.017276),(-12.476262,15.007741),(-12.471508,14.998),(-12.448202,14.918212),(-12.447633,14.907437),(-12.433836,14.899428),(-12.400091,14.860386),(-12.382495,14.84602),(-12.319579,14.817185),(-12.26413,14.774939),(-12.256508,14.745794),(-12.236613,14.728456),(-12.230489,14.714555),(-12.222815,14.70329),(-12.207648,14.696598),(-12.191422,14.693445),(-12.180311,14.692825),(-12.185841,14.68081),(-12.190285,14.673653),(-12.192197,14.666884),(-12.18982,14.655954),(-12.182792,14.650244),(-12.172611,14.647918),(-12.165015,14.641872),(-12.165945,14.625181),(-12.171526,14.616422),(-12.191008,14.597999),(-12.198398,14.58756),(-12.200465,14.577354),(-12.201447,14.565184),(-12.204186,14.554255),(-12.211472,14.547976),(-12.230386,14.536685),(-12.236432,14.519451),(-12.234184,14.498574),(-12.222428,14.454933),(-12.21987,14.434598),(-12.22173,14.391242),(-12.208837,14.388761),(-12.115612,14.35512),(-12.108688,14.34202),(-12.113029,14.329592),(-12.127808,14.324295),(-12.119591,14.310575),(-12.10998,14.298146),(-12.097784,14.28807),(-12.058355,14.274091),(-12.044299,14.264919),(-12.03448,14.250268),(-11.997583,14.166165),(-11.995413,14.144022),(-12.002751,14.103456),(-12.02523,14.026742),(-12.025334,13.985246),(-12.015308,13.959304),(-11.99903,13.943569),(-11.980375,13.929642),(-11.962908,13.909152),(-11.956811,13.890342),(-11.956966,13.870007),(-11.962908,13.829467),(-11.978825,13.784819),(-12.012311,13.751177),(-12.097629,13.70441),(-12.083883,13.692964),(-12.070395,13.673249),(-12.049828,13.634363),(-12.037323,13.598267),(-12.015153,13.564444),(-11.996808,13.544161),(-11.939034,13.50295),(-11.932729,13.496051),(-11.923841,13.481142),(-11.918157,13.474708),(-11.907718,13.469644),(-11.898468,13.468507),(-11.890406,13.465148),(-11.883482,13.453547),(-11.885652,13.43577),(-11.899967,13.382182),(-11.897589,13.371175),(-11.888804,13.368875),(-11.862346,13.356085),(-11.854595,13.350556),(-11.850771,13.34314),(-11.844569,13.323839),(-11.840022,13.316889),(-11.828136,13.307277),(-11.822555,13.306708),(-11.817078,13.312341),(-11.775116,13.343347),(-11.772533,13.362674),(-11.76659,13.383164),(-11.756513,13.399803),(-11.741217,13.407813),(-11.726902,13.405798),(-11.719771,13.397891),(-11.714035,13.388099),(-11.70401,13.380373),(-11.694501,13.379184),(-11.674967,13.383215),(-11.649801,13.38412),(-11.645253,13.379753),(-11.646597,13.365516),(-11.643962,13.355594),(-11.632903,13.35438),(-11.620345,13.357532),(-11.613111,13.360813),(-11.613007,13.339058),(-11.605824,13.319653),(-11.581175,13.286141),(-11.55854,13.266504),(-11.554251,13.256866),(-11.555802,13.245911),(-11.568566,13.227902),(-11.572338,13.217101),(-11.569341,13.199195),(-11.559729,13.186922),(-11.547843,13.176199),(-11.538542,13.16297),(-11.538077,13.128011),(-11.533064,13.111811),(-11.515391,13.107754),(-11.501541,13.099589),(-11.489707,13.090778),(-11.477098,13.083285),(-11.46082,13.079177),(-11.450278,13.075095),(-11.451415,13.068067),(-11.456945,13.060444),(-11.45896,13.054682),(-11.445162,13.035226),(-11.43953,13.023005),(-11.435654,13.016726),(-11.431675,13.01347),(-11.422993,13.009414),(-11.424543,13.005202),(-11.430124,13.00099),(-11.433432,12.99696),(-11.433535,12.988356),(-11.435964,12.968848),(-11.438703,12.9589),(-11.423096,12.956006),(-11.411521,12.960709),(-11.404235,12.972103),(-11.401806,12.989492),(-11.393434,12.980811),(-11.388835,12.970553),(-11.386561,12.959107),(-11.384443,12.933114),(-11.387801,12.927119),(-11.394209,12.923321),(-11.402891,12.916396),(-11.407283,12.916293),(-11.413588,12.919703),(-11.420668,12.922029),(-11.427231,12.918618),(-11.427954,12.912495),(-11.423096,12.907069),(-11.417309,12.901953),(-11.415138,12.896656),(-11.419324,12.886501),(-11.424905,12.876166),(-11.428626,12.865805),(-11.425474,12.849553),(-11.427024,12.845238),(-11.430021,12.841052),(-11.432502,12.835523),(-11.432088,12.829347),(-11.428161,12.827022),(-11.423458,12.826402),(-11.420978,12.825575),(-11.419686,12.824671),(-11.416017,12.820071),(-11.411676,12.812888),(-11.408472,12.804491),(-11.406353,12.794285),(-11.405423,12.782348),(-11.407594,12.77147),(-11.41457,12.764209),(-11.41457,12.759713),(-11.404028,12.741213),(-11.402168,12.73173),(-11.410332,12.718811),(-11.424182,12.716383),(-11.437359,12.712248),(-11.447953,12.685945),(-11.455756,12.680622),(-11.461905,12.673129),(-11.460975,12.658402),(-11.457151,12.655973),(-11.449555,12.653182),(-11.441752,12.647756),(-11.436842,12.637473),(-11.436636,12.627086),(-11.441803,12.595511),(-11.440925,12.584866),(-11.438599,12.577993),(-11.437359,12.570758),(-11.43984,12.559286),(-11.460614,12.549829),(-11.467797,12.543525),(-11.456686,12.539753),(-11.449451,12.535205),(-11.437876,12.515361),(-11.429814,12.508333),(-11.430383,12.515723),(-11.42475,12.526368),(-11.416999,12.529314),(-11.410849,12.513346),(-11.408679,12.504923),(-11.402374,12.488541),(-11.400514,12.479549),(-11.392607,12.491848),(-11.390437,12.497533),(-11.377776,12.480221),(-11.379792,12.456864),(-11.386561,12.430457),(-11.388422,12.403895),(-11.416017,12.40498),(-11.481646,12.428235),(-11.515391,12.431645),(-11.601535,12.425238),(-11.643083,12.417641),(-11.720029,12.389477),(-11.757805,12.383328),(-11.839609,12.386687),(-11.860176,12.391079),(-11.920637,12.416039),(-11.921981,12.417693),(-11.923944,12.418778),(-11.930869,12.418726),(-11.93521,12.417021),(-11.946269,12.409425),(-11.984303,12.389012),(-11.997583,12.386377),(-12.018874,12.388444),(-12.07918,12.408133),(-12.103985,12.407357),(-12.121917,12.398728),(-12.155041,12.369014),(-12.192042,12.348756),(-12.36092,12.305607),(-12.377121,12.313668),(-12.405517,12.356456),(-12.423397,12.369117),(-12.466754,12.384465),(-12.48776,12.389477),(-12.505072,12.390253),(-12.521918,12.386894),(-12.541452,12.379452),(-12.570649,12.363691),(-12.57813,12.361528),(-12.579408,12.361159),(-12.593671,12.361572),(-12.597314,12.365448),(-12.598064,12.372424),(-12.603412,12.381933),(-12.63155,12.41268),(-12.648009,12.425754),(-12.667517,12.433661),(-12.688058,12.435986),(-12.752654,12.432421),(-12.773272,12.435056),(-12.779164,12.443273),(-12.783479,12.453091),(-12.799421,12.460636),(-12.829057,12.462755),(-12.838617,12.466372),(-12.849133,12.475829),(-12.851252,12.484355),(-12.84965,12.491073),(-12.849211,12.495001),(-12.874042,12.516395),(-12.913135,12.536342),(-12.949489,12.535928),(-12.966232,12.496086),(-12.969514,12.476811),(-12.981038,12.466992),(-12.997419,12.465855),(-13.015247,12.472676),(-13.034626,12.470558),(-13.051989,12.472263),(-13.066743,12.480118),(-13.078267,12.496241),(-13.082711,12.515671),(-13.079094,12.532156),(-13.064211,12.566159),(-13.060413,12.583367),(-13.059327,12.60347),(-13.063642,12.62228),(-13.076458,12.635922),(-13.091703,12.638196),(-13.108988,12.635406),(-13.127308,12.634837),(-13.145317,12.643932),(-13.154696,12.632822),(-13.162629,12.638144),(-13.169217,12.638765),(-13.176271,12.637731),(-13.185211,12.637783),(-13.197872,12.634062),(-13.201903,12.63339),(-13.20645,12.635664),(-13.21601,12.645741),(-13.22154,12.648376),(-13.229084,12.647808),(-13.246008,12.643157),(-13.25469,12.641813),(-13.263398,12.643209),(-13.275722,12.651064),(-13.284146,12.653337),(-13.292931,12.652717),(-13.322877,12.646516),(-13.327709,12.644914),(-13.330034,12.642072),(-13.332773,12.639643),(-13.338613,12.63923),(-13.343444,12.640987),(-13.352049,12.646981),(-13.356648,12.648893),(-13.359801,12.649737),(-13.404758,12.661761),(-13.728279,12.673388),(-14.082753,12.674835),(-14.343108,12.675897),(-14.437305,12.676282),(-14.791728,12.67778),(-14.87216,12.678109),(-15.146228,12.679227),(-15.195114,12.679434),(-15.223795,12.675196),(-15.249736,12.663621),(-15.307821,12.622693),(-15.368644,12.595356),(-15.421731,12.557122),(-15.424609,12.555049),(-15.677049,12.439294),(-15.711517,12.432214),(-15.883964,12.442182),(-15.893883,12.442756),(-15.973258,12.437226),(-15.992482,12.440689),(-16.05501,12.461204),(-16.090512,12.464305),(-16.166063,12.451437),(-16.172832,12.448544),(-16.177173,12.445236),(-16.181876,12.443376),(-16.190092,12.444771),(-16.211693,12.453143),(-16.22239,12.455055),(-16.23288,12.452884),(-16.30192,12.416194),(-16.382019,12.373819),(-16.412301,12.361727),(-16.462686,12.361314),(-16.514879,12.34855),(-16.533327,12.347826),(-16.668874,12.356715),(-16.705616,12.348033),(-16.728437,12.332531),(-16.735015,12.34516),(-16.739735,12.358385),(-16.74413,12.378852),(-16.750478,12.385647),(-16.765492,12.395982),(-16.788482,12.417955),(-16.798736,12.430894),(-16.802968,12.443793),(-16.802968,12.485419),(-16.800771,12.494452),(-16.790924,12.503241),(-16.788686,12.512397),(-16.781361,12.522935),(-16.731679,12.552069),(-16.709869,12.552802),(-16.678822,12.550238),(-16.645375,12.570746),(-16.634674,12.579495),(-16.628977,12.587633),(-16.624623,12.596015),(-16.618031,12.605455),(-16.579742,12.632799),(-16.56135,12.611802),(-16.54719,12.573879),(-16.533315,12.565334),(-16.532704,12.580878),(-16.52245,12.593085),(-16.50475,12.598049),(-16.485097,12.593736),(-16.451568,12.575019),(-16.421457,12.566881),(-16.388336,12.551581),(-16.370961,12.550238),(-16.351308,12.559516),(-16.32726,12.58869),(-16.30956,12.598049),(-16.286285,12.597073),(-16.266469,12.590033),(-16.246693,12.587958),(-16.223866,12.601752),(-16.212229,12.60635),(-16.204457,12.597602),(-16.198598,12.584906),(-16.19286,12.577582),(-16.11498,12.606106),(-16.097076,12.610256),(-16.07311,12.611721),(-16.057607,12.616197),(-16.044667,12.625474),(-16.029775,12.632961),(-16.007883,12.632148),(-15.990346,12.62287),(-15.963857,12.60224),(-15.947987,12.58983),(-15.939605,12.580634),(-15.927968,12.578599),(-15.863881,12.577582),(-15.857737,12.573188),(-15.844797,12.559882),(-15.839996,12.557074),(-15.831166,12.558254),(-15.805531,12.564521),(-15.794057,12.571479),(-15.782948,12.584662),(-15.768788,12.592597),(-15.747874,12.583726),(-15.742421,12.588324),(-15.736073,12.591376),(-15.729604,12.591498),(-15.715932,12.581773),(-15.710113,12.58275),(-15.704986,12.585191),(-15.699452,12.583726),(-15.69164,12.574897),(-15.684926,12.557929),(-15.679555,12.550238),(-15.673085,12.54442),(-15.665924,12.540188),(-15.65689,12.537584),(-15.644765,12.537258),(-15.633412,12.539537),(-15.587717,12.55801),(-15.569407,12.576321),(-15.538686,12.615424),(-15.527252,12.623725),(-15.517079,12.628852),(-15.509836,12.63581),(-15.507069,12.649563),(-15.512807,12.655666),(-15.523752,12.660346),(-15.529856,12.665758),(-15.521311,12.673774),(-15.531077,12.696438),(-15.540191,12.726874),(-15.543446,12.758043),(-15.534901,12.783026),(-15.523346,12.789862),(-15.509023,12.790351),(-15.494008,12.789049),(-15.480336,12.790473),(-15.46642,12.796454),(-15.456939,12.803656),(-15.450673,12.812812),(-15.446156,12.824612),(-15.425608,12.804999),(-15.406809,12.799709),(-15.394032,12.810248),(-15.391591,12.838202),(-15.407053,12.822333),(-15.421783,12.822821),(-15.436879,12.829291),(-15.453033,12.831448),(-15.468129,12.824897),(-15.492787,12.807115),(-15.510732,12.803453),(-15.520863,12.803412),(-15.535878,12.801337),(-15.549469,12.794338),(-15.555409,12.779608),(-15.555409,12.721584),(-15.544097,12.684068),(-15.542348,12.673774),(-15.541737,12.657457),(-15.54247,12.6494),(-15.545481,12.642727),(-15.569692,12.62226),(-15.577382,12.612494),(-15.627756,12.567613),(-15.641021,12.559475),(-15.652903,12.558905),(-15.663319,12.563463),(-15.672109,12.570746),(-15.666412,12.600653),(-15.696767,12.614163),(-15.76769,12.625393),(-15.815826,12.595364),(-15.833485,12.591254),(-15.836903,12.594428),(-15.841298,12.601467),(-15.8485,12.608547),(-15.860463,12.611721),(-15.87267,12.609565),(-15.889556,12.600165),(-15.901723,12.598049),(-15.913319,12.601223),(-15.928375,12.608873),(-15.953277,12.625393),(-15.954457,12.630316),(-15.953196,12.637397),(-15.952707,12.643744),(-15.956451,12.64643),(-15.969716,12.648179),(-15.976674,12.650214),(-15.981191,12.652655),(-15.987457,12.660956),(-16.001088,12.687445),(-16.00475,12.690823),(-16.009348,12.692694),(-16.013173,12.696194),(-16.016957,12.717515),(-16.022125,12.72899),(-16.02831,12.72899),(-16.02831,12.721584),(-16.029775,12.717475),(-16.040517,12.696967),(-16.045155,12.690497),(-16.048899,12.656399),(-16.076812,12.638983),(-16.117747,12.632148),(-16.128326,12.627672),(-16.148915,12.614447),(-16.155019,12.611721),(-16.165598,12.61286),(-16.189809,12.619127),(-16.22761,12.619127),(-16.23884,12.616523),(-16.257924,12.608222),(-16.268625,12.605455),(-16.28067,12.605455),(-16.312978,12.611721),(-16.323842,12.609565),(-16.337758,12.600165),(-16.346791,12.598049),(-16.350209,12.593329),(-16.355133,12.582587),(-16.361969,12.571234),(-16.370961,12.564521),(-16.411977,12.577582),(-16.44518,12.596137),(-16.460683,12.608873),(-16.467193,12.62226),(-16.471181,12.624579),(-16.480336,12.627387),(-16.489573,12.631822),(-16.494496,12.638983),(-16.492828,12.648912),(-16.48648,12.657782),(-16.477284,12.66413),(-16.467193,12.666327),(-16.467193,12.673774),(-16.482574,12.67414),(-16.492299,12.681708),(-16.497914,12.693834),(-16.501332,12.707913),(-16.508168,12.625393),(-16.515696,12.625393),(-16.52892,12.642768),(-16.565663,12.673896),(-16.570221,12.69359),(-16.581939,12.684394),(-16.58967,12.673285),(-16.598785,12.664008),(-16.614613,12.660102),(-16.626576,12.662543),(-16.634674,12.669379),(-16.638661,12.679999),(-16.637929,12.69359),(-16.623769,12.719713),(-16.603831,12.739325),(-16.590728,12.76203),(-16.596913,12.797309),(-16.601389,12.770209),(-16.603749,12.762519),(-16.60912,12.75373),(-16.613759,12.749416),(-16.61852,12.746527),(-16.638417,12.728502),(-16.646881,12.718207),(-16.651031,12.705268),(-16.652252,12.684027),(-16.64509,12.648586),(-16.647206,12.632229),(-16.677317,12.619574),(-16.721059,12.583726),(-16.754628,12.572211),(-16.773101,12.582953),(-16.780873,12.608832),(-16.782541,12.642727),(-16.777089,12.678046),(-16.76122,12.713202),(-16.735463,12.732896),(-16.700551,12.721584),(-16.698964,12.736396),(-16.713246,12.747301),(-16.733957,12.75137),(-16.751536,12.745429),(-16.772125,12.720649),(-16.783559,12.712592),(-16.796213,12.715318),(-16.790273,12.723456),(-16.788238,12.732082),(-16.790273,12.740546),(-16.796213,12.748847),(-16.774485,12.778551),(-16.770131,12.793362),(-16.775054,12.81094),(-16.782541,12.81094),(-16.787221,12.799872),(-16.794057,12.794989),(-16.800282,12.798814),(-16.802968,12.814032),(-16.800526,12.825995),(-16.794545,12.838772),(-16.75886,12.890774),(-16.755238,12.903469),(-16.756256,12.916246),(-16.760976,12.939683),(-16.762074,12.951158),(-16.759836,12.972073),(-16.749989,13.013617),(-16.747792,13.040269),(-16.749338,13.056627),(-16.753651,13.065009),(-16.752125,13.088039),(-16.748508,13.099227),(-16.742152,13.107392),(-16.726339,13.122637),(-16.723186,13.132249),(-16.708407,13.156692),(-16.673525,13.164314),(-16.630014,13.1639),(-16.465218,13.162428),(-16.313289,13.161084),(-16.092062,13.15912),(-15.961734,13.157984),(-15.897441,13.157399),(-15.870784,13.157157),(-15.833318,13.156847),(-15.8266,13.161678),(-15.82474,13.232914),(-15.824367,13.248512),(-15.822673,13.319421),(-15.818694,13.333528),(-15.807118,13.339781),(-15.737407,13.346344),(-15.6925,13.360348),(-15.679891,13.360658),(-15.612453,13.354225),(-15.596123,13.355827),(-15.566048,13.365671),(-15.542948,13.377996),(-15.519539,13.3866),(-15.488326,13.385256),(-15.379237,13.362519),(-15.342392,13.36257),(-15.309836,13.368436),(-15.277073,13.380296),(-15.248341,13.398977),(-15.227774,13.425176),(-15.221728,13.452823),(-15.217955,13.51468),(-15.203951,13.536901),(-15.181331,13.559843),(-15.160491,13.580981),(-15.13765,13.589973),(-15.110158,13.57248),(-15.065251,13.531268),(-15.01559,13.496051),(-15.015435,13.495999),(-15.015229,13.495844),(-15.015074,13.495741),(-14.949703,13.463081),(-14.915907,13.454425),(-14.877614,13.451376),(-14.862576,13.447061),(-14.829142,13.427011),(-14.810797,13.421172),(-14.790333,13.417348),(-14.779636,13.410888),(-14.759482,13.38337),(-14.731577,13.359005),(-14.698142,13.345181),(-14.661607,13.340918),(-14.624555,13.345181),(-14.592154,13.35314),(-14.580733,13.34916),(-14.552109,13.323094),(-14.542854,13.314666),(-14.529574,13.307277),(-14.515104,13.303168),(-14.483633,13.301928),(-14.470326,13.298259),(-14.459139,13.286916),(-14.45149,13.276865),(-14.442034,13.268545),(-14.43144,13.26144),(-14.394982,13.242965),(-14.368834,13.235705),(-14.341781,13.233638),(-14.284911,13.238547),(-14.230625,13.228574),(-14.201687,13.229555),(-14.179827,13.240123),(-14.131794,13.275573),(-14.116808,13.282162),(-14.099496,13.281955),(-14.056579,13.297174),(-14.016272,13.297639),(-13.976119,13.308207),(-13.900568,13.314563),(-13.851036,13.33575),(-13.822562,13.378203),(-13.818713,13.429362),(-13.84269,13.476646),(-13.852793,13.484811),(-13.875479,13.497911),(-13.882504,13.503782),(-13.8846,13.505533),(-13.889793,13.513957),(-13.896175,13.532922),(-13.901343,13.541629),(-13.918086,13.554988),(-13.94209,13.566925),(-13.967489,13.575581),(-13.988495,13.579146),(-14.001905,13.577028),(-14.022266,13.565323),(-14.034022,13.560207),(-14.044461,13.558605),(-14.06185,13.560052),(-14.072599,13.55969),(-14.092882,13.554729),(-14.139132,13.531552),(-14.196829,13.518788),(-14.215794,13.510753),(-14.271217,13.476956),(-14.329947,13.456441),(-14.347285,13.452358),(-14.365553,13.454839),(-14.389582,13.465872),(-14.462135,13.516656),(-14.470275,13.522354),(-14.480378,13.533129),(-14.486863,13.546539),(-14.500221,13.589973),(-14.50973,13.609093),(-14.523243,13.625655),(-14.542596,13.640822),(-14.585539,13.660459),(-14.626674,13.663508),(-14.667188,13.652889),(-14.728579,13.619325),(-14.74093,13.615449),(-14.754934,13.620384),(-14.796017,13.644698),(-14.802942,13.65232),(-14.822372,13.7172),(-14.831312,13.735623),(-14.843973,13.752676),(-14.860314,13.765595),(-14.879268,13.780581),(-14.915803,13.792441),(-15.016779,13.796885),(-15.07631,13.818951),(-15.097704,13.819984),(-15.17062,13.793784),(-15.245964,13.746733),(-15.267255,13.741798),(-15.27573,13.748051),(-15.295108,13.773191),(-15.304462,13.781873),(-15.347766,13.788643),(-15.394069,13.771512),(-15.43634,13.741178),(-15.467501,13.708286),(-15.478611,13.691258),(-15.488946,13.670329),(-15.496801,13.648341),(-15.49803,13.641522),(-15.50047,13.627981),(-15.502486,13.588267),(-15.518195,13.5831),(-15.567133,13.583255),(-15.629196,13.583513),(-15.691363,13.58372),(-15.753426,13.583978),(-15.815593,13.584185),(-15.877708,13.584443),(-15.939772,13.58465),(-16.001938,13.584908),(-16.064054,13.585115),(-16.085383,13.585168),(-16.126117,13.58527),(-16.188232,13.585528),(-16.250295,13.585735),(-16.312462,13.585994),(-16.374577,13.5862),(-16.436641,13.586459),(-16.498756,13.586665),(-16.561399,13.586914),(-16.561513,13.587104),(-16.57136,13.601793),(-16.576405,13.61225),(-16.575754,13.640326),(-16.558665,13.655911),(-16.533518,13.668606),(-16.508168,13.687974),(-16.513499,13.690863),(-16.523793,13.698391),(-16.529286,13.700995),(-16.516591,13.712836),(-16.507232,13.728095),(-16.508901,13.74022),(-16.529286,13.742621),(-16.526601,13.72663),(-16.531484,13.707261),(-16.542104,13.693671),(-16.556549,13.69477),(-16.56371,13.673774),(-16.579254,13.659573),(-16.598866,13.654202),(-16.618031,13.660061),(-16.635569,13.678046),(-16.640004,13.696479),(-16.631703,13.735785),(-16.62975,13.760484),(-16.627105,13.770453),(-16.618031,13.783596),(-16.582509,13.824693),(-16.576405,13.838813),(-16.570546,13.83511),(-16.554921,13.827948),(-16.549143,13.82453),(-16.551381,13.829088),(-16.556549,13.845649),(-16.52184,13.851793),(-16.520131,13.832017),(-16.512929,13.8133),(-16.501576,13.801988),(-16.48705,13.804633),(-16.494618,13.82746),(-16.496327,13.852729),(-16.5006,13.872707),(-16.515696,13.879788),(-16.510365,13.893297),(-16.488678,13.986396),(-16.48705,14.002631),(-16.508901,13.971381),(-16.518056,13.95185),(-16.52595,13.910468),(-16.536204,13.885728),(-16.549428,13.869289),(-16.562815,13.872952),(-16.570221,13.872952),(-16.58023,13.859524),(-16.59789,13.854315),(-16.618642,13.85163),(-16.637929,13.845649),(-16.648671,13.836859),(-16.652252,13.828559),(-16.65392,13.820054),(-16.659006,13.810858),(-16.664459,13.805976),(-16.675933,13.799547),(-16.682525,13.794094),(-16.692494,13.775702),(-16.700063,13.769029),(-16.710194,13.773627),(-16.713368,13.783352),(-16.71345,13.795722),(-16.715321,13.806342),(-16.724477,13.810858),(-16.737213,13.819648),(-16.742421,13.839423),(-16.741078,13.860419),(-16.73412,13.872952),(-16.740224,13.886623),(-16.744456,13.902167),(-16.747792,13.934394),(-16.746816,13.951361),(-16.743398,13.961086),(-16.737213,13.967678),(-16.714223,13.985582),(-16.702504,13.989976),(-16.689687,13.990546),(-16.660268,13.98725),(-16.646311,13.982978),(-16.63679,13.974921),(-16.637929,13.961656),(-16.623931,13.973944),(-16.612904,13.988715),(-16.598988,13.996812),(-16.576405,13.988959),(-16.576772,14.010972),(-16.568918,14.020819),(-16.556264,14.026923),(-16.542348,14.03734),(-16.554799,14.033108),(-16.568349,14.030341),(-16.580963,14.032782),(-16.590728,14.043606),(-16.545522,14.07099),(-16.529286,14.085191),(-16.503326,14.116278),(-16.489125,14.128241),(-16.457021,14.137356),(-16.441477,14.156562),(-16.429351,14.160956),(-16.42101,14.157131),(-16.412994,14.149807),(-16.404693,14.145413),(-16.394887,14.150377),(-16.388824,14.154853),(-16.372629,14.162421),(-16.364735,14.167792),(-16.427724,14.170111),(-16.454742,14.180162),(-16.452952,14.20185),(-16.468739,14.193834),(-16.474599,14.179389),(-16.471506,14.164252),(-16.460357,14.15412),(-16.472768,14.147366),(-16.483062,14.148139),(-16.493072,14.151842),(-16.50475,14.15412),(-16.513173,14.151028),(-16.516754,14.143459),(-16.518788,14.134263),(-16.52184,14.126166),(-16.547515,14.081855),(-16.556549,14.071519),(-16.566803,14.066962),(-16.58845,14.061957),(-16.600331,14.054185),(-16.60912,14.043199),(-16.621571,14.019965),(-16.631703,14.010077),(-16.654164,14.002753),(-16.675404,14.006903),(-16.697011,14.014228),(-16.721059,14.016303),(-16.697581,14.05744),(-16.696848,14.064683),(-16.680002,14.069403),(-16.652252,14.099514),(-16.665639,14.095649),(-16.678578,14.076117),(-16.689687,14.071519),(-16.711781,14.070868),(-16.72053,14.068915),(-16.727895,14.064683),(-16.716135,14.051337),(-16.717112,14.042385),(-16.73412,14.023139),(-16.73705,14.015448),(-16.739613,14.001125),(-16.7447,13.992743),(-16.764556,13.970608),(-16.76887,13.961656),(-16.773427,13.93358),(-16.76887,13.838813),(-16.775054,13.838813),(-16.780995,14.030748),(-16.786,14.059719),(-16.802561,14.107856),(-16.82079,14.143459),(-16.829701,14.15412),(-16.842763,14.160061),(-16.868804,14.165758),(-16.878733,14.174547),(-16.883901,14.188951),(-16.892405,14.242865),(-16.898915,14.259955),(-16.906972,14.272528),(-16.925893,14.291246),(-16.93456,14.295885),(-16.941151,14.297268),(-16.945465,14.301418),(-16.947011,14.314521),(-16.94579,14.324774),(-16.940745,14.344428),(-16.939565,14.355862),(-16.944447,14.372382),(-16.956532,14.390123),(-16.987945,14.421047),(-17.059478,14.453925),(-17.070465,14.465399),(-17.076161,14.478583),(-17.11148,14.530219),(-17.137847,14.599026),(-17.178212,14.653144),(-17.206939,14.6789),(-17.22411,14.690416),(-17.243764,14.699286),(-17.265452,14.702826),(-17.281646,14.707261),(-17.324045,14.728909),(-17.330556,14.736314),(-17.363596,14.735907),(-17.392323,14.739325),(-17.417388,14.737698),(-17.439809,14.722073),(-17.431386,14.71247),(-17.419342,14.70897),(-17.426829,14.694403),(-17.439809,14.688463),(-17.436391,14.685289),(-17.430247,14.678046),(-17.426829,14.674872),(-17.433013,14.660549),(-17.436391,14.659573),(-17.439809,14.653754),(-17.452952,14.662055),(-17.520172,14.743069),(-17.536041,14.757392),(-17.370961,14.800279),(-17.322133,14.839016),(-17.172963,14.900824),(-17.138661,14.92772),(-16.979726,15.111884),(-16.947906,15.157864),(-16.878245,15.2331),(-16.739166,15.472398),(-16.669667,15.561835),(-16.53893,15.774359),(-16.534291,15.784369),(-16.536,15.794664),(-16.542348,15.808824),(-16.542346,15.808848),(-16.519736,15.846372),(-16.509918,15.901511),(-16.507541,16.010393),(-16.501598,16.021866),(-16.4878,16.066049),(-16.470437,16.106357),(-16.465993,16.174053),(-16.458758,16.194155),(-16.444185,16.206299),(-16.407288,16.214825),(-16.391682,16.224747),(-16.385378,16.234927),(-16.381088,16.246658),(-16.340161,16.415898),(-16.334941,16.455793),(-16.327397,16.474551),(-16.313547,16.49331),(-16.295099,16.510621),(-16.273808,16.523179),(-16.251019,16.527623),(-16.217946,16.521525),(-16.206732,16.52075),(-16.195363,16.522714),(-16.185183,16.527313),(-16.155779,16.547518),(-16.144307,16.552686),(-16.132266,16.554753),(-16.119657,16.552376),(-16.110459,16.54695),(-16.103069,16.53956),(-16.090977,16.522197),(-16.074027,16.504885),(-16.05377,16.495428),(-16.031187,16.492896),(-16.007313,16.496152),(-16.000181,16.501061),(-15.993102,16.504627),(-15.985609,16.505867),(-15.977289,16.503955),(-15.96437,16.498994),(-15.958065,16.498426),(-15.950675,16.499821),(-15.91104,16.516874),(-15.896932,16.518424),(-15.861999,16.51026),(-15.853575,16.51026),(-15.828926,16.514549),(-15.812958,16.513773),(-15.767741,16.499459),(-15.735288,16.497702),(-15.726813,16.495273),(-15.703197,16.484421),(-15.687539,16.480546),(-15.672191,16.481372),(-15.657412,16.486178),(-15.643614,16.494653),(-15.621497,16.514239),(-15.609663,16.521318),(-15.594418,16.523644),(-15.551475,16.515117),(-15.536696,16.516512),(-15.52481,16.522197),(-15.515198,16.53093),(-15.49091,16.56452),(-15.478508,16.575165),(-15.463987,16.58147),(-15.448846,16.580178),(-15.43944,16.572685),(-15.433704,16.562504),(-15.426883,16.553151),(-15.414532,16.548035),(-15.399805,16.548345),(-15.385749,16.551756),(-15.343632,16.568706),(-15.328026,16.571961),(-15.295935,16.573046),(-15.248599,16.565812),(-15.232476,16.56638),(-15.125093,16.58271),(-15.104009,16.590358),(-15.097498,16.594492),(-15.093208,16.600176),(-15.092847,16.607618),(-15.096154,16.613974),(-15.112329,16.629219),(-15.118271,16.642603),(-15.116256,16.655522),(-15.107574,16.665392),(-15.093312,16.669165),(-15.078894,16.664979),(-15.069851,16.655264),(-15.061996,16.643791),(-15.051557,16.63418),(-15.044374,16.631906),(-15.036933,16.632578),(-15.029853,16.635471),(-15.023652,16.639967),(-15.018743,16.646117),(-15.016521,16.652576),(-15.013368,16.666581),(-15.006909,16.675831),(-14.996625,16.682445),(-14.974301,16.691385),(-14.962932,16.685804),(-14.949858,16.672317),(-14.948934,16.670553),(-14.941331,16.656039),(-14.930944,16.643378),(-14.912496,16.640639)] +Serranilla Bank [(-78.637074,15.862087),(-78.640411,15.864),(-78.636871,15.867296),(-78.637074,15.862087)] +Singapore [(103.960785,1.391099),(103.985688,1.385443),(103.999522,1.380316),(104.003429,1.374172),(103.991873,1.354926),(103.974864,1.334459),(103.954356,1.318101),(103.931895,1.311469),(103.907237,1.308743),(103.887706,1.301256),(103.852712,1.277289),(103.846934,1.271918),(103.844086,1.2685),(103.838878,1.266262),(103.82602,1.264309),(103.801606,1.264797),(103.789561,1.26789),(103.784434,1.273871),(103.77589,1.287584),(103.755138,1.297105),(103.730154,1.302924),(103.708751,1.305243),(103.665294,1.304104),(103.647634,1.308417),(103.640391,1.322252),(103.644705,1.338039),(103.674571,1.380316),(103.678884,1.399237),(103.683849,1.409898),(103.695079,1.421332),(103.708344,1.429389),(103.717947,1.430976),(103.739757,1.428127),(103.762218,1.430976),(103.79005,1.444281),(103.804942,1.448635),(103.831554,1.447089),(103.857188,1.438707),(103.932465,1.401109),(103.960785,1.391099)] +San Marino [(12.42945,43.892056),(12.399581,43.903218),(12.385629,43.924534),(12.395654,43.948409),(12.411049,43.959661),(12.421389,43.967219),(12.453325,43.979053),(12.48216,43.982567),(12.489188,43.97311),(12.492392,43.956419),(12.490325,43.939159),(12.483094,43.929205),(12.48216,43.927919),(12.479576,43.9258),(12.478026,43.923216),(12.477494,43.920051),(12.478287,43.917038),(12.460456,43.895259),(12.42945,43.892056)] +Somaliland [(48.939112,11.24913),(48.939111,11.136737),(48.939111,11.024367),(48.939111,10.912022),(48.939111,10.7996),(48.939111,10.687333),(48.939111,10.574937),(48.939111,10.462567),(48.939111,10.350119),(48.939111,10.2378),(48.939111,10.12543),(48.939111,10.013033),(48.939111,9.900715),(48.939111,9.788422),(48.939111,9.676),(48.939111,9.563603),(48.939111,9.562701),(48.939111,9.451233),(48.879114,9.360308),(48.819325,9.269384),(48.759225,9.178511),(48.699229,9.087689),(48.639336,8.996661),(48.579184,8.90584),(48.519188,8.814915),(48.459243,8.723887),(48.399299,8.633118),(48.339147,8.54209),(48.279099,8.451165),(48.219155,8.360318),(48.159003,8.269419),(48.099058,8.17852),(48.039114,8.087492),(47.979169,7.996567),(47.836697,7.996516),(47.653918,7.996516),(47.52359,7.996516),(47.36608,7.996516),(47.210586,7.996516),(47.068114,7.996516),(46.97923,7.996567),(46.920526,8.025609),(46.857377,8.046745),(46.773558,8.074909),(46.689532,8.102969),(46.605713,8.131133),(46.521687,8.159245),(46.437713,8.187357),(46.353842,8.215469),(46.269816,8.243555),(46.185894,8.271641),(46.101919,8.299727),(46.018049,8.327891),(45.934126,8.356003),(45.850203,8.384115),(45.766384,8.412227),(45.682358,8.440313),(45.598436,8.468425),(45.514462,8.496537),(45.51441,8.496537),(45.426147,8.525476),(45.33809,8.554414),(45.249878,8.583276),(45.16177,8.612137),(45.073558,8.641153),(44.985553,8.67004),(44.89729,8.698928),(44.809233,8.72784),(44.721073,8.756779),(44.633017,8.785718),(44.544753,8.814605),(44.456697,8.843544),(44.368537,8.872457),(44.280377,8.901396),(44.192217,8.930283),(44.104057,8.959222),(44.023855,8.985525),(43.984788,9.008314),(43.914921,9.071489),(43.78759,9.186701),(43.698449,9.267162),(43.621502,9.336899),(43.60724,9.344625),(43.59122,9.343591),(43.566829,9.334315),(43.548225,9.336072),(43.471227,9.382012),(43.419034,9.413018),(43.406322,9.42865),(43.401981,9.447409),(43.399449,9.480947),(43.393351,9.49893),(43.370665,9.544225),(43.361518,9.553165),(43.341364,9.566394),(43.331753,9.575076),(43.325086,9.585902),(43.315578,9.607658),(43.305966,9.617554),(43.297698,9.621533),(43.270671,9.628354),(43.248812,9.652332),(43.235273,9.691787),(43.206334,9.851209),(43.187214,9.883326),(43.149852,9.899991),(43.104273,9.907923),(43.067686,9.922522),(43.039884,9.949988),(43.020764,9.996419),(43.012599,10.029286),(42.999887,10.061971),(42.981903,10.091633),(42.958235,10.115559),(42.862324,10.177158),(42.836279,10.208086),(42.808167,10.269116),(42.78946,10.333324),(42.776644,10.42461),(42.765792,10.451947),(42.750393,10.471636),(42.695202,10.524708),(42.668537,10.56623),(42.64859,10.611033),(42.647247,10.63222),(42.660269,10.641625),(42.680216,10.647672),(42.699646,10.65855),(42.711635,10.675163),(42.718973,10.694852),(42.728585,10.735496),(42.738094,10.759784),(42.749876,10.775829),(42.785636,10.804406),(42.801242,10.820788),(42.80765,10.83611),(42.811578,10.85262),(42.819432,10.872567),(42.834832,10.888406),(42.876793,10.905744),(42.893536,10.919671),(42.901185,10.936595),(42.911313,10.977367),(42.923715,10.998787),(43.188815,11.407764),(43.240733,11.48786),(43.252696,11.47309),(43.266938,11.462348),(43.288341,11.460354),(43.282725,11.498928),(43.29713,11.482245),(43.320079,11.446112),(43.33961,11.426174),(43.352387,11.419745),(43.375987,11.391588),(43.394216,11.385199),(43.413829,11.380927),(43.44337,11.359565),(43.459727,11.35106),(43.466319,11.367906),(43.478201,11.37995),(43.489431,11.380927),(43.494395,11.364732),(43.479015,11.271796),(43.488129,11.238918),(43.506358,11.20897),(43.529307,11.186591),(43.535655,11.183743),(43.551931,11.179836),(43.559093,11.176011),(43.562999,11.170315),(43.568207,11.155422),(43.583181,11.135159),(43.591645,11.107489),(43.617442,11.070787),(43.658946,10.987982),(43.755626,10.894232),(43.8296,10.802965),(43.92213,10.724189),(44.028168,10.652167),(44.097504,10.58926),(44.149587,10.559149),(44.274262,10.456732),(44.303722,10.439846),(44.347554,10.414511),(44.3892,10.397207),(44.465258,10.401481),(44.541423,10.392743),(44.586149,10.383585),(44.627329,10.390613),(44.661857,10.402411),(44.721063,10.419384),(44.750662,10.427865),(44.790324,10.423484),(44.854784,10.414529),(44.899366,10.411814),(44.962009,10.415799),(44.994151,10.442694),(44.987966,10.460395),(45.001475,10.460395),(45.111339,10.52558),(45.12672,10.531968),(45.157237,10.541083),(45.252289,10.600531),(45.320567,10.662095),(45.33725,10.670844),(45.354747,10.66885),(45.37322,10.662421),(45.392426,10.658393),(45.40919,10.659491),(45.445323,10.667792),(45.487071,10.684719),(45.516612,10.701972),(45.542979,10.721666),(45.573009,10.758124),(45.586111,10.765855),(45.662283,10.790595),(45.673106,10.79621),(45.684906,10.808905),(45.694591,10.822252),(45.706391,10.832831),(45.72462,10.837144),(45.737966,10.843573),(45.753591,10.871731),(45.769298,10.878119),(45.787364,10.877753),(45.802745,10.875312),(45.816905,10.869208),(45.831309,10.857611),(45.84018,10.844672),(45.84669,10.832261),(45.855642,10.823961),(45.872325,10.823472),(45.868175,10.841376),(45.884451,10.841213),(45.97755,10.79914),(46.012543,10.794745),(46.047618,10.785305),(46.063731,10.778795),(46.102224,10.770657),(46.137218,10.776313),(46.207367,10.79621),(46.237559,10.792426),(46.263194,10.776842),(46.30714,10.731024),(46.335134,10.709703),(46.370128,10.696845),(46.408702,10.691596),(46.447765,10.693101),(46.482432,10.701361),(46.499848,10.708482),(46.52768,10.726223),(46.56072,10.731676),(46.588715,10.743313),(46.629161,10.745063),(46.646251,10.747748),(46.659679,10.75434),(46.694102,10.781928),(46.782237,10.821723),(46.821951,10.852607),(46.865977,10.871894),(46.871837,10.878079),(46.881358,10.893134),(46.886485,10.898586),(46.893565,10.901557),(46.9074,10.903144),(46.913829,10.905463),(47.008067,10.938951),(47.082774,10.995266),(47.132335,11.035793),(47.167654,11.072089),(47.180675,11.080471),(47.226736,11.093817),(47.23878,11.101264),(47.263357,11.120795),(47.366873,11.172797),(47.386241,11.180121),(47.405935,11.184638),(47.437022,11.179836),(47.489513,11.192816),(47.522716,11.186957),(47.677745,11.107978),(47.71046,11.101264),(47.767345,11.130194),(47.892833,11.132554),(47.948253,11.125149),(48.130382,11.136664),(48.160818,11.145657),(48.173513,11.157131),(48.195811,11.186835),(48.215587,11.196234),(48.217296,11.203681),(48.2199,11.211127),(48.22934,11.214504),(48.246593,11.21426),(48.255138,11.215074),(48.273611,11.220404),(48.2942,11.222602),(48.30421,11.227525),(48.310557,11.234768),(48.313324,11.242011),(48.314952,11.24901),(48.31837,11.25552),(48.331309,11.268704),(48.342784,11.275458),(48.373057,11.282172),(48.444347,11.289252),(48.478526,11.296332),(48.506847,11.313544),(48.521983,11.319281),(48.585948,11.316962),(48.636892,11.329413),(48.654796,11.330634),(48.723888,11.315253),(48.762462,11.301011),(48.800629,11.279039),(48.888845,11.250556),(48.904063,11.247748),(48.921153,11.248033),(48.939112,11.24913)] +Somalia [(50.797864,11.989119),(50.867055,11.942891),(50.970083,11.932323),(51.029307,11.885077),(51.048839,11.878648),(51.127696,11.878648),(51.147227,11.873603),(51.181163,11.855373),(51.199718,11.851304),(51.222911,11.850775),(51.247081,11.847561),(51.267345,11.839423),(51.292698,11.833108),(51.277354,11.800605),(51.266381,11.759286),(51.249359,11.728775),(51.255708,11.681655),(51.247801,11.652391),(51.22954,11.635897),(51.212529,11.607947),(51.181245,11.578829),(51.148123,11.536038),(51.124766,11.511786),(51.12086,11.505316),(51.121918,11.494127),(51.126638,11.478827),(51.127696,11.470893),(51.125011,11.447984),(51.118419,11.426256),(51.086192,11.357164),(51.081309,11.341498),(51.079356,11.275946),(51.07252,11.233791),(51.085948,11.187974),(51.130945,11.160752),(51.17444,11.158764),(51.189504,11.138306),(51.164399,11.116767),(51.142263,11.068427),(51.131358,11.052883),(51.12379,11.038764),(51.118337,11.016913),(51.115082,10.993354),(51.124522,10.85456),(51.138194,10.676744),(51.160655,10.598456),(51.154307,10.587714),(51.131358,10.58393),(51.107432,10.576565),(51.101899,10.55858),(51.107188,10.515041),(51.102224,10.494696),(51.092296,10.482164),(51.076915,10.475816),(51.055675,10.474066),(51.035818,10.467515),(51.018321,10.452094),(51.010102,10.434027),(51.018403,10.41942),(51.038097,10.416083),(51.19044,10.446112),(51.200938,10.44477),(51.211925,10.44184),(51.220388,10.442043),(51.223888,10.449856),(51.219574,10.461005),(51.210216,10.467108),(51.200857,10.471503),(51.196544,10.477444),(51.195811,10.500312),(51.193044,10.521186),(51.186778,10.541571),(51.176117,10.562812),(51.191742,10.548977),(51.20734,10.538096),(51.220647,10.524928),(51.237966,10.515024),(51.24662,10.50909),(51.257942,10.503801),(51.280556,10.48733),(51.292532,10.480075),(51.3112,10.476055),(51.325879,10.47268),(51.335871,10.474614),(51.345875,10.480494),(51.35721,10.48374),(51.377856,10.48169),(51.395173,10.479023),(51.403077,10.456707),(51.417038,10.447485),(51.410965,10.429814),(51.397509,10.395793),(51.38502,10.391506),(51.380154,10.387339),(51.372569,10.381415),(51.37608,10.367693),(51.367419,10.367726),(51.349458,10.375002),(51.336131,10.374395),(51.320079,10.378485),(51.300831,10.372566),(51.272873,10.377905),(51.265391,10.396877),(51.26295,10.408596),(51.256602,10.420315),(51.240977,10.425605),(51.090099,10.407313),(51.017125,10.381916),(50.927389,10.327844),(50.90988,10.295635),(50.901703,10.234442),(50.912814,10.176853),(50.8838,10.101264),(50.888682,10.05565),(50.900401,10.024075),(50.901703,10.011664),(50.89975,10.000718),(50.890798,9.986029),(50.877696,9.916653),(50.881196,9.905463),(50.86964,9.884467),(50.863129,9.866034),(50.854015,9.816107),(50.840587,9.779771),(50.833263,9.768785),(50.838634,9.740912),(50.836925,9.73078),(50.831716,9.712063),(50.824474,9.651068),(50.806163,9.624457),(50.805512,9.59394),(50.812999,9.541164),(50.836762,9.477037),(50.840343,9.456122),(50.837413,9.437201),(50.830333,9.419623),(50.768321,9.319281),(50.748302,9.303534),(50.706309,9.285712),(50.689464,9.274848),(50.676768,9.259182),(50.646983,9.211371),(50.641124,9.196357),(50.649181,9.132514),(50.648448,9.110419),(50.633637,9.073188),(50.604503,9.037909),(50.494884,8.951972),(50.464122,8.920559),(50.439708,8.88817),(50.422048,8.857123),(50.40797,8.816352),(50.389822,8.733547),(50.374278,8.698879),(50.326508,8.641099),(50.319591,8.620347),(50.322602,8.55976),(50.319591,8.541815),(50.303477,8.504584),(50.290212,8.486762),(50.274913,8.479153),(50.256196,8.472561),(50.246104,8.456448),(50.239106,8.436347),(50.230154,8.41767),(50.166026,8.33336),(50.156423,8.320624),(50.141368,8.287991),(50.113048,8.19953),(50.091075,8.161038),(50.058279,8.130316),(49.929373,8.051744),(49.842052,7.962714),(49.824229,7.933905),(49.812511,7.897528),(49.803233,7.82689),(49.808604,7.815009),(49.823416,7.805325),(49.827647,7.782904),(49.825043,7.757758),(49.819347,7.739936),(49.790782,7.69953),(49.760916,7.667304),(49.752208,7.650295),(49.748302,7.606635),(49.744151,7.589057),(49.640798,7.409125),(49.586599,7.314765),(49.520518,7.239651),(49.367035,7.025702),(49.293224,6.880927),(49.247325,6.810614),(49.197927,6.67357),(49.074718,6.415269),(49.072032,6.393297),(49.074067,6.370795),(49.083507,6.329047),(49.085623,6.307359),(49.0713,6.219916),(49.036143,6.144232),(48.951491,5.99872),(48.850108,5.824449),(48.695811,5.587348),(48.646739,5.480048),(48.620128,5.443996),(48.548106,5.375067),(48.448009,5.208726),(48.328868,5.079657),(48.202403,4.908922),(48.055675,4.612942),(47.948497,4.457099),(47.840587,4.341376),(47.577973,4.059882),(47.489268,3.936347),(47.335623,3.778754),(47.206716,3.644599),(47.039806,3.469265),(47.01295,3.441067),(46.834239,3.232489),(46.700043,3.113267),(46.625743,3.023912),(46.487804,2.90884),(46.414317,2.833441),(46.351573,2.788642),(46.34962,2.780178),(46.3449,2.770087),(46.339203,2.761705),(46.334483,2.758246),(46.317638,2.751899),(46.307628,2.736029),(46.299815,2.715766),(46.289399,2.696234),(46.275401,2.685858),(46.236501,2.667629),(46.142345,2.568915),(46.13087,2.554023),(46.114513,2.523261),(46.104991,2.510565),(46.062999,2.484036),(46.047618,2.455064),(46.027029,2.438137),(45.826345,2.308824),(45.711925,2.24433),(45.605642,2.183051),(45.266205,1.987291),(45.232188,1.967678),(45.210704,1.963121),(45.199718,1.959621),(45.001475,1.86636),(44.831554,1.749701),(44.823985,1.740302),(44.812185,1.735582),(44.67628,1.6376),(44.550059,1.559068),(44.332774,1.38996),(44.221365,1.275621),(44.198416,1.265692),(44.157888,1.24079),(44.145518,1.22956),(44.1421,1.221381),(44.139659,1.211168),(44.138031,1.191596),(44.133962,1.187567),(44.115001,1.182034),(44.11085,1.17829),(44.10377,1.168362),(44.032888,1.09748),(44.012543,1.084215),(43.990977,1.078599),(43.97877,1.068671),(43.932628,1.009833),(43.819835,0.949449),(43.781912,0.921617),(43.734223,0.854967),(43.717296,0.845282),(43.703461,0.840522),(43.658946,0.804918),(43.467621,0.620551),(43.285492,0.414984),(43.184906,0.31627),(43.09018,0.223375),(42.891124,0.003079),(42.770274,-0.129327),(42.712087,-0.17669),(42.647797,-0.228936),(42.580333,-0.29754),(42.555919,-0.332127),(42.553559,-0.34238),(42.553966,-0.351251),(42.550792,-0.357599),(42.526622,-0.362726),(42.519298,-0.369317),(42.479747,-0.422052),(42.474457,-0.438653),(42.486501,-0.449395),(42.47641,-0.465997),(42.47283,-0.469903),(42.472911,-0.4638),(42.472423,-0.458673),(42.47047,-0.454034),(42.465994,-0.449395),(42.412608,-0.490981),(42.404552,-0.500909),(42.39796,-0.517348),(42.38266,-0.535252),(42.349864,-0.565606),(42.250255,-0.685642),(42.246755,-0.694268),(42.246755,-0.701918),(42.245291,-0.707452),(42.236339,-0.709568),(42.232595,-0.713067),(42.192231,-0.776137),(42.166515,-0.802667),(42.151622,-0.813897),(42.135509,-0.82171),(42.116466,-0.826267),(42.086599,-0.825616),(42.071544,-0.828709),(42.062511,-0.839288),(42.081716,-0.843438),(42.080903,-0.862888),(42.071951,-0.884454),(42.065684,-0.894464),(42.051443,-0.902032),(42.036957,-0.920017),(42.025564,-0.941583),(42.020844,-0.960056),(42.016368,-0.968032),(41.983165,-0.994073),(41.971934,-0.99977),(41.967947,-0.992852),(41.963634,-0.95086),(41.964692,-0.911554),(41.958832,-0.894464),(41.95281,-0.894464),(41.955414,-0.909601),(41.952403,-0.920831),(41.94752,-0.930841),(41.94516,-0.942966),(41.946462,-0.954767),(41.951427,-0.969415),(41.95281,-0.980401),(41.955577,-0.992934),(41.96225,-0.998956),(41.969249,-1.003188),(41.973155,-1.011163),(41.97169,-1.023614),(41.961436,-1.044122),(41.958832,-1.055841),(41.953461,-1.068617),(41.930024,-1.089939),(41.924653,-1.097101),(41.923025,-1.110121),(41.918305,-1.121026),(41.911632,-1.130955),(41.873871,-1.176039),(41.869477,-1.186212),(41.872895,-1.195489),(41.880707,-1.19492),(41.890147,-1.189386),(41.897472,-1.183201),(41.885427,-1.209649),(41.862804,-1.212335),(41.84197,-1.196954),(41.835297,-1.168878),(41.829112,-1.168878),(41.830251,-1.189223),(41.84197,-1.224867),(41.842784,-1.24391),(41.836599,-1.262302),(41.73227,-1.431085),(41.708751,-1.460056),(41.689708,-1.489516),(41.65211,-1.565118),(41.633311,-1.580336),(41.610606,-1.593194),(41.575043,-1.652602),(41.554861,-1.669692),(41.561046,-1.669692),(41.535105,-1.696283),(41.535103,-1.696269),(41.535944,-1.676312),(41.53858,-1.613699),(41.534963,-1.594785),(41.522871,-1.572771),(41.484527,-1.523162),(41.434194,-1.458049),(41.383758,-1.39304),(41.332185,-1.326378),(41.282989,-1.262816),(41.237307,-1.203905),(41.18222,-1.132695),(41.13106,-1.066445),(41.081554,-1.002573),(41.056129,-0.969604),(41.030601,-0.936738),(41.00528,-0.903768),(40.979751,-0.870798),(40.978821,-0.794834),(40.977891,-0.724347),(40.976961,-0.653861),(40.975514,-0.545237),(40.974067,-0.436716),(40.97262,-0.328299),(40.971173,-0.219675),(40.97045,-0.152186),(40.969623,-0.084697),(40.968486,-0.002738),(40.968486,0.122319),(40.968486,0.247273),(40.968486,0.37233),(40.968486,0.497283),(40.968486,0.62234),(40.968486,0.747242),(40.968486,0.872248),(40.968486,0.997201),(40.968486,1.122207),(40.968486,1.230295),(40.968486,1.247212),(40.968486,1.372191),(40.968486,1.497145),(40.968486,1.62215),(40.968486,1.747181),(40.968486,1.872135),(40.968486,1.997166),(40.968486,2.103619),(40.968486,2.210047),(40.968486,2.316501),(40.968486,2.422954),(40.968486,2.49711),(40.967142,2.631727),(40.965902,2.760608),(40.965385,2.814145),(40.979751,2.841895),(41.013961,2.875795),(41.096127,2.957082),(41.178396,3.03842),(41.260665,3.119811),(41.342727,3.201149),(41.394506,3.27515),(41.446183,3.349047),(41.497963,3.423074),(41.549639,3.497023),(41.633562,3.617093),(41.717381,3.737163),(41.801303,3.857182),(41.885019,3.977226),(41.898455,3.996915),(41.912201,4.007974),(41.917472,4.020453),(41.916645,4.051098),(41.923466,4.070554),(41.941243,4.086212),(42.011833,4.129491),(42.068367,4.174553),(42.102887,4.19189),(42.13534,4.200081),(42.221846,4.200959),(42.297294,4.201734),(42.415013,4.221707),(42.568285,4.247856),(42.718663,4.273487),(42.78977,4.285605),(42.831628,4.302322),(42.868938,4.326765),(42.870195,4.328171),(42.899634,4.361104),(42.914724,4.393299),(42.9325,4.463217),(42.945936,4.496858),(42.952551,4.507581),(42.960406,4.517374),(43.03544,4.578895),(43.119259,4.647702),(43.232792,4.701497),(43.346997,4.755654),(43.459342,4.808829),(43.528485,4.841566),(43.640519,4.867353),(43.716484,4.884793),(43.815186,4.907479),(43.845158,4.914352),(43.932284,4.945203),(43.968975,4.953962),(44.029126,4.950448),(44.081009,4.947451),(44.132789,4.94448),(44.184672,4.941431),(44.236452,4.938485),(44.288335,4.935488),(44.340115,4.932439),(44.391998,4.929468),(44.443726,4.926445),(44.495557,4.923473),(44.547441,4.920476),(44.596808,4.917643),(44.59922,4.917505),(44.651104,4.914507),(44.702883,4.911562),(44.754766,4.908565),(44.806546,4.905541),(44.858378,4.902544),(44.912586,4.899392),(44.941525,4.911484),(45.020642,4.99688),(45.0209,4.99688),(45.077744,5.059072),(45.185024,5.176248),(45.292356,5.293476),(45.399585,5.410704),(45.506865,5.527881),(45.518477,5.540564),(45.614146,5.645057),(45.721426,5.762337),(45.828706,5.879513),(45.935986,5.996689),(45.99681,6.059192),(46.057839,6.12172),(46.118818,6.184223),(46.179899,6.246726),(46.240981,6.309228),(46.302062,6.371731),(46.362937,6.43426),(46.423915,6.496736),(46.466963,6.538292),(46.488046,6.558645),(46.508406,6.578308),(46.55321,6.621457),(46.598065,6.664633),(46.618425,6.684244),(46.667001,6.731115),(46.715577,6.777985),(46.764101,6.824882),(46.812729,6.871675),(46.861408,6.918597),(46.909984,6.965467),(46.95856,7.012286),(47.007032,7.059208),(47.055608,7.106079),(47.104287,7.153001),(47.152863,7.19982),(47.201439,7.246691),(47.250118,7.293509),(47.298797,7.34038),(47.347373,7.387302),(47.395949,7.434173),(47.444525,7.481043),(47.493101,7.527914),(47.532388,7.565864),(47.541676,7.574836),(47.590252,7.621655),(47.638932,7.668525),(47.687507,7.715396),(47.736032,7.762215),(47.784659,7.809137),(47.833183,7.855956),(47.881811,7.902826),(47.930593,7.949697),(47.979169,7.996567),(48.039114,8.087492),(48.099058,8.17852),(48.159003,8.269419),(48.219155,8.360318),(48.279099,8.451165),(48.339147,8.54209),(48.399299,8.633118),(48.459243,8.723887),(48.519188,8.814915),(48.579184,8.90584),(48.639336,8.996661),(48.699229,9.087689),(48.759225,9.178511),(48.819325,9.269384),(48.879114,9.360308),(48.939111,9.451233),(48.939111,9.562701),(48.939111,9.563603),(48.939111,9.676),(48.939111,9.788422),(48.939111,9.900715),(48.939111,10.013033),(48.939111,10.12543),(48.939111,10.2378),(48.939111,10.350119),(48.939111,10.462567),(48.939111,10.574937),(48.939111,10.687333),(48.939111,10.7996),(48.939111,10.912022),(48.939111,11.024367),(48.939111,11.136737),(48.939112,11.24913),(48.939138,11.249132),(48.976817,11.25141),(49.108409,11.276597),(49.239594,11.300279),(49.278087,11.316962),(49.293305,11.337958),(49.303477,11.345445),(49.315929,11.340522),(49.32545,11.33511),(49.335704,11.334621),(49.400076,11.340522),(49.4192,11.344794),(49.435069,11.35106),(49.488617,11.381741),(49.507335,11.385199),(49.521739,11.393785),(49.544444,11.436713),(49.558604,11.453518),(49.576834,11.460028),(49.59962,11.461737),(49.644542,11.460354),(49.650076,11.462144),(49.666026,11.471137),(49.675304,11.473944),(49.686778,11.474351),(49.716319,11.46776),(49.804861,11.458401),(49.851248,11.464911),(49.880707,11.488227),(49.88852,11.487291),(49.906423,11.498725),(49.917979,11.501899),(49.921886,11.503852),(49.934418,11.512885),(49.942149,11.51557),(49.949474,11.51496),(49.956309,11.512519),(49.961111,11.509955),(49.962657,11.508734),(50.053884,11.511379),(50.07252,11.508734),(50.131521,11.539944),(50.151134,11.557929),(50.161876,11.563381),(50.197602,11.562649),(50.206554,11.566799),(50.214366,11.572659),(50.225434,11.578111),(50.268321,11.589301),(50.28891,11.602444),(50.372325,11.668931),(50.418142,11.678046),(50.437022,11.690619),(50.470388,11.727851),(50.500824,11.754828),(50.512706,11.771226),(50.517589,11.79267),(50.518891,11.815253),(50.52296,11.837958),(50.52947,11.859524),(50.538585,11.878648),(50.561209,11.907904),(50.575938,11.920966),(50.589854,11.926459),(50.602061,11.927965),(50.627452,11.940131),(50.632091,11.946763),(50.636485,11.951606),(50.641124,11.954413),(50.647146,11.954047),(50.655935,11.948432),(50.661469,11.947577),(50.682953,11.953355),(50.724864,11.971137),(50.761567,11.978746),(50.771983,11.985785),(50.797864,11.989119)] +Republic of Serbia [(19.690095,46.168398),(19.711889,46.15871),(19.772984,46.131552),(19.79045,46.129072),(19.873649,46.152992),(19.888946,46.15739),(19.92915,46.16354),(19.993125,46.159406),(20.034983,46.142973),(20.063405,46.145298),(20.088623,46.154135),(20.098442,46.154962),(20.114772,46.152223),(20.120146,46.149226),(20.130378,46.139355),(20.138026,46.136461),(20.145364,46.137082),(20.170479,46.145505),(20.188462,46.140389),(20.242826,46.108091),(20.305665,46.053572),(20.317653,46.038586),(20.338634,45.992801),(20.35393,45.976678),(20.370984,45.96779),(20.410258,45.955594),(20.429068,45.946706),(20.481674,45.912703),(20.499865,45.906656),(20.538002,45.903711),(20.556709,45.89844),(20.572108,45.887691),(20.605284,45.846143),(20.612312,45.841492),(20.629676,45.833276),(20.636704,45.827023),(20.640114,45.818703),(20.642285,45.798343),(20.64349,45.795141),(20.645902,45.788731),(20.655617,45.77731),(20.678562,45.75664),(20.68807,45.7431),(20.700059,45.735401),(20.713392,45.733334),(20.726827,45.736176),(20.739436,45.743411),(20.745328,45.754986),(20.754113,45.763564),(20.765171,45.766768),(20.77747,45.762324),(20.785739,45.752557),(20.785532,45.743411),(20.781604,45.733954),(20.779124,45.72367),(20.779951,45.671684),(20.777264,45.657524),(20.773233,45.648894),(20.762174,45.630601),(20.754423,45.605589),(20.75804,45.58926),(20.787392,45.553655),(20.800208,45.530504),(20.797624,45.516499),(20.783155,45.506061),(20.760727,45.493348),(20.767135,45.479344),(20.781604,45.472574),(20.799484,45.468544),(20.816021,45.462859),(20.830387,45.452524),(20.863047,45.418728),(20.927642,45.37749),(20.966193,45.341575),(20.981489,45.33279),(21.016668,45.321482),(21.063964,45.30628),(21.0743,45.300544),(21.082775,45.293671),(21.09156,45.288089),(21.103342,45.286074),(21.113057,45.28933),(21.12918,45.301887),(21.139412,45.303696),(21.155638,45.295169),(21.189745,45.259564),(21.206075,45.245922),(21.239251,45.229385),(21.257131,45.224114),(21.299299,45.223184),(21.405546,45.199671),(21.433761,45.188819),(21.459393,45.17404),(21.484388,45.152702),(21.493292,45.145101),(21.49784,45.131872),(21.494119,45.119314),(21.48151,45.111563),(21.469004,45.111046),(21.458566,45.107325),(21.449987,45.101021),(21.442443,45.092908),(21.443786,45.091461),(21.444406,45.08526),(21.444406,45.07787),(21.443786,45.072909),(21.440996,45.068723),(21.432521,45.061488),(21.429524,45.057303),(21.425596,45.043247),(21.425079,45.036219),(21.421875,45.031413),(21.409266,45.023971),(21.398828,45.021387),(21.3733,45.020096),(21.363378,45.01653),(21.356143,45.008572),(21.351389,44.998236),(21.353456,44.989813),(21.366995,44.987281),(21.383945,44.986661),(21.387046,44.981545),(21.384565,44.97493),(21.385185,44.969504),(21.40844,44.958342),(21.456499,44.952348),(21.48151,44.943563),(21.51634,44.933899),(21.531016,44.924649),(21.539078,44.908474),(21.536287,44.889302),(21.522128,44.880776),(21.48151,44.872611),(21.453398,44.869562),(21.395314,44.871629),(21.368545,44.86486),(21.355523,44.856591),(21.346428,44.845636),(21.342811,44.831942),(21.3598,44.826657),(21.359841,44.826644),(21.360587,44.826412),(21.378571,44.816645),(21.395934,44.790239),(21.41216,44.784813),(21.49722,44.778043),(21.558405,44.78166),(21.578042,44.777681),(21.595612,44.765951),(21.604293,44.749983),(21.610288,44.731948),(21.619693,44.713913),(21.65628,44.687661),(21.705166,44.677067),(21.756842,44.677274),(21.801697,44.683889),(21.838284,44.695206),(21.855441,44.698461),(21.871977,44.695981),(21.962411,44.662288),(21.994347,44.658567),(22.004269,44.651539),(22.032174,44.603325),(22.034243,44.596168),(22.036174,44.589489),(22.039822,44.576867),(22.045197,44.569219),(22.055739,44.562139),(22.067107,44.55723),(22.076306,44.550718),(22.086951,44.52178),(22.104314,44.509636),(22.126639,44.502659),(22.148239,44.500902),(22.172114,44.505347),(22.185136,44.515113),(22.299031,44.661668),(22.304922,44.677377),(22.319702,44.685336),(22.361146,44.692054),(22.38068,44.700528),(22.41551,44.727814),(22.426052,44.733653),(22.450547,44.732981),(22.468943,44.730191),(22.483723,44.72399),(22.553279,44.669161),(22.587489,44.649369),(22.621182,44.637432),(22.700144,44.63061),(22.714716,44.623065),(22.765153,44.58281),(22.759262,44.564671),(22.741692,44.551855),(22.719367,44.544362),(22.700144,44.54183),(22.678543,44.545551),(22.642163,44.563121),(22.621182,44.569219),(22.600305,44.569787),(22.580461,44.565498),(22.565578,44.555421),(22.55979,44.538781),(22.55669,44.52147),(22.548422,44.511703),(22.535503,44.507517),(22.500363,44.50638),(22.491061,44.50421),(22.484136,44.499766),(22.479795,44.490412),(22.477212,44.476976),(22.477005,44.463954),(22.480002,44.455789),(22.500983,44.44194),(22.505427,44.435015),(22.506357,44.427522),(22.50398,44.411709),(22.505117,44.404061),(22.522687,44.37507),(22.549352,44.348974),(22.582838,44.328406),(22.621182,44.315901),(22.662523,44.311663),(22.68154,44.305307),(22.689498,44.291716),(22.685364,44.243657),(22.690739,44.228878),(22.69164,44.228435),(22.648777,44.213995),(22.639992,44.207329),(22.624799,44.189397),(22.608573,44.175858),(22.606196,44.174566),(22.604852,44.168468),(22.605989,44.163145),(22.607953,44.159993),(22.6094,44.159941),(22.599065,44.130331),(22.597101,44.119065),(22.598134,44.109298),(22.604646,44.088163),(22.604749,44.079378),(22.592967,44.063926),(22.57519,44.061394),(22.554623,44.062428),(22.534159,44.057157),(22.522583,44.044703),(22.514935,44.030285),(22.50367,44.019898),(22.481449,44.019433),(22.465885,44.017624),(22.43432,44.013955),(22.411789,44.006927),(22.399594,43.993336),(22.39732,43.980934),(22.396803,43.951944),(22.394529,43.936337),(22.391945,43.931867),(22.382024,43.918561),(22.379026,43.913496),(22.377063,43.883524),(22.367554,43.852751),(22.354738,43.829703),(22.349467,43.807921),(22.362593,43.780843),(22.388535,43.758286),(22.389568,43.750509),(22.385848,43.733817),(22.386054,43.725498),(22.390498,43.712449),(22.396906,43.699401),(22.404865,43.687179),(22.41396,43.676663),(22.426465,43.668214),(22.455921,43.656406),(22.466256,43.64912),(22.472871,43.635942),(22.473801,43.612998),(22.481449,43.600647),(22.481759,43.599975),(22.481966,43.599459),(22.481759,43.598942),(22.481449,43.598529),(22.478142,43.594911),(22.477108,43.591294),(22.478142,43.587573),(22.481449,43.584137),(22.482689,43.581734),(22.483103,43.579279),(22.482689,43.576695),(22.481449,43.574111),(22.478658,43.569176),(22.477625,43.564164),(22.478452,43.559229),(22.490647,43.540883),(22.509354,43.493341),(22.518863,43.474247),(22.532609,43.464842),(22.565785,43.453344),(22.57271,43.44815),(22.586766,43.43443),(22.596274,43.429159),(22.606919,43.427402),(22.62852,43.428255),(22.637822,43.426369),(22.645367,43.420297),(22.656529,43.403192),(22.658926,43.401295),(22.664694,43.396732),(22.674202,43.394148),(22.693219,43.394872),(22.702934,43.394045),(22.719367,43.388671),(22.724343,43.38606),(22.73301,43.381513),(22.80453,43.328984),(22.817139,43.315497),(22.820756,43.307539),(22.823857,43.289297),(22.826958,43.28139),(22.833159,43.274647),(22.857343,43.256947),(22.883802,43.230592),(22.897754,43.220335),(22.915531,43.212247),(22.964727,43.204418),(22.981367,43.198992),(22.982902,43.187318),(22.984571,43.174627),(22.974029,43.141192),(22.955632,43.108274),(22.935271,43.085562),(22.927107,43.081144),(22.910157,43.075279),(22.901682,43.069749),(22.896721,43.062721),(22.889486,43.044376),(22.884215,43.036651),(22.842254,43.007505),(22.829025,42.993656),(22.829025,42.993501),(22.828921,42.993449),(22.828818,42.993449),(22.815796,42.989703),(22.788097,42.984897),(22.776418,42.979729),(22.76939,42.97128),(22.763189,42.958645),(22.745516,42.910069),(22.739579,42.898858),(22.738798,42.897383),(22.727015,42.886892),(22.69663,42.87741),(22.666244,42.871932),(22.5909,42.886892),(22.563615,42.884283),(22.549972,42.877358),(22.544785,42.871706),(22.544494,42.871389),(22.53757,42.868341),(22.519793,42.870356),(22.506047,42.870123),(22.497055,42.864413),(22.481449,42.84674),(22.470907,42.840125),(22.445482,42.830178),(22.436801,42.824286),(22.430446,42.817077),(22.427395,42.813615),(22.425845,42.809843),(22.429359,42.806122),(22.45313,42.763592),(22.466566,42.748529),(22.481449,42.739821),(22.482586,42.736824),(22.482896,42.733775),(22.482586,42.730675),(22.481449,42.727677),(22.468116,42.718324),(22.442072,42.681685),(22.449203,42.667965),(22.444552,42.64329),(22.441318,42.632891),(22.428842,42.592776),(22.425328,42.572855),(22.429669,42.571408),(22.481449,42.535622),(22.512145,42.519189),(22.524857,42.507665),(22.532505,42.493557),(22.532505,42.493402),(22.536536,42.47839),(22.533125,42.45759),(22.519483,42.420926),(22.508838,42.404932),(22.497572,42.399196),(22.485066,42.397155),(22.46977,42.391703),(22.454371,42.376768),(22.438454,42.340052),(22.423985,42.325893),(22.405795,42.321552),(22.364144,42.320984),(22.345023,42.313439),(22.325283,42.314318),(22.307609,42.31933),(22.29159,42.328399),(22.276914,42.341241),(22.27402,42.348476),(22.273296,42.365477),(22.268852,42.370335),(22.259757,42.369095),(22.233402,42.348889),(22.095529,42.305817),(22.060906,42.301088),(22.045407,42.302424),(22.027627,42.303956),(21.994967,42.312612),(21.941534,42.333102),(21.929028,42.335117),(21.918279,42.331345),(21.88438,42.309512),(21.877352,42.30822),(21.837354,42.308556),(21.8172,42.305145),(21.719521,42.260957),(21.706509,42.25507),(21.69204,42.242022),(21.67695,42.234943),(21.676886,42.234945),(21.65969,42.235563),(21.624654,42.242772),(21.575044,42.242022),(21.564066,42.246289),(21.553857,42.273984),(21.514893,42.317832),(21.51603,42.341939),(21.537321,42.35863),(21.596645,42.372092),(21.617419,42.386639),(21.621863,42.402167),(21.616902,42.433923),(21.618969,42.449245),(21.627858,42.460381),(21.667855,42.490095),(21.717671,42.551151),(21.727697,42.574147),(21.726766,42.577945),(21.719738,42.586678),(21.718291,42.591019),(21.720152,42.593887),(21.726973,42.596393),(21.728833,42.598305),(21.730074,42.601018),(21.735551,42.621276),(21.734725,42.624247),(21.744543,42.629647),(21.756532,42.633626),(21.767074,42.638716),(21.772758,42.647501),(21.764387,42.669619),(21.74425,42.679425),(21.738652,42.68215),(21.708886,42.687189),(21.687389,42.686827),(21.644084,42.672306),(21.629408,42.672203),(21.612665,42.680393),(21.580522,42.710211),(21.565226,42.720184),(21.542488,42.725817),(21.441823,42.736101),(21.4178,42.73557),(21.405546,42.7353),(21.388699,42.739046),(21.378674,42.744136),(21.379191,42.747004),(21.383945,42.749976),(21.387149,42.754962),(21.39056,42.770414),(21.404099,42.803978),(21.408336,42.820747),(21.408419,42.841743),(21.40844,42.846998),(21.398931,42.854569),(21.378777,42.855292),(21.346738,42.860847),(21.336403,42.865473),(21.316972,42.877616),(21.306327,42.882448),(21.294958,42.884386),(21.2716,42.884283),(21.260542,42.886556),(21.23243,42.910896),(21.226745,42.942522),(21.225298,42.973554),(21.209795,42.995878),(21.193052,42.997893),(21.17941,42.990581),(21.165354,42.985103),(21.147887,42.992622),(21.139309,43.005826),(21.124012,43.058277),(21.10851,43.081558),(21.092593,43.090678),(21.025827,43.093366),(21.005157,43.099128),(20.993431,43.104148),(20.912494,43.138805),(20.838552,43.170467),(20.832041,43.178606),(20.836071,43.179433),(20.839069,43.192455),(20.840619,43.206976),(20.839999,43.212092),(20.851471,43.219818),(20.8616,43.217518),(20.8647,43.217337),(20.855088,43.231445),(20.848474,43.238137),(20.838449,43.245863),(20.819432,43.257412),(20.809717,43.25961),(20.79442,43.263071),(20.769512,43.260849),(20.745328,43.252865),(20.666986,43.209663),(20.644869,43.203307),(20.612312,43.202274),(20.604044,43.197959),(20.597533,43.184962),(20.600117,43.173826),(20.612106,43.154938),(20.620581,43.133337),(20.626058,43.123725),(20.632053,43.117266),(20.640941,43.115276),(20.65169,43.11631),(20.661818,43.115948),(20.669157,43.109799),(20.664919,43.085407),(20.643835,43.052257),(20.617273,43.02213),(20.596396,43.007092),(20.584304,43.006911),(20.572832,43.00934),(20.562393,43.009495),(20.553401,43.002596),(20.543893,42.987248),(20.538415,42.980659),(20.530457,42.975156),(20.51113,42.970195),(20.493457,42.970195),(20.476403,42.966371),(20.459454,42.950015),(20.450979,42.922032),(20.466688,42.909501),(20.488909,42.899191),(20.494367,42.887467),(20.498831,42.877875),(20.4763,42.855525),(20.428034,42.840642),(20.345352,42.827439),(20.355171,42.86617),(20.35362,42.890975),(20.337084,42.906969),(20.275589,42.929887),(20.223189,42.957663),(20.19456,42.966836),(20.14092,42.970815),(20.129464,42.973605),(20.116942,42.976654),(20.056344,43.020796),(20.054388,43.022221),(20.019894,43.047348),(19.959742,43.07856),(19.949821,43.085924),(19.942276,43.095639),(19.936591,43.105897),(19.92915,43.113907),(19.916644,43.117059),(19.907136,43.113261),(19.883778,43.095691),(19.872203,43.090368),(19.838303,43.088353),(19.805127,43.089955),(19.781769,43.096466),(19.761202,43.108739),(19.742805,43.126516),(19.713556,43.165609),(19.705494,43.166178),(19.69733,43.160209),(19.684617,43.156721),(19.663016,43.158504),(19.618678,43.168245),(19.598111,43.176203),(19.580851,43.187804),(19.549948,43.217518),(19.547845,43.218815),(19.512431,43.240643),(19.502303,43.251935),(19.485146,43.280098),(19.473054,43.293276),(19.414039,43.338389),(19.372285,43.384226),(19.355645,43.393063),(19.218392,43.438202),(19.192244,43.454532),(19.175914,43.480887),(19.175191,43.509619),(19.195345,43.532796),(19.217462,43.532796),(19.229451,43.549746),(19.238856,43.572122),(19.252706,43.588633),(19.263661,43.590958),(19.289189,43.587935),(19.300868,43.588297),(19.31265,43.593154),(19.335801,43.606513),(19.34655,43.608838),(19.363396,43.601577),(19.38045,43.585584),(19.394609,43.566463),(19.402877,43.549643),(19.410732,43.540754),(19.41931,43.549255),(19.431816,43.57114),(19.443908,43.571864),(19.481735,43.560831),(19.48959,43.564448),(19.491761,43.568608),(19.48897,43.573181),(19.481735,43.578116),(19.476878,43.588684),(19.475638,43.602559),(19.477498,43.616977),(19.481735,43.628914),(19.507367,43.647182),(19.505713,43.67364),(19.481735,43.729218),(19.461685,43.762136),(19.359469,43.842209),(19.305932,43.904737),(19.275443,43.933263),(19.241027,43.952357),(19.229348,43.95768),(19.240717,43.965741),(19.242887,43.972821),(19.238133,43.985378),(19.238029,43.99251),(19.243507,44.002018),(19.252085,44.007496),(19.272756,44.012405),(19.287329,44.013025),(19.300558,44.009511),(19.325879,43.996592),(19.351718,43.979125),(19.364637,43.973286),(19.379106,43.973854),(19.393989,43.977058),(19.447112,43.979797),(19.50406,43.975663),(19.528554,43.977213),(19.552222,43.983415),(19.593357,44.005584),(19.61041,44.019278),(19.618885,44.035711),(19.611443,44.054521),(19.598938,44.062583),(19.589946,44.060309),(19.583848,44.054315),(19.580231,44.051524),(19.570929,44.056898),(19.554599,44.071265),(19.522043,44.08501),(19.516189,44.091194),(19.498169,44.110229),(19.482666,44.120667),(19.476361,44.127023),(19.474191,44.144903),(19.465716,44.15281),(19.459721,44.152707),(19.448456,44.144438),(19.442565,44.143198),(19.435537,44.146092),(19.424891,44.153792),(19.381173,44.177098),(19.362363,44.191206),(19.356058,44.204021),(19.353991,44.22433),(19.341589,44.245828),(19.324329,44.263966),(19.307379,44.274198),(19.295907,44.2758),(19.263661,44.270167),(19.249502,44.270736),(19.240717,44.272699),(19.220046,44.280244),(19.177155,44.286962),(19.157001,44.293577),(19.138914,44.309338),(19.116693,44.343703),(19.108942,44.36365),(19.107185,44.382718),(19.115763,44.403596),(19.129612,44.416153),(19.141394,44.430829),(19.143358,44.458218),(19.127339,44.502556),(19.129922,44.518317),(19.165269,44.526689),(19.173124,44.531443),(19.179635,44.538264),(19.185319,44.546223),(19.187283,44.553302),(19.18625,44.569322),(19.188317,44.57604),(19.193278,44.580587),(19.20413,44.585135),(19.208677,44.588391),(19.255703,44.645648),(19.270069,44.67562),(19.277614,44.684871),(19.288259,44.693035),(19.308413,44.705128),(19.318025,44.715463),(19.32836,44.733963),(19.363707,44.854628),(19.367841,44.859278),(19.373112,44.86026),(19.376626,44.862999),(19.375695,44.873128),(19.372802,44.881448),(19.368667,44.887132),(19.362776,44.891111),(19.356993,44.895869),(19.356982,44.895877),(19.353165,44.899018),(19.352958,44.898087),(19.350271,44.897002),(19.340142,44.896227),(19.33022,44.898708),(19.31017,44.91235),(19.301281,44.91235),(19.293013,44.909405),(19.283815,44.908371),(19.239476,44.915141),(19.229554,44.913745),(19.211881,44.908371),(19.201856,44.908371),(19.196895,44.913177),(19.193174,44.921549),(19.18687,44.927543),(19.174261,44.925424),(19.08455,44.878967),(19.068427,44.874833),(19.047757,44.872714),(19.015821,44.865635),(18.994323,44.894832),(18.991429,44.914934),(19.018405,44.925683),(19.031944,44.922634),(19.052098,44.906976),(19.06667,44.905684),(19.078659,44.910852),(19.087858,44.919326),(19.103567,44.93824),(19.113076,44.942426),(19.124548,44.94594),(19.131679,44.953175),(19.127649,44.968419),(19.118554,44.97555),(19.09809,44.970021),(19.087238,44.977101),(19.085171,44.987281),(19.088478,44.999477),(19.093232,45.011517),(19.095402,45.020922),(19.094266,45.031413),(19.085997,45.06092),(19.082277,45.084949),(19.079176,45.094613),(19.071528,45.107067),(19.064087,45.113578),(19.054165,45.120606),(19.046207,45.128358),(19.044863,45.137246),(19.060056,45.146858),(19.116073,45.142879),(19.137674,45.146031),(19.141705,45.162154),(19.128785,45.181068),(19.121861,45.195795),(19.143875,45.199516),(19.155761,45.194969),(19.174571,45.175797),(19.185319,45.168045),(19.204543,45.162878),(19.225937,45.161947),(19.267795,45.165823),(19.272756,45.168355),(19.275753,45.172851),(19.279474,45.177244),(19.286709,45.179517),(19.291359,45.177709),(19.299421,45.168975),(19.304279,45.166547),(19.390682,45.169337),(19.393929,45.171624),(19.405358,45.179672),(19.407838,45.203133),(19.397296,45.223287),(19.378073,45.229592),(19.363086,45.248247),(19.162065,45.285041),(19.124755,45.298115),(19.098813,45.319871),(19.096229,45.329121),(19.095402,45.340489),(19.091992,45.349998),(19.08207,45.354029),(19.040832,45.354029),(19.020988,45.357233),(19.003625,45.366121),(18.988742,45.379247),(18.975927,45.394956),(19.028637,45.412165),(19.037422,45.422293),(19.031634,45.434024),(19.012258,45.448468),(19.003005,45.455366),(18.99639,45.473815),(19.00962,45.498671),(19.017926,45.497807),(19.077212,45.491643),(19.106255,45.511642),(19.095092,45.526059),(19.082277,45.531175),(19.067807,45.533398),(19.050961,45.538927),(19.040936,45.545025),(19.036491,45.549469),(19.033391,45.554637),(19.02719,45.562595),(19.018095,45.567401),(19.009206,45.565489),(19.000628,45.561199),(18.983161,45.55474),(18.973136,45.546265),(18.960217,45.539134),(18.941717,45.538927),(18.932002,45.545541),(18.912054,45.568227),(18.90358,45.573085),(18.90699,45.581663),(18.90823,45.600422),(18.912365,45.619232),(18.924457,45.627707),(18.935412,45.633391),(18.962904,45.660108),(18.968485,45.668738),(18.962697,45.683052),(18.948125,45.692044),(18.931071,45.698917),(18.917325,45.706565),(18.908954,45.719433),(18.90482,45.749767),(18.900169,45.764908),(18.871127,45.789971),(18.863995,45.798549),(18.848699,45.809556),(18.844978,45.815706),(18.846735,45.819995),(18.850353,45.824232),(18.85242,45.830072),(18.855314,45.857357),(18.887146,45.859476),(18.899755,45.861388),(18.90699,45.867951),(18.903993,45.875702),(18.893451,45.883867),(18.872884,45.895236),(18.881979,45.902626),(18.889834,45.907897),(18.90699,45.9157),(18.901306,45.931203),(18.962697,45.927947),(18.981818,45.921849),(18.987502,45.923813),(18.988742,45.927017),(18.986469,45.931254),(18.97882,45.939781),(18.977684,45.943502),(18.978717,45.947171),(18.981818,45.950788),(19.005589,45.96257),(19.03091,45.960038),(19.048584,45.963449),(19.049721,45.993111),(19.06543,46.012025),(19.088478,46.018846),(19.111009,46.012955),(19.125788,45.993266),(19.125788,45.993111),(19.148009,45.984068),(19.235652,45.977711),(19.263454,45.981432),(19.274823,45.991612),(19.279474,46.003808),(19.286915,46.016159),(19.298315,46.022123),(19.306966,46.026649),(19.325156,46.029491),(19.362156,46.029646),(19.378899,46.033677),(19.389131,46.041532),(19.396573,46.051557),(19.404738,46.060239),(19.417243,46.064321),(19.428302,46.06551),(19.43688,46.06799),(19.453727,46.07755),(19.460858,46.084475),(19.465922,46.091968),(19.47295,46.098686),(19.499305,46.108608),(19.496722,46.116876),(19.48928,46.126023),(19.487523,46.134239),(19.501993,46.145608),(19.525247,46.156409),(19.549948,46.16416),(19.568449,46.166434),(19.589739,46.165969),(19.647824,46.173875),(19.669321,46.1731),(19.690095,46.168398)] +Suriname [(-54.170965,5.348376),(-54.19046,5.325748),(-54.269163,5.269085),(-54.311331,5.225806),(-54.320652,5.212454),(-54.332002,5.196196),(-54.343577,5.156379),(-54.350037,5.149583),(-54.365437,5.138757),(-54.369881,5.132375),(-54.37231,5.121058),(-54.375617,5.114883),(-54.430239,5.053388),(-54.448636,5.024294),(-54.454785,5.008533),(-54.457576,4.99135),(-54.448842,4.951482),(-54.450806,4.936728),(-54.455509,4.931431),(-54.482122,4.912802),(-54.486721,4.902958),(-54.484964,4.892752),(-54.47866,4.87867),(-54.47866,4.755189),(-54.475404,4.741727),(-54.467291,4.736198),(-54.457007,4.73333),(-54.447344,4.727852),(-54.435458,4.709404),(-54.435148,4.692376),(-54.438559,4.673282),(-54.437732,4.648735),(-54.425278,4.61605),(-54.423469,4.604345),(-54.423469,4.563392),(-54.428172,4.546158),(-54.447964,4.509545),(-54.450806,4.484224),(-54.433443,4.376375),(-54.402954,4.312942),(-54.394117,4.269818),(-54.393187,4.244393),(-54.399595,4.227262),(-54.41055,4.208581),(-54.406571,4.191528),(-54.394892,4.177911),(-54.38249,4.169566),(-54.3489,4.160522),(-54.338565,4.152332),(-54.334689,4.131713),(-54.337583,4.116649),(-54.351019,4.082078),(-54.355153,4.066523),(-54.353861,4.041718),(-54.344353,4.024949),(-54.310194,3.994202),(-54.30389,3.984461),(-54.293141,3.949812),(-54.286475,3.940717),(-54.272522,3.929529),(-54.265804,3.922527),(-54.241051,3.876354),(-54.222241,3.866199),(-54.218004,3.857647),(-54.214541,3.858215),(-54.207048,3.846485),(-54.197488,3.826899),(-54.18736,3.814678),(-54.181623,3.811009),(-54.170203,3.805815),(-54.136097,3.795738),(-54.125503,3.788736),(-54.104781,3.75804),(-54.094445,3.747059),(-54.074033,3.676107),(-54.050675,3.640554),(-54.050107,3.634534),(-54.03941,3.636446),(-54.028403,3.639831),(-54.017861,3.641458),(-54.008818,3.637919),(-53.994813,3.623604),(-53.988819,3.610995),(-53.990266,3.595699),(-53.998276,3.573039),(-54.006285,3.531026),(-54.00303,3.455397),(-54.019359,3.415374),(-54.055688,3.377676),(-54.060339,3.364214),(-54.062716,3.346696),(-54.069486,3.327085),(-54.080234,3.309722),(-54.080805,3.309314),(-54.114289,3.285382),(-54.140024,3.245023),(-54.176559,3.200581),(-54.19046,3.178102),(-54.211182,3.127407),(-54.18798,3.130973),(-54.177076,3.116555),(-54.174699,3.093921),(-54.177024,3.072785),(-54.179453,3.070305),(-54.184001,3.067979),(-54.188496,3.06462),(-54.190667,3.059143),(-54.188548,3.058316),(-54.179195,3.051598),(-54.177024,3.048911),(-54.170875,3.024829),(-54.169169,3.010722),(-54.173614,3.004521),(-54.185137,2.997803),(-54.179763,2.983747),(-54.168756,2.971396),(-54.163433,2.969742),(-54.162968,2.955996),(-54.170203,2.925404),(-54.173252,2.919513),(-54.18705,2.899307),(-54.190667,2.887835),(-54.191339,2.877345),(-54.189633,2.870627),(-54.18338,2.863857),(-54.170203,2.853057),(-54.182192,2.846546),(-54.18891,2.838277),(-54.204723,2.791769),(-54.212526,2.776421),(-54.285338,2.677977),(-54.320426,2.606664),(-54.359442,2.508013),(-54.375617,2.483777),(-54.423469,2.435925),(-54.435458,2.431119),(-54.450548,2.428948),(-54.472613,2.42869),(-54.483311,2.422851),(-54.493387,2.417063),(-54.520311,2.348902),(-54.531576,2.340168),(-54.551162,2.338101),(-54.584751,2.348333),(-54.599221,2.345801),(-54.615292,2.326267),(-54.634128,2.320118),(-54.653378,2.316501),(-54.67286,2.315984),(-54.692497,2.318981),(-54.704124,2.32482),(-54.706553,2.332882),(-54.705442,2.342545),(-54.706734,2.353191),(-54.715699,2.375928),(-54.709963,2.39479),(-54.707276,2.395876),(-54.702031,2.395721),(-54.697251,2.397322),(-54.695597,2.403524),(-54.696838,2.409105),(-54.701101,2.419905),(-54.702548,2.425745),(-54.703194,2.445847),(-54.707664,2.450343),(-54.721177,2.457991),(-54.743036,2.466517),(-54.759805,2.465794),(-54.775494,2.457335),(-54.792491,2.448172),(-54.841919,2.433496),(-54.880289,2.447345),(-54.978577,2.54305),(-54.982815,2.552352),(-54.979559,2.566098),(-54.960232,2.585683),(-54.953669,2.599067),(-54.959095,2.608989),(-54.976872,2.606922),(-55.017748,2.590592),(-55.037747,2.577932),(-55.076298,2.54522),(-55.112471,2.527805),(-55.120894,2.524808),(-55.128852,2.525687),(-55.136604,2.5338),(-55.13309,2.552869),(-55.137793,2.56217),(-55.171951,2.559328),(-55.25192,2.497885),(-55.275252,2.499332),(-55.286982,2.513905),(-55.302795,2.519692),(-55.32052,2.518297),(-55.337754,2.511269),(-55.354523,2.494888),(-55.360079,2.476232),(-55.362766,2.457939),(-55.37106,2.442539),(-55.399585,2.430189),(-55.435552,2.43086),(-55.474309,2.435821),(-55.51131,2.43639),(-55.568206,2.431274),(-55.587326,2.433858),(-55.608306,2.433961),(-55.645384,2.416649),(-55.724294,2.396909),(-55.744112,2.401043),(-55.754602,2.409415),(-55.766126,2.431274),(-55.773568,2.440059),(-55.783128,2.445175),(-55.853769,2.462642),(-55.870668,2.47091),(-55.925031,2.515662),(-55.9472,2.528167),(-55.971023,2.530338),(-55.983012,2.526462),(-55.989239,2.520829),(-55.996913,2.503259),(-56.007507,2.460678),(-56.008179,2.416288),(-56.013346,2.398821),(-56.042569,2.355103),(-56.050243,2.347041),(-56.062155,2.341564),(-56.07342,2.34239),(-56.082283,2.347713),(-56.091455,2.351899),(-56.10378,2.349057),(-56.116803,2.333089),(-56.131995,2.304357),(-56.143881,2.274746),(-56.146775,2.256194),(-56.135251,2.248546),(-56.091455,2.245911),(-56.072929,2.241518),(-56.054016,2.224051),(-56.044843,2.184726),(-56.03133,2.163487),(-56.004406,2.144986),(-55.995776,2.13739),(-55.959965,2.090985),(-55.925806,2.061684),(-55.918262,2.050393),(-55.915135,2.037655),(-55.916763,2.028508),(-55.92038,2.019387),(-55.923584,2.006597),(-55.922344,1.962155),(-55.916763,1.922235),(-55.922034,1.886217),(-55.953815,1.853273),(-56.019651,1.833507),(-56.082644,1.846555),(-56.145276,1.871773),(-56.209768,1.888542),(-56.257931,1.885648),(-56.273796,1.887509),(-56.292709,1.895467),(-56.328624,1.918463),(-56.347951,1.926602),(-56.367175,1.928876),(-56.396527,1.921667),(-56.415182,1.919703),(-56.429807,1.9227),(-56.481819,1.941614),(-56.4851,1.953215),(-56.491198,1.962905),(-56.499983,1.969984),(-56.520964,1.976728),(-56.529387,1.981792),(-56.536493,1.988639),(-56.542074,1.997166),(-56.579772,2.016803),(-56.677802,2.018405),(-56.70519,2.029645),(-56.801464,2.165967),(-56.80875,2.195784),(-56.816346,2.217592),(-56.826191,2.261672),(-56.838877,2.281102),(-56.847792,2.285856),(-56.870865,2.290146),(-56.880141,2.294796),(-56.88443,2.303736),(-56.883887,2.339755),(-56.89505,2.362079),(-56.930836,2.393292),(-56.938458,2.41143),(-56.932024,2.425796),(-56.930241,2.436183),(-56.935073,2.445898),(-56.951635,2.461246),(-56.956364,2.470031),(-56.959593,2.483777),(-56.957526,2.493492),(-56.952617,2.504551),(-56.951274,2.515455),(-56.959593,2.524705),(-56.980006,2.509719),(-56.994113,2.504861),(-57.000573,2.514163),(-56.995302,2.547856),(-56.997111,2.555142),(-57.02238,2.584546),(-57.027238,2.59359),(-57.02791,2.610591),(-57.023155,2.623665),(-57.020468,2.635447),(-57.027238,2.648212),(-57.048012,2.636481),(-57.05597,2.642372),(-57.061964,2.68175),(-57.071886,2.700095),(-57.097725,2.72738),(-57.102944,2.740454),(-57.099016,2.750376),(-57.092144,2.763037),(-57.08987,2.773889),(-57.099533,2.778591),(-57.133743,2.773424),(-57.13705,2.77115),(-57.143665,2.790012),(-57.126405,2.82603),(-57.133381,2.832593),(-57.145215,2.830423),(-57.165266,2.821069),(-57.174619,2.818951),(-57.186608,2.82324),(-57.191052,2.832593),(-57.194256,2.841998),(-57.202266,2.846236),(-57.206348,2.856571),(-57.219629,2.908299),(-57.210328,2.918221),(-57.194721,2.930623),(-57.183818,2.944679),(-57.188623,2.95951),(-57.221851,2.963024),(-57.234615,2.970362),(-57.226451,2.983385),(-57.22118,2.992583),(-57.2218,3.000438),(-57.224694,3.009171),(-57.226451,3.021264),(-57.223247,3.024778),(-57.209242,3.024054),(-57.205987,3.028137),(-57.20702,3.035681),(-57.211774,3.048342),(-57.21286,3.056042),(-57.222213,3.078263),(-57.239473,3.094128),(-57.248568,3.112369),(-57.233324,3.14167),(-57.236734,3.143478),(-57.237406,3.143995),(-57.237613,3.144874),(-57.239473,3.147871),(-57.246243,3.141618),(-57.254976,3.13583),(-57.264898,3.132626),(-57.274923,3.13428),(-57.286033,3.142393),(-57.284173,3.148956),(-57.277714,3.156914),(-57.274923,3.169007),(-57.285672,3.192106),(-57.287946,3.203113),(-57.287119,3.21536),(-57.281744,3.235928),(-57.280452,3.247813),(-57.284018,3.25975),(-57.290271,3.267967),(-57.292493,3.276287),(-57.284225,3.288793),(-57.282778,3.295045),(-57.280452,3.329772),(-57.283553,3.343802),(-57.308409,3.39491),(-57.340035,3.370157),(-57.366752,3.36561),(-57.393469,3.373826),(-57.425043,3.387495),(-57.423958,3.369382),(-57.430934,3.360623),(-57.459201,3.353336),(-57.461682,3.349978),(-57.468761,3.343182),(-57.476254,3.338945),(-57.479717,3.343389),(-57.482042,3.348556),(-57.487985,3.351528),(-57.49584,3.352975),(-57.503901,3.353336),(-57.509637,3.357677),(-57.522401,3.365248),(-57.535269,3.36778),(-57.545036,3.348143),(-57.554234,3.346748),(-57.565138,3.349822),(-57.596193,3.367121),(-57.596402,3.367237),(-57.613249,3.376643),(-57.641464,3.38243),(-57.649939,3.385944),(-57.654848,3.39013),(-57.658207,3.39522),(-57.662548,3.40708),(-57.664615,3.417544),(-57.663995,3.425839),(-57.658931,3.443899),(-57.658362,3.450617),(-57.660533,3.462994),(-57.660688,3.469505),(-57.645495,3.498987),(-57.644048,3.51666),(-57.660429,3.535186),(-57.681255,3.547304),(-57.685131,3.549164),(-57.687249,3.552162),(-57.697998,3.553609),(-57.702856,3.555676),(-57.707351,3.560662),(-57.708643,3.564125),(-57.709522,3.56769),(-57.71748,3.582444),(-57.722493,3.599962),(-57.72611,3.607197),(-57.764247,3.631588),(-57.813133,3.651845),(-57.829773,3.662439),(-57.840987,3.680991),(-57.846929,3.702101),(-57.849617,3.747473),(-57.853854,3.76667),(-57.875145,3.812197),(-57.925839,3.886405),(-57.942117,3.905447),(-58.007902,3.957279),(-58.032138,3.987716),(-58.042008,4.023037),(-58.055082,4.108071),(-58.067691,4.151143),(-58.065934,4.171839),(-58.052033,4.193104),(-57.964958,4.282039),(-57.953848,4.299015),(-57.947388,4.318756),(-57.94527,4.343922),(-57.94806,4.360484),(-57.953486,4.375703),(-57.956639,4.391438),(-57.952659,4.409732),(-57.942789,4.425106),(-57.931317,4.437844),(-57.92186,4.450944),(-57.914471,4.484069),(-57.896074,4.52851),(-57.879124,4.556829),(-57.863311,4.60773),(-57.845431,4.633517),(-57.837421,4.65088),(-57.836026,4.669845),(-57.844346,4.687519),(-57.871166,4.721728),(-57.88455,4.762863),(-57.901138,4.773922),(-57.91783,4.782371),(-57.925374,4.796142),(-57.918501,4.829758),(-57.90243,4.852728),(-57.884188,4.872262),(-57.870701,4.888928),(-57.85034,4.922801),(-57.842795,4.929881),(-57.830238,4.933059),(-57.820575,4.930294),(-57.810963,4.92554),(-57.798457,4.92306),(-57.773962,4.926445),(-57.762335,4.93554),(-57.747297,4.964013),(-57.720477,4.9898),(-57.686939,5.006259),(-57.64937,5.008429),(-57.610096,4.99135),(-57.566223,5.007086),(-57.543279,5.011091),(-57.517596,5.012434),(-57.512221,5.009153),(-57.496873,4.994657),(-57.490259,4.99135),(-57.47734,4.992487),(-57.460493,4.997629),(-57.381377,5.005742),(-57.35621,5.012434),(-57.345513,5.01662),(-57.338072,5.020754),(-57.329442,5.024087),(-57.315231,5.026103),(-57.306497,5.024449),(-57.298694,5.021116),(-57.290478,5.020289),(-57.280452,5.026103),(-57.316936,5.058969),(-57.321432,5.070157),(-57.320192,5.083412),(-57.317091,5.094755),(-57.302208,5.128474),(-57.295542,5.157206),(-57.288979,5.171029),(-57.277714,5.17692),(-57.259937,5.1763),(-57.247276,5.172373),(-57.23875,5.162012),(-57.233324,5.142116),(-57.217769,5.14855),(-57.202008,5.157619),(-57.189812,5.16922),(-57.184903,5.183147),(-57.192396,5.203172),(-57.225727,5.243609),(-57.232522,5.260572),(-57.233324,5.262574),(-57.237613,5.268723),(-57.247638,5.271772),(-57.259007,5.271204),(-57.26743,5.266295),(-57.269187,5.256709),(-57.264019,5.247045),(-57.253787,5.234927),(-57.256423,5.228287),(-57.263037,5.223997),(-57.271667,5.222861),(-57.280452,5.225341),(-57.285465,5.230819),(-57.287274,5.238699),(-57.288824,5.30854),(-57.292028,5.311331),(-57.298332,5.311021),(-57.308409,5.313475),(-57.322827,5.30761),(-57.331715,5.30761),(-57.335695,5.316886),(-57.332284,5.327867),(-57.324119,5.33859),(-57.275491,5.387398),(-57.265208,5.403366),(-57.261229,5.42675),(-57.260092,5.448196),(-57.25694,5.464086),(-57.24767,5.484931),(-57.233998,5.498969),(-57.225087,5.507514),(-57.193023,5.519721),(-57.179514,5.530585),(-57.170155,5.542792),(-57.163686,5.557074),(-57.139638,5.665107),(-57.134877,5.759914),(-57.128,5.793158),(-57.12577,5.818145),(-57.113847,5.858844),(-57.102283,5.886416),(-57.075795,5.929999),(-57.071645,5.94123),(-57.066029,5.9501),(-57.057688,5.955878),(-57.03482,5.959906),(-57.027903,5.964423),(-57.022694,5.96894),(-57.017445,5.970933),(-57.012807,5.973863),(-57.000111,5.987982),(-56.994496,5.992662),(-56.98469,5.996283),(-56.974599,5.998114),(-56.963872,6.009152),(-56.956537,6.011574),(-56.928844,6.004262),(-56.866972,5.989637),(-56.830356,5.985557),(-56.780724,5.985508),(-56.702631,5.98219),(-56.659512,5.979716),(-56.642432,5.973223),(-56.611422,5.953647),(-56.593104,5.945753),(-56.57395,5.940756),(-56.526859,5.936549),(-56.418314,5.911349),(-56.355024,5.89467),(-56.303807,5.892508),(-56.256766,5.880406),(-56.222834,5.870753),(-56.19164,5.862616),(-56.124257,5.848049),(-56.083036,5.834366),(-56.058595,5.827737),(-56.037994,5.824164),(-55.999182,5.810713),(-55.936006,5.804661),(-55.917877,5.784735),(-55.903554,5.776353),(-55.897694,5.763007),(-55.897694,5.676703),(-55.897247,5.676703),(-55.890248,5.676703),(-55.884999,5.69245),(-55.88329,5.708075),(-55.884023,5.741929),(-55.887278,5.759467),(-55.90453,5.797187),(-55.915362,5.821771),(-55.899963,5.841964),(-55.910003,5.850918),(-55.922245,5.850353),(-55.933959,5.849827),(-55.947872,5.861521),(-55.951169,5.881511),(-55.946669,5.896493),(-55.930433,5.91758),(-55.923613,5.927845),(-55.910395,5.941616),(-55.900654,5.951945),(-55.886052,5.962954),(-55.86799,5.969813),(-55.844382,5.975962),(-55.820095,5.977275),(-55.729089,5.981216),(-55.678578,5.985256),(-55.637318,5.985907),(-55.394988,5.973876),(-55.335967,5.962708),(-55.307871,5.94335),(-55.292045,5.936727),(-55.270823,5.929999),(-55.263783,5.926418),(-55.253204,5.917792),(-55.242909,5.909369),(-55.2329,5.903266),(-55.229766,5.902411),(-55.221425,5.900214),(-55.21288,5.900214),(-55.202433,5.898761),(-55.188361,5.897395),(-55.176908,5.90129),(-55.164052,5.906684),(-55.14784,5.908177),(-55.130727,5.895855),(-55.110829,5.881171),(-55.103107,5.866412),(-55.115101,5.837128),(-55.129872,5.820746),(-55.128611,5.821357),(-55.101039,5.830499),(-55.091712,5.852791),(-55.090749,5.875117),(-55.08552,5.882799),(-55.063423,5.882883),(-55.030385,5.859768),(-55.010121,5.855536),(-54.99706,5.858466),(-54.988922,5.863674),(-54.981191,5.865465),(-54.958811,5.851793),(-54.950307,5.850287),(-54.941803,5.852118),(-54.931956,5.855536),(-54.924143,5.860419),(-54.918691,5.867092),(-54.911977,5.87287),(-54.900258,5.875393),(-54.890777,5.873358),(-54.880727,5.868354),(-54.863026,5.855536),(-54.867543,5.863674),(-54.874338,5.871568),(-54.882192,5.878363),(-54.890289,5.882799),(-54.903472,5.885403),(-54.91258,5.884025),(-54.921851,5.876625),(-54.933319,5.869672),(-54.956207,5.867575),(-54.971566,5.877267),(-54.985634,5.880387),(-55.001517,5.871259),(-55.016591,5.871975),(-55.031728,5.884467),(-55.047271,5.892279),(-55.105295,5.908922),(-55.12564,5.918647),(-55.142974,5.930121),(-55.15038,5.940863),(-55.154124,5.951361),(-55.159966,5.958114),(-55.153323,5.968592),(-55.1445,5.974248),(-55.116851,5.985256),(-55.085301,5.990649),(-55.044799,5.993105),(-55.013905,5.993394),(-54.77359,5.985256),(-54.75536,5.980943),(-54.712555,5.976184),(-54.673556,5.969192),(-54.471781,5.94097),(-54.34863,5.913755),(-54.252699,5.894808),(-54.169342,5.867906),(-54.097396,5.847339),(-54.074456,5.844887),(-54.062032,5.840559),(-54.036731,5.842351),(-54.030944,5.834184),(-54.020462,5.83025),(-54.014687,5.820148),(-54.016307,5.809704),(-53.992085,5.763497),(-53.986357,5.745665),(-53.99592,5.734524),(-54.019753,5.688979),(-54.031148,5.66931),(-54.036439,5.629502),(-54.050364,5.552069),(-54.061106,5.512885),(-54.073598,5.489814),(-54.091786,5.467922),(-54.10912,5.452826),(-54.118479,5.442776),(-54.122548,5.433417),(-54.128529,5.414293),(-54.170969,5.348375),(-54.170965,5.348376)] +Slovakia [(19.706321,49.387529),(19.726578,49.388873),(19.760065,49.397658),(19.769056,49.393213),(19.769263,49.39311),(19.778565,49.374197),(19.783629,49.357557),(19.78952,49.309188),(19.78797,49.305105),(19.780322,49.297612),(19.779713,49.293453),(19.779702,49.293375),(19.783216,49.290016),(19.79686,49.283399),(19.796962,49.28335),(19.798563,49.281081),(19.798822,49.280714),(19.806415,49.275488),(19.80678,49.275236),(19.808641,49.270895),(19.806263,49.265263),(19.800476,49.263041),(19.794068,49.261852),(19.789624,49.259475),(19.751797,49.219064),(19.747787,49.205956),(19.747766,49.205887),(19.760685,49.194208),(19.785903,49.188162),(19.831998,49.185888),(19.854219,49.191262),(19.868292,49.200788),(19.887809,49.214),(19.905896,49.222785),(19.937935,49.22511),(19.965737,49.215653),(20.01731,49.183872),(20.050486,49.173227),(20.07002,49.183097),(20.080355,49.208109),(20.08604,49.243042),(20.098442,49.25286),(20.105367,49.263971),(20.111051,49.275856),(20.130171,49.303917),(20.135856,49.308878),(20.138336,49.307327),(20.16035,49.305622),(20.170169,49.311617),(20.191976,49.328618),(20.207169,49.334199),(20.284374,49.338643),(20.289335,49.343087),(20.296466,49.356937),(20.301634,49.371199),(20.303701,49.380398),(20.307422,49.386599),(20.317653,49.391612),(20.329539,49.391767),(20.370467,49.38169),(20.422143,49.382982),(20.421936,49.40019),(20.437543,49.402515),(20.522085,49.374352),(20.543996,49.370838),(20.567664,49.376367),(20.579136,49.383395),(20.595053,49.396263),(20.605284,49.400035),(20.614483,49.400448),(20.636084,49.39833),(20.673911,49.402309),(20.689517,49.4005),(20.778297,49.331202),(20.79411,49.323657),(20.816538,49.321383),(20.833591,49.322055),(20.849301,49.320505),(20.868007,49.31141),(20.884337,49.300299),(20.900564,49.2926),(20.91896,49.290326),(20.942422,49.295855),(20.964022,49.308103),(20.996682,49.339367),(21.017249,49.352441),(21.032959,49.354611),(21.054043,49.354766),(21.072543,49.357195),(21.080708,49.366342),(21.068512,49.381431),(21.045464,49.390578),(21.033269,49.399673),(21.053526,49.414453),(21.068822,49.419207),(21.10944,49.424581),(21.124943,49.423651),(21.143029,49.415538),(21.157292,49.405151),(21.172588,49.398278),(21.194086,49.400603),(21.211242,49.411094),(21.242455,49.441273),(21.260542,49.449438),(21.274391,49.447267),(21.330408,49.427785),(21.42787,49.409802),(21.444406,49.409905),(21.48151,49.415228),(21.496186,49.412386),(21.514422,49.417213),(21.529569,49.421222),(21.601193,49.426493),(21.6199,49.423341),(21.630028,49.418897),(21.648632,49.407063),(21.65876,49.402464),(21.666305,49.401792),(21.681808,49.404066),(21.69173,49.402154),(21.708576,49.390888),(21.742166,49.357092),(21.757566,49.348927),(21.768004,49.353474),(21.782164,49.364482),(21.799423,49.374817),(21.819577,49.377246),(21.837871,49.370424),(21.874561,49.348358),(21.928408,49.330788),(21.964478,49.308568),(21.99321,49.278182),(22.005819,49.242887),(22.012434,49.211054),(22.040752,49.197463),(22.111549,49.188627),(22.144105,49.174881),(22.155681,49.171522),(22.165706,49.171108),(22.189684,49.17302),(22.197952,49.171987),(22.208908,49.163977),(22.209011,49.156949),(22.20622,49.150489),(22.208494,49.144185),(22.215936,49.139999),(22.262858,49.130594),(22.318151,49.131989),(22.339442,49.12646),(22.390085,49.093025),(22.426775,49.085635),(22.505013,49.083413),(22.539637,49.0722),(22.531989,49.055715),(22.524754,49.032874),(22.520103,49.009826),(22.520516,48.992928),(22.505013,48.984246),(22.466566,48.980526),(22.448996,48.971431),(22.427292,48.929469),(22.41489,48.911693),(22.41365,48.906783),(22.413753,48.893864),(22.411789,48.887766),(22.402384,48.878826),(22.378406,48.865442),(22.370799,48.858248),(22.368898,48.856451),(22.362283,48.844255),(22.36156,48.836452),(22.363523,48.828287),(22.365694,48.794387),(22.36342,48.787617),(22.356495,48.776145),(22.347814,48.767877),(22.338409,48.762968),(22.330761,48.756405),(22.32766,48.743021),(22.3289,48.721575),(22.322492,48.700336),(22.310297,48.681681),(22.294277,48.667625),(22.282185,48.662405),(22.25552,48.656773),(22.243221,48.651192),(22.235676,48.644164),(22.225237,48.628222),(22.219036,48.620935),(22.153717,48.585873),(22.138731,48.569595),(22.136664,48.549337),(22.148343,48.508823),(22.144829,48.493114),(22.13377,48.476835),(22.13284,48.404798),(22.113926,48.38865),(22.09646,48.379425),(22.077856,48.375808),(22.018015,48.379735),(21.999928,48.37896),(21.981531,48.374723),(21.929338,48.372914),(21.914765,48.36909),(21.884276,48.357463),(21.841178,48.353174),(21.789398,48.335526),(21.759012,48.333769),(21.727697,48.340901),(21.701238,48.353949),(21.67757,48.372346),(21.621553,48.429655),(21.613388,48.440352),(21.600366,48.481641),(21.591684,48.49301),(21.574631,48.495568),(21.537734,48.495232),(21.521818,48.50009),(21.5151,48.507118),(21.506005,48.526496),(21.49939,48.535075),(21.490812,48.540268),(21.472725,48.544997),(21.439135,48.558329),(21.424563,48.561275),(21.372679,48.550345),(21.338573,48.549854),(21.32183,48.54758),(21.302296,48.539907),(21.293925,48.530579),(21.28824,48.519934),(21.276561,48.50872),(21.261782,48.50319),(21.250413,48.506498),(21.238011,48.513448),(21.219924,48.518719),(21.186748,48.513707),(21.109336,48.489109),(21.084015,48.49301),(21.063861,48.506239),(21.035956,48.514637),(21.0065,48.518151),(20.981489,48.516859),(20.945832,48.518978),(20.891365,48.541095),(20.859946,48.543317),(20.845477,48.545823),(20.815814,48.563807),(20.800311,48.569233),(20.784085,48.569052),(20.572522,48.536573),(20.51051,48.533783),(20.481674,48.526083),(20.480538,48.518538),(20.480227,48.510218),(20.482191,48.492881),(20.482811,48.489367),(20.482915,48.485827),(20.482501,48.482261),(20.481674,48.478747),(20.468239,48.465389),(20.465968,48.46379),(20.435579,48.442393),(20.420593,48.429241),(20.409017,48.413713),(20.370157,48.334338),(20.349279,48.305476),(20.324268,48.279948),(20.295226,48.260415),(20.272385,48.252456),(20.260293,48.255893),(20.249027,48.264187),(20.22908,48.270905),(20.217815,48.267598),(20.187636,48.248994),(20.170892,48.244033),(20.153322,48.245273),(20.14309,48.247805),(20.134512,48.246669),(20.122006,48.236747),(20.118079,48.229719),(20.112601,48.211735),(20.105263,48.202795),(20.096995,48.198429),(20.078082,48.193545),(20.038303,48.177233),(20.034983,48.175872),(19.99695,48.167914),(19.973902,48.158379),(19.928633,48.130087),(19.905069,48.124299),(19.884295,48.129621),(19.846261,48.152669),(19.821663,48.157914),(19.785593,48.14869),(19.776084,48.149517),(19.766679,48.159),(19.76916,48.167449),(19.774844,48.176079),(19.774327,48.185897),(19.756551,48.200315),(19.73309,48.202899),(19.686994,48.196904),(19.676969,48.200392),(19.655265,48.21835),(19.643896,48.224809),(19.633871,48.226773),(19.623226,48.227006),(19.531241,48.21065),(19.513982,48.203958),(19.503026,48.189411),(19.493621,48.150705),(19.481735,48.134892),(19.481425,48.134427),(19.481219,48.133962),(19.481425,48.133342),(19.481735,48.13267),(19.483286,48.127193),(19.483803,48.121767),(19.483286,48.116496),(19.481735,48.111328),(19.428199,48.085852),(19.29322,48.087764),(19.233482,48.06208),(19.222526,48.060582),(19.098503,48.070736),(19.038662,48.064871),(19.019017,48.065497),(18.996494,48.066214),(18.981818,48.061615),(18.933595,48.054349),(18.838467,48.040015),(18.821001,48.030454),(18.794232,47.993144),(18.784724,47.987615),(18.765293,47.985393),(18.756198,47.981827),(18.743176,47.971052),(18.744519,47.967357),(18.751444,47.963353),(18.754751,47.951803),(18.744726,47.910513),(18.742246,47.889455),(18.748757,47.870723),(18.778006,47.851447),(18.816453,47.83256),(18.814916,47.832194),(18.790305,47.826332),(18.767671,47.822302),(18.750307,47.81362),(18.717234,47.788118),(18.692843,47.777963),(18.663698,47.775896),(18.633829,47.779824),(18.597448,47.79065),(18.552593,47.792846),(18.347851,47.776775),(18.273024,47.756259),(18.23592,47.753882),(18.11262,47.762486),(17.883532,47.752521),(17.825713,47.750006),(17.741997,47.76538),(17.719245,47.773669),(17.676678,47.789177),(17.666239,47.797032),(17.658384,47.807316),(17.639884,47.819201),(17.61911,47.829226),(17.604227,47.834239),(17.592962,47.833102),(17.582937,47.829795),(17.572601,47.829536),(17.560406,47.837986),(17.526609,47.872118),(17.517308,47.876252),(17.492193,47.879818),(17.481858,47.882711),(17.472039,47.888809),(17.36941,47.981207),(17.337887,47.998725),(17.272671,48.00534),(17.262316,48.007283),(17.220892,48.015055),(17.184821,48.020274),(17.148338,48.005443),(17.12498,48.019525),(17.092631,48.02725),(17.069686,48.035674),(17.075061,48.052081),(17.063072,48.058773),(17.059144,48.060427),(17.064829,48.07903),(17.069996,48.089159),(17.080228,48.097608),(17.067206,48.106936),(17.062455,48.112724),(17.047465,48.130991),(17.036923,48.135513),(17.020904,48.137166),(17.007158,48.142799),(16.98194,48.161299),(16.974808,48.17688),(16.974705,48.198558),(16.969951,48.216645),(16.954345,48.25256),(16.953931,48.25734),(16.955275,48.268786),(16.954345,48.273127),(16.950624,48.276589),(16.944423,48.27801),(16.933364,48.284728),(16.924269,48.287519),(16.916621,48.2908),(16.913313,48.296691),(16.912073,48.301239),(16.908869,48.306975),(16.905459,48.311988),(16.902771,48.314106),(16.898431,48.316173),(16.900291,48.321238),(16.904218,48.327025),(16.906492,48.33147),(16.901945,48.339402),(16.891713,48.347024),(16.881171,48.352812),(16.875486,48.355034),(16.855332,48.356455),(16.847581,48.359582),(16.84448,48.365602),(16.845101,48.376583),(16.846858,48.381131),(16.849338,48.384102),(16.851922,48.390407),(16.86081,48.443788),(16.864944,48.458077),(16.875073,48.471539),(16.901221,48.496602),(16.906492,48.509908),(16.913934,48.519339),(16.93047,48.528202),(16.946903,48.539726),(16.949055,48.544836),(16.954345,48.557399),(16.945043,48.604166),(16.947523,48.623157),(16.963336,48.635947),(16.974808,48.649874),(17.025348,48.746328),(17.049946,48.774027),(17.084362,48.793715),(17.098728,48.805756),(17.10462,48.824618),(17.113715,48.83392),(17.167458,48.859758),(17.21221,48.866062),(17.260269,48.857794),(17.374371,48.819605),(17.391734,48.821776),(17.411225,48.830216),(17.429561,48.838157),(17.453332,48.842756),(17.467905,48.838105),(17.498497,48.816763),(17.535084,48.812991),(17.727217,48.86291),(17.744891,48.872574),(17.77941,48.911744),(17.795533,48.920581),(17.820131,48.923371),(17.841215,48.920994),(17.860336,48.921718),(17.878733,48.933552),(17.886897,48.947246),(17.894649,48.9782),(17.90085,48.993031),(17.914079,49.010498),(17.93506,49.019386),(17.959244,49.021867),(18.012885,49.019128),(18.046061,49.029153),(18.075516,49.047188),(18.09629,49.070288),(18.102905,49.09225),(18.10163,49.136928),(18.101458,49.142945),(18.105075,49.169765),(18.117788,49.202579),(18.136495,49.233068),(18.160576,49.2587),(18.190031,49.276942),(18.324597,49.311255),(18.361586,49.330191),(18.385162,49.342261),(18.387642,49.389751),(18.416788,49.385462),(18.439215,49.395074),(18.481797,49.429077),(18.514663,49.440601),(18.522931,49.446079),(18.527995,49.454864),(18.530476,49.473467),(18.535643,49.481684),(18.556211,49.490159),(18.600446,49.485973),(18.628971,49.495791),(18.635896,49.496721),(18.64282,49.495791),(18.675583,49.485043),(18.704522,49.479255),(18.732531,49.480288),(18.773562,49.504886),(18.792269,49.509537),(18.833196,49.510261),(18.932208,49.504318),(18.961147,49.492794),(18.952362,49.475948),(18.953396,49.461685),(18.958253,49.448146),(18.960837,49.433315),(18.956703,49.400448),(18.962284,49.389183),(18.981818,49.386806),(19.007139,49.388098),(19.045793,49.402774),(19.067601,49.406133),(19.076799,49.404066),(19.096643,49.394609),(19.106255,49.391405),(19.11659,49.39094),(19.141705,49.394195),(19.172504,49.402257),(19.179738,49.410267),(19.182322,49.422721),(19.18935,49.442203),(19.192244,49.442616),(19.204543,49.442823),(19.208987,49.444993),(19.211364,49.45166),(19.209401,49.456414),(19.206197,49.459411),(19.20444,49.460548),(19.220459,49.493001),(19.234102,49.507212),(19.248675,49.516255),(19.265005,49.521475),(19.284228,49.524162),(19.315027,49.523955),(19.325363,49.52504),(19.339522,49.528761),(19.347067,49.532998),(19.43378,49.595165),(19.437604,49.600126),(19.443392,49.60178),(19.44889,49.600313),(19.457344,49.598059),(19.474191,49.578732),(19.481735,49.573513),(19.505197,49.563384),(19.517289,49.543282),(19.535479,49.492846),(19.551602,49.461013),(19.55677,49.453882),(19.573926,49.445252),(19.594804,49.441583),(19.634801,49.441324),(19.63015,49.43502),(19.6286,49.429594),(19.62922,49.413936),(19.627097,49.402165),(19.627044,49.401868),(19.684514,49.389079),(19.706321,49.387529)] +Slovenia [(16.343426,46.714178),(16.357275,46.715832),(16.357585,46.699011),(16.365383,46.696712),(16.366216,46.696467),(16.371434,46.694929),(16.390038,46.694154),(16.405024,46.687255),(16.410502,46.668367),(16.402607,46.663109),(16.396652,46.659143),(16.377636,46.652864),(16.368437,46.642994),(16.372246,46.636341),(16.376395,46.629093),(16.394585,46.619016),(16.430242,46.604392),(16.467139,46.564704),(16.500832,46.544809),(16.515302,46.501711),(16.491117,46.515146),(16.481298,46.519022),(16.470756,46.520262),(16.449052,46.51835),(16.440371,46.519022),(16.431999,46.523208),(16.415153,46.535559),(16.406264,46.539486),(16.394895,46.540106),(16.382183,46.539383),(16.369471,46.540571),(16.357895,46.546979),(16.351694,46.539486),(16.351254,46.539922),(16.344149,46.546979),(16.340276,46.543827),(16.32999,46.535455),(16.310663,46.530985),(16.295367,46.524448),(16.263947,46.515922),(16.260931,46.513576),(16.234905,46.493339),(16.234188,46.484892),(16.233665,46.47874),(16.237489,46.465072),(16.249375,46.437528),(16.250098,46.429441),(16.248238,46.413344),(16.250925,46.404998),(16.257023,46.399908),(16.274076,46.392105),(16.278727,46.387351),(16.279936,46.378661),(16.280277,46.376214),(16.275626,46.373165),(16.252785,46.373424),(16.217129,46.367352),(16.208654,46.367093),(16.191807,46.369781),(16.177544,46.375594),(16.153567,46.391433),(16.143851,46.394714),(16.131552,46.393061),(16.123181,46.386885),(16.115533,46.379289),(16.106024,46.373734),(16.094345,46.372261),(16.088654,46.373086),(16.057965,46.377532),(16.057448,46.359652),(16.059722,46.345312),(16.059619,46.332315),(16.052384,46.318595),(16.049922,46.316735),(16.038948,46.308441),(16.019208,46.298829),(15.998434,46.291542),(15.993668,46.290613),(15.982001,46.288339),(15.948721,46.284204),(15.918903,46.272827),(15.883712,46.2594),(15.880895,46.259341),(15.879323,46.259308),(15.834206,46.258366),(15.81829,46.255524),(15.803097,46.250511),(15.799526,46.248607),(15.789144,46.24307),(15.768887,46.21935),(15.749767,46.210772),(15.677975,46.214462),(15.661297,46.21532),(15.639799,46.207672),(15.626571,46.19521),(15.62285,46.191704),(15.604349,46.167002),(15.589983,46.138684),(15.58988,46.113517),(15.603833,46.090986),(15.623605,46.076415),(15.631531,46.070574),(15.643727,46.06551),(15.671735,46.057397),(15.683931,46.051144),(15.69288,46.041636),(15.697987,46.036209),(15.693646,46.025771),(15.681967,46.013523),(15.674319,45.993318),(15.674216,45.993163),(15.675381,45.972486),(15.67711,45.941796),(15.67556,45.925157),(15.670392,45.912651),(15.663364,45.900817),(15.659436,45.888828),(15.663674,45.876064),(15.675456,45.855962),(15.676076,45.841699),(15.666051,45.831674),(15.645587,45.824129),(15.626054,45.820202),(15.587296,45.81922),(15.549748,45.823693),(15.523527,45.826816),(15.513916,45.823406),(15.495312,45.812657),(15.48539,45.810176),(15.473918,45.811572),(15.462549,45.814207),(15.451284,45.815137),(15.440328,45.811468),(15.435574,45.802115),(15.439502,45.791676),(15.441052,45.782168),(15.429755,45.775691),(15.429063,45.775295),(15.331031,45.752486),(15.303799,45.746149),(15.263492,45.730388),(15.255017,45.723463),(15.249913,45.713732),(15.248919,45.711836),(15.250883,45.70765),(15.258221,45.705118),(15.267832,45.698452),(15.277754,45.685016),(15.283025,45.680107),(15.291914,45.675559),(15.304936,45.672149),(15.30907,45.674164),(15.310414,45.678195),(15.314961,45.680882),(15.327054,45.683156),(15.330774,45.684551),(15.333875,45.682639),(15.350034,45.669619),(15.351962,45.668066),(15.368291,45.649049),(15.373769,45.640213),(15.353099,45.640316),(15.339146,45.636905),(15.326744,45.632255),(15.297391,45.625692),(15.291604,45.61825),(15.287883,45.610344),(15.281062,45.606158),(15.268556,45.601662),(15.269589,45.593446),(15.276721,45.582697),(15.282179,45.571494),(15.282612,45.570605),(15.288606,45.54456),(15.296668,45.522959),(15.311034,45.505906),(15.361367,45.482031),(15.351755,45.47614),(15.333875,45.458518),(15.325193,45.452834),(15.314031,45.450509),(15.281578,45.450974),(15.225849,45.43645),(15.18422,45.4256),(15.139262,45.430045),(15.066128,45.473934),(15.056166,45.479912),(15.007383,45.480843),(14.997461,45.487199),(14.986299,45.490868),(14.977341,45.491728),(14.962631,45.493142),(14.945372,45.50451),(14.922634,45.514949),(14.904444,45.514432),(14.900826,45.493142),(14.881603,45.469784),(14.838815,45.458983),(14.797164,45.465185),(14.781454,45.493142),(14.781351,45.493193),(14.781247,45.493348),(14.781144,45.493348),(14.688333,45.522029),(14.668489,45.533966),(14.668179,45.539134),(14.671693,45.556807),(14.669833,45.564558),(14.664045,45.570036),(14.663675,45.570187),(14.657327,45.572775),(14.650299,45.574842),(14.615986,45.594066),(14.603067,45.603574),(14.593868,45.616183),(14.592938,45.629671),(14.594075,45.648016),(14.591905,45.663364),(14.580949,45.667808),(14.569095,45.664252),(14.563896,45.662692),(14.556145,45.656697),(14.543639,45.63644),(14.533097,45.625692),(14.507879,45.605848),(14.498577,45.596184),(14.492273,45.58342),(14.491502,45.579165),(14.487415,45.5566),(14.482144,45.542441),(14.468915,45.525594),(14.429744,45.505389),(14.411244,45.493193),(14.372797,45.477845),(14.326805,45.4749),(14.280399,45.481101),(14.240608,45.493348),(14.218698,45.497172),(14.193066,45.491901),(14.145524,45.476243),(14.119686,45.472884),(14.117321,45.472976),(14.116747,45.472998),(14.092917,45.473918),(14.066665,45.480274),(14.041551,45.493142),(14.041551,45.493193),(14.028322,45.50265),(14.013956,45.507973),(13.987476,45.511909),(13.971891,45.514226),(13.964966,45.51097),(13.961452,45.50389),(13.961452,45.493142),(13.98264,45.475313),(13.969824,45.462963),(13.923005,45.448958),(13.908432,45.438881),(13.899647,45.429218),(13.889002,45.423637),(13.835568,45.429114),(13.819859,45.432628),(13.806526,45.442137),(13.759294,45.463169),(13.65997,45.459978),(13.629018,45.458983),(13.589529,45.488837),(13.591645,45.493109),(13.589122,45.501614),(13.595958,45.511908),(13.595958,45.518134),(13.586192,45.519477),(13.578624,45.523383),(13.572765,45.529975),(13.568614,45.539252),(13.58961,45.535793),(13.675141,45.544745),(13.75294,45.552883),(13.75294,45.559068),(13.742361,45.56977),(13.727387,45.581204),(13.711762,45.593207),(13.761051,45.596236),(13.800532,45.58125),(13.847764,45.584661),(13.867926,45.602169),(13.887038,45.618767),(13.894686,45.631841),(13.893641,45.633758),(13.893136,45.634683),(13.884144,45.635148),(13.869158,45.641143),(13.858409,45.649359),(13.778724,45.743411),(13.709478,45.765321),(13.699908,45.770524),(13.660334,45.792038),(13.643591,45.795655),(13.609174,45.798601),(13.581269,45.809246),(13.574172,45.819028),(13.565973,45.83033),(13.56928,45.86454),(13.599306,45.912327),(13.608244,45.926552),(13.615325,45.945912),(13.622817,45.966394),(13.605867,45.985411),(13.600735,45.984574),(13.571657,45.97983),(13.539411,45.96903),(13.509439,45.967428),(13.482257,45.989235),(13.481843,45.990372),(13.481223,45.991354),(13.480396,45.992284),(13.479466,45.993111),(13.474815,45.995747),(13.461793,46.006392),(13.477089,46.016055),(13.482257,46.018433),(13.490008,46.025564),(13.492799,46.032489),(13.490318,46.038948),(13.482257,46.044839),(13.505098,46.066027),(13.522585,46.075298),(13.616409,46.125041),(13.645037,46.161731),(13.641071,46.171405),(13.637389,46.180386),(13.627366,46.181733),(13.613928,46.183539),(13.584473,46.181317),(13.559048,46.184107),(13.528972,46.204829),(13.510162,46.213976),(13.482257,46.217904),(13.468304,46.223433),(13.438332,46.22488),(13.422829,46.228601),(13.437402,46.210927),(13.410116,46.207982),(13.401641,46.216663),(13.398127,46.230513),(13.384898,46.243122),(13.384795,46.243225),(13.384692,46.243328),(13.378594,46.268391),(13.373013,46.280277),(13.365261,46.290302),(13.391306,46.301568),(13.395638,46.306728),(13.409806,46.323608),(13.423242,46.344847),(13.434094,46.353864),(13.447323,46.354846),(13.459726,46.359032),(13.483704,46.37115),(13.530006,46.388332),(13.554397,46.405954),(13.575688,46.426676),(13.600182,46.442644),(13.634082,46.445719),(13.658783,46.445125),(13.67749,46.452075),(13.685853,46.464047),(13.688446,46.467759),(13.689893,46.493339),(13.695474,46.498636),(13.699194,46.504837),(13.701055,46.511891),(13.700951,46.519746),(13.716093,46.518867),(13.782135,46.507782),(13.795778,46.507886),(13.860683,46.51525),(13.890862,46.511787),(13.98233,46.481918),(13.998763,46.480523),(14.014922,46.482531),(14.032456,46.484709),(14.050026,46.484399),(14.066355,46.48104),(14.081032,46.47595),(14.137255,46.442438),(14.147933,46.440425),(14.149865,46.440061),(14.242323,46.438237),(14.362151,46.435875),(14.395844,46.440991),(14.40649,46.439337),(14.411244,46.434635),(14.414448,46.429002),(14.420029,46.424351),(14.437145,46.418884),(14.450931,46.414481),(14.467675,46.412672),(14.502194,46.418356),(14.515837,46.40536),(14.527102,46.388229),(14.540332,46.378643),(14.557695,46.38394),(14.562108,46.391737),(14.566997,46.400373),(14.575368,46.419726),(14.590148,46.434428),(14.599863,46.437167),(14.621567,46.43851),(14.631696,46.440577),(14.642031,46.445228),(14.662081,46.459698),(14.666629,46.460524),(14.672546,46.459791),(14.679961,46.458871),(14.687093,46.471221),(14.698772,46.480962),(14.703733,46.487758),(14.709727,46.492512),(14.726367,46.497706),(14.735255,46.493339),(14.760887,46.496284),(14.783004,46.503261),(14.788585,46.506646),(14.796663,46.519401),(14.807189,46.536024),(14.814519,46.551337),(14.822278,46.567546),(14.833647,46.584393),(14.85039,46.601136),(14.862999,46.604831),(14.877055,46.603642),(14.894063,46.605215),(14.897726,46.605554),(14.919507,46.615017),(14.933589,46.621135),(14.947955,46.619274),(14.967179,46.600257),(15.004386,46.636844),(15.061954,46.649557),(15.085723,46.647795),(15.105591,46.646323),(15.172557,46.64136),(15.204891,46.638963),(15.332784,46.64358),(15.388135,46.645578),(15.417591,46.637955),(15.435381,46.627195),(15.440018,46.62439),(15.462653,46.614649),(15.492625,46.618293),(15.511228,46.628369),(15.513939,46.632545),(15.517636,46.63824),(15.520308,46.64772),(15.52084,46.649608),(15.530659,46.663845),(15.545955,46.671881),(15.567349,46.675757),(15.58864,46.675963),(15.603729,46.673018),(15.616648,46.67555),(15.621745,46.678175),(15.626984,46.680873),(15.632978,46.689632),(15.632875,46.702473),(15.635975,46.717563),(15.652098,46.710819),(15.728683,46.70299),(15.755141,46.704024),(15.78461,46.7122),(15.822941,46.722834),(15.850743,46.724488),(15.878545,46.720715),(15.946344,46.697151),(15.986962,46.69219),(15.997917,46.686919),(16.016593,46.670757),(16.016727,46.670641),(16.016723,46.670691),(16.014557,46.693714),(16.003291,46.709191),(15.982001,46.718545),(15.970529,46.743014),(15.969702,46.760532),(15.970985,46.77505),(15.971252,46.778076),(15.978177,46.809134),(15.97735,46.816213),(15.972906,46.818435),(15.971976,46.820632),(15.981691,46.827685),(15.987582,46.830011),(16.028441,46.836947),(16.032024,46.837556),(16.052936,46.84606),(16.094035,46.862774),(16.130246,46.856708),(16.135376,46.855849),(16.179486,46.858468),(16.272009,46.863962),(16.282241,46.859932),(16.297392,46.847033),(16.301878,46.843214),(16.310663,46.84001),(16.325339,46.839442),(16.329783,46.834403),(16.327509,46.825463),(16.321825,46.813268),(16.3149,46.802002),(16.311097,46.797519),(16.302188,46.787016),(16.29949,46.77951),(16.298157,46.775802),(16.300431,46.772082),(16.314177,46.743324),(16.325546,46.733273),(16.334124,46.721749),(16.343426,46.714178)] +Swaziland [(31.863357,-25.989937),(31.891882,-25.983839),(31.949243,-25.958104),(31.975288,-25.980429),(32.00402,-25.994381),(32.070579,-26.009781),(32.057454,-26.0412),(32.062725,-26.077167),(32.074559,-26.114167),(32.081432,-26.14879),(32.077814,-26.175455),(32.044741,-26.25452),(32.039884,-26.283666),(32.052338,-26.386812),(32.059831,-26.414821),(32.107063,-26.500293),(32.117398,-26.582252),(32.113884,-26.840014),(32.097761,-26.833503),(32.073163,-26.811386),(32.057144,-26.808595),(31.990068,-26.808285),(31.992238,-26.838257),(31.975288,-26.926624),(31.959682,-27.00879),(31.942112,-27.10067),(31.944204,-27.162338),(31.944851,-27.181389),(31.947383,-27.255493),(31.952964,-27.270169),(31.959785,-27.281021),(31.964849,-27.291666),(31.967743,-27.303035),(31.96826,-27.316264),(31.878602,-27.315231),(31.782535,-27.313991),(31.636911,-27.312234),(31.52653,-27.31089),(31.459454,-27.298694),(31.35667,-27.267068),(31.280137,-27.243504),(31.244707,-27.232586),(31.157043,-27.205573),(31.141954,-27.196478),(31.126503,-27.182629),(31.078754,-27.11824),(30.976073,-27.035041),(30.953645,-27.000315),(30.949408,-26.975407),(30.959743,-26.936133),(30.960983,-26.911224),(30.955092,-26.891381),(30.944447,-26.876601),(30.915818,-26.849419),(30.902589,-26.831333),(30.885294,-26.785641),(30.880213,-26.772215),(30.868741,-26.784927),(30.853393,-26.796606),(30.836443,-26.805081),(30.819803,-26.807975),(30.80244,-26.808905),(30.79567,-26.785547),(30.785697,-26.716921),(30.784146,-26.578842),(30.782906,-26.472388),(30.804559,-26.397457),(30.897318,-26.291727),(30.897334,-26.291709),(30.969871,-26.209148),(31.037774,-26.100111),(31.091621,-25.983633),(31.106866,-25.930923),(31.119836,-25.910045),(31.20841,-25.838628),(31.309282,-25.757393),(31.337394,-25.744681),(31.372017,-25.736412),(31.401473,-25.735999),(31.426898,-25.743647),(31.532835,-25.805556),(31.638771,-25.867464),(31.7306,-25.921207),(31.746966,-25.93079),(31.834573,-25.982082),(31.863357,-25.989937)] +Sint Maarten [(-63.017569,18.033391),(-63.030629,18.01911),(-63.097646,18.035956),(-63.112172,18.043036),(-63.118886,18.0515),(-63.107004,18.059475),(-63.107004,18.062109),(-63.085886,18.058511),(-63.017569,18.033391)] +Syria [(42.236832,37.286304),(42.267218,37.274522),(42.272902,37.276744),(42.279207,37.282273),(42.285822,37.286562),(42.292023,37.285064),(42.296364,37.279689),(42.301428,37.269923),(42.305769,37.264548),(42.339875,37.242637),(42.346696,37.239769),(42.353208,37.227031),(42.335328,37.171169),(42.346696,37.158431),(42.354551,37.15241),(42.356515,37.138277),(42.357238,37.109984),(42.363646,37.09815),(42.371191,37.087944),(42.376875,37.076756),(42.377186,37.062235),(42.376806,37.062001),(42.34587,37.042908),(42.281894,36.994125),(42.281894,36.994022),(42.281894,36.99397),(42.281584,36.99397),(42.178438,36.90532),(41.978554,36.733625),(41.843781,36.617869),(41.817323,36.599731),(41.789935,36.589292),(41.479773,36.536117),(41.414867,36.527384),(41.385411,36.516377),(41.365361,36.494156),(41.365361,36.494053),(41.365258,36.494001),(41.365258,36.493898),(41.276994,36.354785),(41.268829,36.327965),(41.236583,36.077024),(41.236687,36.060332),(41.240614,36.043021),(41.266246,35.99429),(41.266349,35.994342),(41.266349,35.994238),(41.343657,35.857657),(41.354509,35.825566),(41.359263,35.792752),(41.363501,35.655241),(41.358023,35.623925),(41.34221,35.593694),(41.308458,35.552248),(41.261285,35.49432),(41.261285,35.494165),(41.261181,35.494165),(41.261078,35.494165),(41.25188,35.46409),(41.243095,35.366525),(41.20134,35.243018),(41.191521,35.182143),(41.192326,35.158904),(41.198033,34.994041),(41.206508,34.819323),(41.204234,34.793123),(41.195656,34.768473),(41.023986,34.49433),(41.023986,34.494175),(40.98802,34.42852),(40.965282,34.401855),(40.936033,34.386068),(40.690467,34.331497),(40.543809,34.257988),(40.433221,34.202539),(40.322634,34.147167),(40.212046,34.091796),(40.173111,34.072283),(40.101459,34.036373),(39.990871,33.980976),(39.880387,33.925605),(39.769696,33.870233),(39.659212,33.81481),(39.548624,33.759491),(39.438037,33.704094),(39.327449,33.648722),(39.216862,33.593325),(39.106274,33.537928),(38.995686,33.482479),(38.885099,33.427108),(38.774511,33.371685),(38.529565,33.244251),(38.315742,33.13118),(38.230875,33.086302),(38.056726,32.994344),(38.056726,32.994292),(37.929395,32.92533),(37.758036,32.832519),(37.586677,32.739837),(37.494606,32.690056),(37.415214,32.64713),(37.244062,32.554396),(37.133371,32.494581),(37.133371,32.494529),(37.133165,32.494529),(37.133165,32.494478),(36.980099,32.410038),(36.819385,32.316788),(36.806569,32.313042),(36.792513,32.313533),(36.728641,32.327795),(36.706937,32.328338),(36.689574,32.319656),(36.653504,32.342859),(36.516684,32.357014),(36.480181,32.360791),(36.463955,32.369395),(36.407627,32.374227),(36.387887,32.379317),(36.373108,32.386422),(36.285258,32.456935),(36.220765,32.494581),(36.188209,32.52228),(36.177357,32.527318),(36.17219,32.525923),(36.160821,32.517215),(36.15586,32.5152),(36.149865,32.51613),(36.13953,32.519541),(36.133226,32.520109),(36.096225,32.515872),(36.081906,32.516265),(36.06987,32.516595),(36.066253,32.517319),(36.066046,32.521608),(36.060465,32.533261),(36.015403,32.591164),(36.005998,32.607907),(36.005275,32.626692),(36.008272,32.643719),(36.003621,32.655088),(35.980263,32.656612),(35.965794,32.654365),(35.955355,32.657439),(35.94657,32.664441),(35.937475,32.674002),(35.941196,32.673536),(35.9444,32.677619),(35.945743,32.684104),(35.944193,32.690771),(35.940369,32.692502),(35.92745,32.692373),(35.922489,32.693768),(35.905229,32.708573),(35.895721,32.713276),(35.788234,32.734411),(35.779035,32.744282),(35.779035,32.744359),(35.779139,32.744462),(35.779139,32.744514),(35.774901,32.747279),(35.769734,32.748054),(35.763842,32.746969),(35.75759,32.744347),(35.784203,32.777949),(35.834226,32.827946),(35.841874,32.853577),(35.83805,32.866031),(35.849729,32.895823),(35.866885,32.920782),(35.874017,32.922333),(35.888073,32.944941),(35.864611,32.97773),(35.85903,32.99021),(35.845801,33.085423),(35.848902,33.098678),(35.811488,33.111908),(35.811488,33.126765),(35.822443,33.14157),(35.833399,33.161129),(35.830195,33.189991),(35.807664,33.201721),(35.803633,33.248463),(35.775625,33.264896),(35.768597,33.272699),(35.802083,33.31249),(35.763842,33.334401),(35.785753,33.342875),(35.793505,33.349929),(35.809938,33.360032),(35.812315,33.373365),(35.815415,33.378868),(35.816966,33.395198),(35.822443,33.401373),(35.8211,33.406722),(35.845116,33.418742),(35.870089,33.431242),(35.888486,33.440415),(35.919492,33.462351),(35.935408,33.494262),(35.921869,33.51457),(35.933238,33.527825),(35.956802,33.534207),(35.980263,33.533949),(35.99928,33.541261),(36.019847,33.55263),(36.035247,33.567797),(36.038451,33.586349),(36.029666,33.59764),(36.012923,33.608027),(35.994526,33.615701),(35.980263,33.619008),(35.956906,33.629938),(35.934788,33.6334),(35.921559,33.640299),(35.925383,33.661667),(35.929414,33.665078),(35.942436,33.669212),(35.94719,33.673088),(35.949878,33.6827),(35.946984,33.700838),(35.948431,33.70921),(35.955872,33.718124),(35.974165,33.732154),(35.980263,33.743549),(35.994009,33.760705),(36.027082,33.784296),(36.040518,33.805612),(36.05044,33.816438),(36.06646,33.821994),(36.085063,33.82605),(36.102426,33.832277),(36.13829,33.850622),(36.144904,33.847418),(36.157617,33.83406),(36.165678,33.829797),(36.186556,33.83021),(36.202679,33.838297),(36.216631,33.847754),(36.231824,33.852534),(36.249187,33.849744),(36.300554,33.828686),(36.338278,33.821193),(36.357501,33.823776),(36.369594,33.837006),(36.36763,33.857547),(36.35037,33.866409),(36.311096,33.87199),(36.28164,33.891111),(36.275336,33.897209),(36.268928,33.906769),(36.267171,33.910386),(36.288565,33.946508),(36.302311,33.964388),(36.31802,33.980511),(36.357811,34.009553),(36.391091,34.044719),(36.412175,34.053633),(36.423647,34.052806),(36.445144,34.04614),(36.45889,34.046708),(36.47522,34.053504),(36.480698,34.062754),(36.482662,34.07451),(36.488449,34.088644),(36.507983,34.109185),(36.552735,34.140992),(36.575886,34.173264),(36.604101,34.199102),(36.603554,34.200101),(36.59821,34.209851),(36.574026,34.229746),(36.567514,34.244138),(36.56276,34.262949),(36.570305,34.275868),(36.579917,34.286901),(36.581984,34.299897),(36.576816,34.307674),(36.570305,34.308966),(36.562967,34.308501),(36.555835,34.311085),(36.54519,34.320723),(36.523589,34.345889),(36.518628,34.353641),(36.515941,34.36165),(36.516768,34.369867),(36.519972,34.375061),(36.523589,34.379789),(36.526276,34.386688),(36.52979,34.403095),(36.530617,34.41418),(36.52514,34.422939),(36.509223,34.432421),(36.501885,34.430303),(36.494651,34.434256),(36.480181,34.449139),(36.463231,34.455237),(36.449795,34.464538),(36.439873,34.477457),(36.433466,34.494175),(36.433466,34.49433),(36.41972,34.498335),(36.392331,34.500143),(36.363082,34.499032),(36.343652,34.494175),(36.340965,34.493477),(36.338174,34.493296),(36.335384,34.493477),(36.332697,34.494175),(36.329851,34.498603),(36.319881,34.514122),(36.336624,34.52885),(36.364012,34.541097),(36.383546,34.553809),(36.388094,34.569519),(36.386853,34.584247),(36.388921,34.596236),(36.4037,34.603832),(36.418479,34.600318),(36.429125,34.593187),(36.436256,34.597838),(36.440184,34.62936),(36.415999,34.622901),(36.391194,34.622487),(36.367526,34.629205),(36.347373,34.64414),(36.323808,34.679486),(36.308925,34.687548),(36.288151,34.675559),(36.284844,34.667911),(36.284431,34.648326),(36.28071,34.639127),(36.271512,34.630962),(36.26159,34.627242),(36.201232,34.624451),(36.195134,34.626208),(36.183352,34.633494),(36.178287,34.635303),(36.17219,34.634063),(36.160201,34.628068),(36.15586,34.626931),(36.11214,34.629532),(36.087234,34.631014),(36.060775,34.627913),(36.037934,34.62843),(36.01623,34.633649),(35.998763,34.64538),(35.991425,34.648222),(35.98264,34.650238),(35.9699,34.649849),(35.965668,34.668443),(35.947439,34.69953),(35.940929,34.726223),(35.931163,34.740953),(35.928966,34.749823),(35.928966,34.790717),(35.926036,34.796942),(35.908458,34.821763),(35.904552,34.831773),(35.899099,34.852769),(35.866873,34.924221),(35.872895,34.926907),(35.873546,34.931627),(35.879568,34.938056),(35.881358,34.944973),(35.879568,34.95189),(35.873546,34.958319),(35.873546,34.965155),(35.878591,34.96955),(35.878917,34.97016),(35.876638,34.971666),(35.873546,34.978827),(35.881602,34.992865),(35.88738,35.00019),(35.895356,35.006781),(35.900564,35.021918),(35.897309,35.036566),(35.891449,35.049954),(35.887869,35.061347),(35.887869,35.109198),(35.894216,35.12108),(35.941254,35.180569),(35.962413,35.197943),(35.953298,35.224799),(35.915294,35.287909),(35.928966,35.321479),(35.924083,35.338528),(35.916677,35.403306),(35.918956,35.41767),(35.908865,35.425727),(35.860606,35.479071),(35.840099,35.487372),(35.830089,35.493476),(35.825857,35.503323),(35.81837,35.508938),(35.802257,35.506903),(35.786794,35.502183),(35.781261,35.499579),(35.770518,35.504218),(35.771983,35.515448),(35.77711,35.52912),(35.778087,35.541164),(35.771983,35.546332),(35.737071,35.561672),(35.73878,35.566596),(35.740896,35.576483),(35.743337,35.582099),(35.737071,35.582099),(35.723399,35.575914),(35.723399,35.582099),(35.743419,35.587958),(35.763357,35.598293),(35.778494,35.612738),(35.784353,35.630561),(35.782074,35.64175),(35.773204,35.655463),(35.771169,35.667792),(35.776622,35.675116),(35.800059,35.681464),(35.838552,35.742092),(35.840343,35.747463),(35.840099,35.770819),(35.835948,35.789984),(35.825369,35.813463),(35.81186,35.835395),(35.798595,35.849677),(35.846853,35.847235),(35.87086,35.851793),(35.881033,35.866685),(35.885265,35.885972),(35.911305,35.91775),(35.920835,35.915122),(35.940576,35.918377),(35.96073,35.924372),(35.980263,35.926852),(35.992769,35.915277),(35.993079,35.902357),(35.990082,35.889283),(35.992356,35.877346),(36.003931,35.869181),(36.019434,35.866184),(36.05075,35.865409),(36.080309,35.854195),(36.138497,35.819779),(36.155308,35.822232),(36.157617,35.822569),(36.168779,35.852076),(36.174877,35.922666),(36.196891,35.951708),(36.229034,35.961165),(36.253115,35.955636),(36.269031,35.958736),(36.277403,35.99398),(36.277403,35.994031),(36.277506,35.994187),(36.277506,35.994238),(36.29735,36.000749),(36.336727,35.988244),(36.358018,35.99398),(36.355538,36.022402),(36.358638,36.166992),(36.360498,36.181669),(36.366286,36.189213),(36.374451,36.19588),(36.375795,36.20451),(36.361429,36.218152),(36.373004,36.227609),(36.385613,36.215465),(36.398119,36.20823),(36.411865,36.204458),(36.439253,36.201409),(36.445248,36.19991),(36.450726,36.19991),(36.4592,36.203114),(36.463955,36.208799),(36.465298,36.21593),(36.468916,36.22239),(36.480181,36.225542),(36.498578,36.227867),(36.574439,36.218359),(36.593456,36.2181),(36.664253,36.229004),(36.67004,36.237324),(36.66911,36.259855),(36.665493,36.274014),(36.658465,36.290499),(36.648761,36.305719),(36.648646,36.305899),(36.637071,36.316802),(36.620741,36.322022),(36.587771,36.324812),(36.577643,36.332874),(36.58219,36.333081),(36.587771,36.342124),(36.594283,36.35711),(36.594489,36.365947),(36.593352,36.373492),(36.590562,36.380364),(36.585704,36.387031),(36.580847,36.389873),(36.565034,36.395609),(36.558006,36.400622),(36.552735,36.408166),(36.533821,36.462478),(36.531237,36.479015),(36.535475,36.494001),(36.565344,36.5325),(36.569995,36.575701),(36.569271,36.620143),(36.582811,36.662414),(36.594696,36.685824),(36.598107,36.705461),(36.598934,36.724788),(36.603274,36.746957),(36.615677,36.766594),(36.632006,36.784319),(36.643272,36.803646),(36.639861,36.828089),(36.649163,36.828554),(36.658568,36.827521),(36.659563,36.827243),(36.843673,36.775844),(36.906822,36.772589),(36.925942,36.768971),(36.945889,36.762667),(36.964699,36.75383),(36.980099,36.742255),(37.010588,36.719517),(37.018443,36.706649),(37.019476,36.685824),(37.010795,36.653733),(37.014515,36.642261),(37.033326,36.628721),(37.053066,36.619936),(37.062368,36.622107),(37.070119,36.631512),(37.085622,36.644173),(37.104432,36.650994),(37.120969,36.649909),(37.137402,36.645878),(37.156109,36.643914),(37.219671,36.657143),(37.241892,36.65859),(37.404466,36.634458),(37.446117,36.634199),(37.593395,36.710525),(37.654063,36.732126),(37.819738,36.760548),(37.980038,36.819666),(38.007943,36.825764),(38.026005,36.835006),(38.122975,36.884623),(38.190051,36.905526),(38.224261,36.908394),(38.28989,36.901702),(38.479956,36.855736),(38.529358,36.833722),(38.635192,36.744039),(38.66413,36.719517),(38.725005,36.693937),(38.795389,36.686651),(38.957963,36.692904),(38.979977,36.698175),(39.03217,36.701172),(39.185856,36.659521),(39.239599,36.661278),(39.441708,36.692373),(39.765252,36.742151),(39.979812,36.806953),(40.079238,36.854857),(40.115205,36.864728),(40.152722,36.87036),(40.190136,36.884416),(40.261409,36.922785),(40.393741,36.994022),(40.413894,37.004022),(40.435185,37.01061),(40.456993,37.014124),(40.479834,37.015158),(40.525722,37.025881),(40.659461,37.085257),(40.708967,37.100476),(40.896449,37.122696),(41.135091,37.084249),(41.179739,37.069625),(41.20134,37.064974),(41.479773,37.075568),(41.896365,37.154283),(42.009249,37.175613),(42.052968,37.196645),(42.128312,37.253283),(42.178541,37.306303),(42.193011,37.313227),(42.211201,37.324906),(42.22257,37.313951),(42.22381,37.302375),(42.222156,37.292402),(42.22319,37.288139),(42.236832,37.286304)] +Chad [(23.981306,19.496124),(23.981512,19.263838),(23.981719,19.031553),(23.981926,18.799293),(23.982133,18.567033),(23.982236,18.334799),(23.982443,18.102514),(23.982753,17.870228),(23.982856,17.637943),(23.983063,17.405657),(23.983269,17.173371),(23.983476,16.941138),(23.983683,16.7088),(23.983786,16.476515),(23.983993,16.244229),(23.984303,16.011944),(23.984406,15.779658),(23.984406,15.72194),(23.984406,15.72116),(23.972624,15.691085),(23.945546,15.692222),(23.829067,15.731031),(23.707524,15.748859),(23.592699,15.749014),(23.52707,15.735165),(23.395812,15.688346),(23.320571,15.681318),(23.166782,15.712944),(23.119249,15.707224),(23.094642,15.704262),(23.068493,15.686692),(23.004518,15.611425),(22.92566,15.563935),(22.906746,15.541404),(22.899511,15.510191),(22.906849,15.481408),(22.923593,15.455569),(22.944987,15.433116),(22.966484,15.404823),(22.976406,15.373636),(22.97837,15.340202),(22.965657,15.223904),(22.958009,15.201631),(22.913257,15.121688),(22.905506,15.112567),(22.871606,15.0997),(22.848765,15.087504),(22.829025,15.071639),(22.738901,14.97981),(22.727222,14.959036),(22.721951,14.934671),(22.721021,14.915938),(22.715337,14.899428),(22.695493,14.88147),(22.658906,14.857415),(22.650844,14.841938),(22.650844,14.816151),(22.659009,14.761271),(22.66459,14.743752),(22.67968,14.711816),(22.681437,14.702928),(22.676579,14.688975),(22.666347,14.681741),(22.465429,14.629289),(22.422745,14.609084),(22.382334,14.579111),(22.363523,14.543532),(22.386364,14.506532),(22.417164,14.484104),(22.424915,14.470436),(22.439074,14.362923),(22.442382,14.356928),(22.447343,14.351632),(22.45096,14.345792),(22.449926,14.338377),(22.444862,14.333364),(22.431323,14.327214),(22.426982,14.323003),(22.418094,14.30595),(22.41706,14.298095),(22.419954,14.286235),(22.429049,14.264608),(22.441038,14.249855),(22.457678,14.241147),(22.514109,14.231458),(22.531885,14.220632),(22.540877,14.201176),(22.547698,14.169033),(22.546355,14.139707),(22.531472,14.122627),(22.508217,14.113636),(22.481449,14.108546),(22.458711,14.096117),(22.421608,14.06214),(22.402281,14.049299),(22.243531,13.975427),(22.214695,13.956617),(22.190614,13.932794),(22.180762,13.920555),(22.099353,13.819416),(22.074962,13.780323),(22.073722,13.771357),(22.09708,13.749756),(22.112893,13.729835),(22.116303,13.715185),(22.11434,13.699708),(22.11434,13.677383),(22.132116,13.638652),(22.195885,13.580464),(22.210561,13.541733),(22.211181,13.484191),(22.215625,13.464993),(22.228648,13.441119),(22.263995,13.399183),(22.275984,13.376316),(22.267612,13.334562),(22.232265,13.289035),(22.139971,13.193511),(22.123435,13.182168),(22.016051,13.140233),(21.998378,13.130595),(21.964065,13.098349),(21.935126,13.059152),(21.85296,12.905725),(21.827846,12.831104),(21.811826,12.799969),(21.809449,12.793665),(21.813686,12.782296),(21.840868,12.748939),(21.880142,12.676282),(21.900813,12.656438),(21.935953,12.63954),(21.97719,12.63184),(22.019668,12.631426),(22.058736,12.636697),(22.105865,12.650392),(22.144105,12.671269),(22.176248,12.7015),(22.204877,12.743358),(22.33014,12.661451),(22.43246,12.62383),(22.445689,12.611066),(22.395873,12.496086),(22.372825,12.463116),(22.374892,12.450869),(22.407965,12.399761),(22.481449,12.176674),(22.484033,12.164737),(22.484756,12.152541),(22.483826,12.140345),(22.458091,12.03043),(22.464499,12.032962),(22.470494,12.036114),(22.481449,12.044279),(22.546458,12.064433),(22.585525,12.071357),(22.598858,12.063244),(22.607333,12.077714),(22.612397,12.072804),(22.613534,12.05725),(22.610537,12.039628),(22.592863,11.988933),(22.537053,11.68089),(22.541704,11.632986),(22.561754,11.586012),(22.592347,11.543663),(22.628107,11.509841),(22.662523,11.493072),(22.743035,11.466097),(22.76877,11.442326),(22.771561,11.433308),(22.771871,11.403181),(22.781792,11.398892),(22.87698,11.40884),(22.900442,11.408245),(22.914808,11.396101),(22.928347,11.32515),(22.953668,11.250942),(22.954536,11.237843),(22.956459,11.2088),(22.952015,11.191049),(22.935168,11.155883),(22.928967,11.137926),(22.92566,11.118134),(22.925143,11.097954),(22.922352,11.087076),(22.906539,11.069894),(22.900235,11.059895),(22.861064,10.919154),(22.805977,10.924502),(22.745102,10.943803),(22.719884,10.964655),(22.682677,10.974137),(22.673169,10.975068),(22.638339,10.974137),(22.62821,10.976127),(22.60909,10.985222),(22.600822,10.987806),(22.57705,10.985119),(22.55576,10.978969),(22.534676,10.98052),(22.511938,11.000828),(22.502843,10.992173),(22.490751,10.993154),(22.476281,10.99796),(22.460468,11.000828),(22.447136,10.99827),(22.437627,10.991552),(22.419231,10.970727),(22.407035,10.963053),(22.391842,10.958505),(22.36469,10.954209),(22.361146,10.953648),(22.339442,10.947731),(22.318772,10.939359),(22.305956,10.932564),(22.287249,10.91595),(22.2765,10.908534),(22.268439,10.908999),(22.253039,10.915304),(22.24012,10.905899),(22.229371,10.891972),(22.200639,10.868666),(22.189787,10.837298),(22.176351,10.816214),(22.148239,10.830761),(22.132426,10.828539),(22.048607,10.836988),(22.029487,10.828746),(22.018325,10.809884),(22.0114,10.789291),(22.004889,10.775519),(22.014604,10.754564),(22.003855,10.743273),(21.943084,10.728261),(21.925617,10.720122),(21.895025,10.699193),(21.872081,10.677592),(21.86836,10.676223),(21.863606,10.667929),(21.852754,10.670151),(21.83291,10.679944),(21.822575,10.678755),(21.803558,10.673665),(21.795393,10.672476),(21.784851,10.669324),(21.778753,10.66227),(21.774205,10.655165),(21.768418,10.651987),(21.753431,10.650721),(21.736482,10.646173),(21.722632,10.636716),(21.716845,10.621007),(21.714674,10.601395),(21.705476,10.571811),(21.703305,10.552406),(21.705476,10.53202),(21.714674,10.493702),(21.716845,10.47732),(21.720462,10.468018),(21.738032,10.44802),(21.744233,10.439106),(21.74444,10.432439),(21.742786,10.425773),(21.743613,10.418978),(21.751054,10.41182),(21.720462,10.360816),(21.716845,10.339809),(21.717775,10.328983),(21.722116,10.314178),(21.723046,10.305987),(21.718808,10.296634),(21.708886,10.293533),(21.697414,10.292422),(21.688939,10.288908),(21.67695,10.269168),(21.668889,10.249195),(21.65628,10.233666),(21.630648,10.227439),(21.625274,10.224493),(21.593441,10.214546),(21.589721,10.216613),(21.579282,10.212272),(21.566673,10.214494),(21.554477,10.218654),(21.544969,10.219997),(21.513239,10.200515),(21.485437,10.164316),(21.433348,10.046055),(21.406889,10.005566),(21.374333,9.973113),(21.339503,9.95991),(21.326067,9.962752),(21.28514,9.978591),(21.27129,9.987247),(21.256924,9.975749),(21.205661,9.916838),(21.198427,9.902988),(21.195429,9.887305),(21.187264,9.885134),(21.131971,9.849426),(21.121739,9.831907),(21.106753,9.79545),(21.105926,9.791884),(21.106753,9.778061),(21.105202,9.77403),(21.101585,9.774237),(21.097037,9.775373),(21.09311,9.77434),(21.080294,9.762609),(21.073163,9.757648),(21.065825,9.754496),(21.062207,9.756201),(21.052906,9.765891),(21.048358,9.768165),(21.042674,9.767079),(21.04009,9.764754),(21.039056,9.76217),(21.037816,9.760671),(21.032339,9.75801),(21.025621,9.753256),(21.019936,9.747933),(21.017352,9.743592),(21.014252,9.724472),(21.000092,9.697394),(20.996888,9.682175),(20.996062,9.648301),(20.989964,9.635615),(20.975804,9.630964),(20.975804,9.624168),(20.980145,9.619931),(20.981799,9.616778),(20.983143,9.603678),(20.96764,9.610603),(20.962265,9.606934),(20.960508,9.598123),(20.955961,9.589416),(20.934257,9.577065),(20.925058,9.569598),(20.921234,9.558978),(20.912656,9.544328),(20.874209,9.502496),(20.86377,9.493789),(20.841446,9.484409),(20.834314,9.462473),(20.832661,9.437255),(20.82615,9.418083),(20.820258,9.416222),(20.813884,9.418847),(20.81323,9.419116),(20.806719,9.423328),(20.801965,9.42555),(20.798244,9.423379),(20.792353,9.414),(20.788322,9.411881),(20.77654,9.407799),(20.771062,9.398058),(20.766618,9.38656),(20.757937,9.377129),(20.750495,9.384545),(20.740883,9.377129),(20.695822,9.363461),(20.654894,9.342971),(20.667916,9.302017),(20.616653,9.302017),(20.609729,9.302792),(20.592882,9.308218),(20.592262,9.308063),(20.573555,9.309149),(20.572315,9.308218),(20.550921,9.320259),(20.541826,9.321629),(20.538208,9.311939),(20.537278,9.299201),(20.533661,9.289641),(20.526426,9.283621),(20.514231,9.281502),(20.496144,9.270882),(20.502655,9.247421),(20.51299,9.223883),(20.507203,9.213263),(20.481778,9.204659),(20.467618,9.184143),(20.455423,9.159313),(20.435166,9.138126),(20.423073,9.143241),(20.412428,9.142053),(20.40292,9.136989),(20.384419,9.123579),(20.378322,9.120065),(20.359408,9.116421),(20.276829,9.120736),(20.256985,9.116421),(20.234454,9.13456),(20.222982,9.14195),(20.212647,9.144973),(20.197971,9.140503),(20.169549,9.120891),(20.154563,9.116421),(20.137613,9.121822),(20.125727,9.133785),(20.117149,9.145748),(20.109604,9.151174),(20.101026,9.148073),(20.099579,9.141174),(20.100509,9.134146),(20.099372,9.13071),(20.090587,9.131123),(20.076945,9.13673),(20.068676,9.138126),(20.060512,9.134353),(20.031159,9.11022),(20.028369,9.104562),(20.029919,9.098981),(20.030332,9.093865),(20.024338,9.089756),(20.01793,9.091048),(20.014416,9.106345),(20.006871,9.11022),(20.002944,9.108515),(19.999533,9.104303),(19.997156,9.098619),(19.996329,9.092831),(19.993022,9.084589),(19.985477,9.083193),(19.976486,9.084175),(19.969044,9.082883),(19.943413,9.065882),(19.932091,9.063331),(19.928737,9.062575),(19.914474,9.069267),(19.902175,9.0518),(19.889463,9.046374),(19.80554,9.051128),(19.784663,9.048751),(19.758411,9.041982),(19.746836,9.04131),(19.738154,9.039372),(19.713969,9.02914),(19.709008,9.024567),(19.700017,9.020587),(19.656402,9.021259),(19.640072,9.013999),(19.613614,9.031672),(19.583125,9.025342),(19.553772,9.013327),(19.530828,9.013999),(19.52132,9.008831),(19.515842,9.009451),(19.511811,9.012293),(19.506644,9.013999),(19.430162,9.012862),(19.420964,9.017435),(19.38262,9.003198),(19.369391,9.000382),(19.352234,9.002061),(19.333321,9.006557),(19.316268,9.01312),(19.304795,9.020846),(19.295494,9.009503),(19.285778,9.01281),(19.275236,9.021983),(19.263248,9.028261),(19.253429,9.027951),(19.232862,9.022293),(19.192037,9.020174),(19.179635,9.015265),(19.174571,9.003767),(19.168783,9.002216),(19.142118,9.008676),(19.133643,9.007177),(19.126718,9.007177),(19.10057,9.015265),(19.060676,9.00418),(19.021919,8.985215),(18.999491,8.969635),(18.984815,8.956431),(18.97851,8.949455),(18.975927,8.941988),(18.971896,8.938215),(18.952052,8.931988),(18.936446,8.923358),(18.928591,8.921679),(18.922907,8.918216),(18.920736,8.907855),(18.917739,8.898812),(18.910608,8.894239),(18.901409,8.89398),(18.892727,8.897933),(18.86968,8.864111),(18.869783,8.849409),(18.886526,8.835844),(18.902959,8.84481),(18.909677,8.835327),(18.912468,8.818403),(18.917325,8.805148),(18.929108,8.796544),(19.048687,8.745669),(19.057782,8.729701),(19.073492,8.720528),(19.103877,8.698049),(19.124135,8.675079),(19.091475,8.652858),(19.081657,8.637226),(19.072261,8.631872),(19.061296,8.625624),(19.020472,8.545578),(18.920529,8.432122),(18.910401,8.412976),(18.901306,8.388636),(18.887457,8.370963),(18.8549,8.339802),(18.813042,8.276421),(18.791235,8.257378),(18.773768,8.248619),(18.715064,8.228672),(18.672586,8.20751),(18.638583,8.177642),(18.618636,8.138652),(18.617912,8.090127),(18.589283,8.047882),(18.508255,8.030674),(18.070452,8.019202),(17.977228,7.997187),(17.897853,7.967473),(17.858785,7.960445),(17.817238,7.962099),(17.679778,7.985198),(17.661795,7.986284),(17.639884,7.985043),(17.62066,7.978739),(17.59999,7.950369),(17.580766,7.940602),(17.559786,7.934711),(17.523819,7.93099),(17.503665,7.926236),(17.487232,7.914453),(17.478344,7.891819),(17.466355,7.884119),(17.419122,7.898227),(17.405997,7.883034),(17.385739,7.870477),(17.250864,7.822831),(17.234637,7.811617),(17.23379,7.810801),(17.220685,7.798181),(17.214484,7.786813),(17.211073,7.768312),(17.204562,7.763817),(17.196397,7.76516),(17.188645,7.764127),(17.170559,7.747539),(17.135522,7.705112),(17.116298,7.68687),(17.101932,7.677724),(17.095525,7.67824),(17.090254,7.683822),(17.079091,7.689919),(17.059351,7.696534),(17.045605,7.6847),(17.041058,7.675502),(17.042091,7.667027),(17.038991,7.662479),(17.008295,7.667647),(16.997546,7.666717),(16.988968,7.660774),(16.98194,7.648733),(16.962716,7.650697),(16.919618,7.644082),(16.880654,7.632869),(16.865461,7.624445),(16.854816,7.611475),(16.847168,7.591579),(16.848098,7.584706),(16.852439,7.580262),(16.855849,7.575404),(16.853886,7.567498),(16.850372,7.565896),(16.839623,7.567446),(16.836729,7.567498),(16.815071,7.549544),(16.812854,7.547706),(16.805516,7.543675),(16.782365,7.541143),(16.768619,7.550238),(16.746709,7.586566),(16.709812,7.627753),(16.686867,7.645788),(16.6632,7.657415),(16.624546,7.66868),(16.61421,7.679584),(16.609869,7.701598),(16.611833,7.713897),(16.616174,7.723871),(16.618138,7.734309),(16.613073,7.74821),(16.605219,7.757202),(16.596434,7.761129),(16.586822,7.763558),(16.576383,7.767796),(16.560157,7.779733),(16.549305,7.794719),(16.54486,7.813013),(16.550235,7.843502),(16.550752,7.8527),(16.550131,7.861692),(16.548685,7.870012),(16.509204,7.858281),(16.491737,7.849238),(16.475717,7.835802),(16.469413,7.825828),(16.457217,7.799628),(16.450913,7.792084),(16.437373,7.788363),(16.427245,7.791464),(16.41815,7.795856),(16.407401,7.796063),(16.392208,7.783609),(16.387041,7.762628),(16.387144,7.694674),(16.38301,7.680669),(16.370814,7.672504),(16.282758,7.660102),(16.26188,7.651885),(16.227257,7.625582),(16.207207,7.613542),(16.185606,7.610751),(16.162662,7.611113),(16.128762,7.599486),(16.0652,7.591217),(16.042979,7.583931),(16.026339,7.574888),(16.012283,7.560315),(15.990372,7.529412),(15.975696,7.515201),(15.94314,7.495306),(15.92526,7.488175),(15.793899,7.457996),(15.758345,7.455567),(15.720001,7.468641),(15.668532,7.516287),(15.624813,7.519749),(15.55195,7.509879),(15.515569,7.512204),(15.481049,7.523263),(15.521977,7.576076),(15.548952,7.630801),(15.562181,7.690178),(15.562905,7.792445),(15.540787,7.796838),(15.509368,7.804021),(15.487871,7.804951),(15.440742,7.839419),(15.406532,7.921585),(15.345347,8.13599),(15.210706,8.421822),(15.183703,8.479148),(15.16851,8.498604),(15.110736,8.555138),(15.068568,8.623867),(15.051928,8.643789),(15.031258,8.658749),(15.005833,8.66663),(14.968523,8.672159),(14.955087,8.676216),(14.951469,8.68283),(14.951469,8.692106),(14.949092,8.704276),(14.940101,8.729649),(14.934416,8.739003),(14.927285,8.745075),(14.919947,8.74771),(14.913332,8.752438),(14.908268,8.764841),(14.89938,8.774323),(14.859899,8.803314),(14.846049,8.810988),(14.836748,8.813003),(14.827963,8.813158),(14.819178,8.811608),(14.809876,8.808611),(14.793856,8.813623),(14.571699,8.99099),(14.349542,9.168356),(14.331145,9.200215),(14.321327,9.243158),(14.036486,9.568771),(13.947603,9.637759),(13.945949,9.652642),(14.006721,9.739277),(14.088473,9.809635),(14.119789,9.85201),(14.168365,9.94774),(14.170638,9.957843),(14.171155,9.96761),(14.173532,9.975025),(14.181697,9.978178),(14.196341,9.979147),(14.440493,9.995308),(14.732465,9.923814),(14.772566,9.921747),(14.898139,9.960478),(14.944131,9.958825),(15.002422,9.945053),(15.033015,9.942857),(15.06123,9.949239),(15.071669,9.955957),(15.089445,9.972183),(15.100711,9.978901),(15.109599,9.981537),(15.155488,9.986523),(15.214916,9.984095),(15.382968,9.930196),(15.439398,9.931695),(15.663777,9.98611),(15.681244,9.991278),(15.637939,10.029957),(15.602799,10.04099),(15.536137,10.080523),(15.490144,10.120107),(15.490661,10.124448),(15.476399,10.132742),(15.439192,10.185245),(15.301422,10.311749),(15.29057,10.328983),(15.284266,10.349292),(15.282199,10.374588),(15.278374,10.394276),(15.268763,10.406343),(15.255637,10.41704),(15.241167,10.432904),(15.227215,10.470137),(15.218326,10.487216),(15.198173,10.496492),(15.193315,10.501195),(15.186597,10.505871),(15.176055,10.50799),(15.164686,10.509075),(15.153628,10.511969),(15.144429,10.51631),(15.138228,10.521659),(15.131717,10.540701),(15.132337,10.565403),(15.138435,10.589691),(15.14846,10.607338),(15.149907,10.623125),(15.142259,10.647207),(15.065881,10.793115),(15.06309,10.830761),(15.075596,10.873498),(15.079007,10.898147),(15.072702,10.915769),(15.06247,10.930703),(15.035185,10.994627),(15.02883,11.080218),(15.021233,11.182549),(15.028261,11.244483),(15.033325,11.26027),(15.056373,11.29342),(15.06309,11.309931),(15.062264,11.320034),(15.057819,11.325356),(15.052548,11.329801),(15.049448,11.337268),(15.049448,11.348714),(15.054305,11.364088),(15.06061,11.416126),(15.067018,11.435556),(15.076113,11.453307),(15.122312,11.503227),(15.135644,11.530822),(15.123862,11.563171),(15.09575,11.598156),(15.085208,11.615881),(15.069395,11.660788),(15.066501,11.680632),(15.068258,11.700114),(15.076113,11.721456),(15.079834,11.722593),(15.086345,11.72218),(15.093063,11.722903),(15.097197,11.727657),(15.095957,11.734117),(15.085311,11.744039),(15.083554,11.748173),(15.089135,11.75763),(15.105362,11.772719),(15.110943,11.782899),(15.086345,11.840467),(15.079834,11.851216),(15.06278,11.853489),(15.050998,11.861603),(15.044177,11.877312),(15.042006,11.902375),(15.046967,11.910179),(15.056579,11.918447),(15.063401,11.927283),(15.05937,11.936792),(15.055546,11.942476),(15.050585,11.952863),(15.048311,11.962785),(15.052548,11.967229),(15.081177,11.971673),(15.076836,11.982836),(15.05968,11.997305),(15.049448,12.011929),(15.051205,12.024228),(15.053685,12.031877),(15.053065,12.038026),(15.045727,12.046088),(15.04056,12.055648),(15.04087,12.067585),(15.04459,12.078385),(15.049448,12.084586),(15.030431,12.100916),(15.011827,12.108616),(14.993844,12.106704),(14.976791,12.094147),(14.964802,12.092441),(14.950746,12.103345),(14.928732,12.128615),(14.9031,12.145875),(14.898036,12.152799),(14.894832,12.167372),(14.899896,12.171765),(14.907441,12.17347),(14.911575,12.180136),(14.910128,12.190368),(14.905891,12.195639),(14.90093,12.200032),(14.898036,12.207473),(14.898036,12.219462),(14.9031,12.236257),(14.904857,12.248401),(14.906304,12.317957),(14.908268,12.326897),(14.891215,12.402655),(14.877469,12.427201),(14.876849,12.431594),(14.878502,12.443066),(14.877469,12.447045),(14.872404,12.450404),(14.865893,12.452574),(14.861862,12.452006),(14.863826,12.447045),(14.855455,12.454538),(14.85101,12.455158),(14.849563,12.457019),(14.850184,12.468129),(14.852044,12.474692),(14.860105,12.490091),(14.863826,12.495466),(14.830753,12.618249),(14.819178,12.638816),(14.786208,12.63122),(14.768845,12.633235),(14.761403,12.649358),(14.758716,12.658815),(14.752102,12.668944),(14.743317,12.67716),(14.734118,12.680416),(14.728847,12.677212),(14.713654,12.65251),(14.702079,12.668995),(14.716755,12.70181),(14.709934,12.718243),(14.694017,12.723721),(14.664458,12.715969),(14.648129,12.725116),(14.641721,12.730904),(14.624254,12.741885),(14.62074,12.747853),(14.620327,12.754055),(14.618363,12.759196),(14.610612,12.762349),(14.603997,12.760798),(14.584877,12.746355),(14.575265,12.744908),(14.570717,12.750386),(14.569374,12.75961),(14.569374,12.769403),(14.560692,12.766224),(14.554801,12.766896),(14.55108,12.771573),(14.549013,12.780461),(14.549013,12.818211),(14.53103,12.836246),(14.500437,12.859113),(14.490102,12.873608),(14.490619,12.886346),(14.506122,12.93208),(14.507672,12.95244),(14.504675,12.969003),(14.496303,12.983808),(14.482144,12.99882),(14.481041,13.000508),(14.435429,13.070289),(14.418169,13.081141),(14.064908,13.077988),(13.836111,13.391044),(13.607314,13.7041),(13.600182,13.735984),(13.592948,13.767843),(13.585816,13.799727),(13.578582,13.831534),(13.57145,13.863418),(13.564319,13.895225),(13.557188,13.927161),(13.549953,13.958994),(13.542821,13.990853),(13.53569,14.022737),(13.528455,14.054518),(13.521324,14.086428),(13.514193,14.118235),(13.506958,14.150119),(13.499723,14.181978),(13.492695,14.213862),(13.482257,14.259777),(13.468304,14.310678),(13.449184,14.380131),(13.449494,14.439042),(13.482257,14.483587),(13.507785,14.495964),(13.543855,14.510562),(13.584369,14.513818),(13.608052,14.518266),(13.624264,14.521311),(13.657853,14.548725),(13.665605,14.56689),(13.666742,14.585519),(13.660334,14.623734),(13.657026,14.629651),(13.646278,14.639056),(13.644727,14.644249),(13.648345,14.649417),(13.668085,14.662879),(13.700021,14.697734),(13.709995,14.705124),(13.730045,14.709646),(13.749165,14.711248),(13.764358,14.719077),(13.773247,14.742512),(13.772006,14.762873),(13.75795,14.805532),(13.75392,14.825944),(13.75516,14.847209),(13.760534,14.866355),(13.775417,14.897438),(13.808077,14.965573),(13.833915,15.019601),(13.862957,15.059056),(13.892826,15.0997),(13.922592,15.140498),(13.952564,15.181219),(13.98233,15.221992),(14.012199,15.262687),(14.042068,15.303434),(14.071833,15.344181),(14.101702,15.384876),(14.131571,15.425545),(14.16144,15.466292),(14.191206,15.507039),(14.221178,15.547734),(14.250944,15.588455),(14.280709,15.629254),(14.310682,15.669949),(14.340447,15.710722),(14.368973,15.749634),(14.423543,15.806323),(14.482144,15.86725),(14.520798,15.907557),(14.576919,15.965797),(14.633143,16.024243),(14.689263,16.082534),(14.745384,16.140876),(14.801401,16.199219),(14.857418,16.257613),(14.913539,16.315904),(14.969659,16.374247),(15.02578,16.432538),(15.081797,16.490881),(15.137918,16.549275),(15.194039,16.607566),(15.250159,16.665909),(15.30628,16.7242),(15.3624,16.782646),(15.418418,16.840885),(15.452421,16.876232),(15.465547,16.89468),(15.468517,16.90491),(15.471954,16.916746),(15.474125,16.942068),(15.478259,16.987698),(15.48229,17.033277),(15.486217,17.078907),(15.490248,17.124537),(15.494279,17.170116),(15.498309,17.215746),(15.50234,17.261376),(15.506371,17.307058),(15.510505,17.352637),(15.514536,17.398267),(15.518567,17.443846),(15.522597,17.489528),(15.526628,17.535107),(15.530659,17.580737),(15.53469,17.626367),(15.538617,17.672049),(15.542648,17.717679),(15.546782,17.76331),(15.550813,17.808888),(15.554843,17.85457),(15.558874,17.900149),(15.562905,17.945779),(15.566936,17.991409),(15.567698,18.000039),(15.570966,18.03704),(15.574997,18.082644),(15.579028,18.128249),(15.583162,18.173879),(15.587193,18.219483),(15.59112,18.265088),(15.595151,18.310718),(15.599182,18.356348),(15.603213,18.402004),(15.607243,18.447583),(15.611274,18.493239),(15.615305,18.538818),(15.619439,18.584474),(15.62347,18.630078),(15.6275,18.675709),(15.631531,18.721313),(15.635562,18.766943),(15.639593,18.8126),(15.64352,18.858178),(15.647551,18.903834),(15.651582,18.949387),(15.655716,18.995069),(15.659747,19.040648),(15.663777,19.086304),(15.667808,19.131882),(15.671839,19.177539),(15.67587,19.223169),(15.6799,19.268747),(15.683931,19.314404),(15.687962,19.360008),(15.692096,19.405638),(15.696023,19.451243),(15.700054,19.496873),(15.704085,19.542529),(15.708116,19.588108),(15.712146,19.633764),(15.716177,19.679317),(15.720208,19.724999),(15.724342,19.770577),(15.728373,19.816259),(15.732404,19.861838),(15.736021,19.903541),(15.767234,19.982037),(15.782323,20.00803),(15.822321,20.076993),(15.862318,20.145955),(15.902419,20.214943),(15.94252,20.283957),(15.962984,20.319226),(15.970322,20.336331),(15.968151,20.352816),(15.953992,20.374571),(15.930324,20.399324),(15.872033,20.460199),(15.813846,20.521074),(15.755555,20.582001),(15.697264,20.642875),(15.669462,20.671866),(15.588123,20.732792),(15.570243,20.751913),(15.556084,20.773669),(15.544198,20.79899),(15.536033,20.844052),(15.544301,20.890302),(15.569003,20.928905),(15.60931,20.95066),(15.592774,20.974793),(15.576134,20.999339),(15.559288,21.023782),(15.542544,21.048277),(15.525801,21.072772),(15.509058,21.097266),(15.492212,21.121761),(15.475572,21.146256),(15.458829,21.17075),(15.441982,21.195193),(15.425342,21.219791),(15.408496,21.244234),(15.391753,21.268729),(15.375009,21.293223),(15.358266,21.317718),(15.34142,21.342161),(15.32478,21.366707),(15.301009,21.40133),(15.266592,21.440656),(15.247472,21.453265),(15.20024,21.476468),(15.18453,21.491196),(15.180396,21.507267),(15.180086,21.533467),(15.179776,21.553208),(15.178846,21.605297),(15.177502,21.678988),(15.176055,21.763427),(15.174608,21.847918),(15.173265,21.921557),(15.172438,21.973647),(15.172024,21.993387),(15.16448,22.033695),(15.156315,22.076173),(15.14815,22.118651),(15.136058,22.181335),(15.124069,22.243966),(15.11208,22.306598),(15.099987,22.369282),(15.087998,22.431914),(15.075906,22.494597),(15.064021,22.557177),(15.051928,22.619861),(15.039939,22.682544),(15.02795,22.745176),(15.015858,22.807782),(15.003973,22.87044),(14.991984,22.933097),(14.979909,22.995664),(14.997461,23.003817),(15.055236,23.029965),(15.112907,23.056113),(15.170371,23.082261),(15.228145,23.108358),(15.285816,23.134455),(15.343487,23.160577),(15.401158,23.186751),(15.458829,23.212899),(15.516499,23.239048),(15.574274,23.265196),(15.631945,23.291344),(15.689616,23.317518),(15.747183,23.343641),(15.804854,23.369789),(15.862525,23.395937),(15.920196,23.422034),(15.964637,23.442214),(15.985101,23.44472),(16.076155,23.399632),(16.199765,23.338706),(16.323169,23.277728),(16.446779,23.216724),(16.570285,23.15572),(16.693792,23.094664),(16.817299,23.03366),(16.940909,22.972733),(17.064312,22.911755),(17.187922,22.850751),(17.311429,22.789799),(17.434832,22.728795),(17.558442,22.667765),(17.681949,22.606787),(17.805455,22.545757),(17.928962,22.484779),(18.052469,22.423852),(18.175975,22.362822),(18.299585,22.301844),(18.422989,22.240866),(18.546599,22.179836),(18.670105,22.118806),(18.793612,22.05788),(18.917119,21.99685),(19.040729,21.935871),(19.164132,21.874893),(19.185837,21.864177),(19.287639,21.813915),(19.411145,21.752885),(19.534652,21.691855),(19.658262,21.630877),(19.781665,21.569899),(19.905276,21.508869),(20.028782,21.447943),(20.152289,21.386913),(20.275796,21.325935),(20.399406,21.265008),(20.522809,21.203926),(20.646419,21.142897),(20.769926,21.08197),(20.893329,21.02094),(21.016939,20.959962),(21.140342,20.899036),(21.263952,20.838006),(21.387459,20.777027),(21.510966,20.716049),(21.634472,20.654968),(21.758082,20.59399),(21.881486,20.533063),(22.005096,20.472033),(22.128602,20.411055),(22.252109,20.350077),(22.375616,20.289124),(22.499122,20.228095),(22.622629,20.167091),(22.746136,20.106061),(22.869642,20.045108),(22.993149,19.984104),(23.116759,19.923152),(23.240162,19.862096),(23.363772,19.80117),(23.487279,19.740166),(23.610786,19.67911),(23.734292,19.618132),(23.857799,19.557179),(23.981306,19.496124)] +Togo [(0.487649,10.933236),(0.612603,10.976566),(0.675338,10.988529),(0.77156,10.990364),(0.901474,10.992741),(0.875843,10.931169),(0.872949,10.911299),(0.875326,10.900524),(0.883698,10.880216),(0.885144,10.869389),(0.869538,10.839908),(0.867575,10.829211),(0.866024,10.80637),(0.862924,10.796086),(0.850005,10.77769),(0.795641,10.726478),(0.781275,10.693044),(0.789233,10.602946),(0.78851,10.563852),(0.773833,10.508145),(0.759881,10.405154),(0.760708,10.382158),(0.768769,10.367094),(0.844423,10.317175),(0.939508,10.254517),(0.997106,10.216553),(1.082238,10.16044),(1.225485,10.066053),(1.331009,9.996471),(1.343825,9.962442),(1.343942,9.954756),(1.345065,9.881103),(1.346925,9.771834),(1.348165,9.694164),(1.35602,9.647474),(1.354573,9.635304),(1.352196,9.625357),(1.352506,9.60528),(1.351266,9.595074),(1.345065,9.582388),(1.327288,9.555309),(1.323154,9.542313),(1.326358,9.521952),(1.336486,9.497509),(1.351266,9.482549),(1.368422,9.490843),(1.379895,9.462473),(1.386716,9.361135),(1.401185,9.321267),(1.420146,9.292317),(1.425267,9.284499),(1.505158,9.201455),(1.567273,9.13673),(1.587841,9.100893),(1.595799,9.076811),(1.601173,9.049526),(1.602827,8.924392),(1.604274,8.815225),(1.605514,8.722492),(1.607204,8.588617),(1.607581,8.558755),(1.609028,8.546973),(1.614092,8.535785),(1.63993,8.503255),(1.644168,8.493488),(1.640447,8.475815),(1.607581,8.421864),(1.606031,8.413389),(1.606031,8.396026),(1.60107,8.371635),(1.603945,8.367476),(1.603964,8.367449),(1.609855,8.365485),(1.614919,8.356261),(1.625564,8.270478),(1.623807,8.155886),(1.621327,7.996567),(1.621947,7.838282),(1.622774,7.640052),(1.622855,7.62246),(1.623251,7.536385),(1.623704,7.4381),(1.624324,7.288807),(1.624944,7.143648),(1.625668,6.996783),(1.607478,6.991409),(1.531927,6.991926),(1.551357,6.920871),(1.562623,6.904283),(1.564223,6.903089),(1.579056,6.892035),(1.588047,6.881235),(1.590114,6.867334),(1.58257,6.825347),(1.58319,6.808268),(1.587531,6.791034),(1.595179,6.77057),(1.60107,6.746437),(1.597039,6.73096),(1.589182,6.72046),(1.574301,6.700574),(1.566033,6.678146),(1.572441,6.666907),(1.58536,6.656442),(1.596316,6.636418),(1.596522,6.62864),(1.594765,6.620269),(1.594145,6.611045),(1.597349,6.600813),(1.603344,6.592596),(1.611198,6.58469),(1.61957,6.577998),(1.627425,6.573347),(1.63683,6.572261),(1.646648,6.573192),(1.653883,6.570659),(1.655227,6.559213),(1.657811,6.552263),(1.67445,6.538594),(1.680755,6.530068),(1.681995,6.520017),(1.679515,6.498571),(1.681685,6.489838),(1.6883,6.484437),(1.709797,6.473404),(1.718375,6.466997),(1.74411,6.425733),(1.76354,6.350647),(1.782351,6.277267),(1.761577,6.276026),(1.633109,6.245692),(1.612439,6.234763),(1.619663,6.213899),(1.61964,6.213894),(1.619314,6.213813),(1.429535,6.181952),(1.271007,6.133734),(1.199555,6.102525),(1.19158,6.101874),(1.185396,6.100491),(1.187968,6.135647),(1.176186,6.151512),(1.093401,6.160917),(1.079655,6.167919),(1.068906,6.180347),(1.05578,6.20063),(1.048132,6.20939),(1.040587,6.213472),(1.033146,6.216547),(1.025188,6.222334),(1.009685,6.244452),(0.983536,6.324602),(0.907262,6.324912),(0.886798,6.33039),(0.873879,6.340131),(0.841323,6.379224),(0.816208,6.395063),(0.766805,6.419351),(0.745721,6.4409),(0.729908,6.465085),(0.71792,6.48883),(0.711718,6.513376),(0.713076,6.533936),(0.713475,6.53999),(0.71978,6.552728),(0.726808,6.562107),(0.727428,6.571435),(0.714612,6.583914),(0.705517,6.585775),(0.677612,6.584896),(0.668207,6.585827),(0.659422,6.601717),(0.645366,6.612026),(0.63224,6.62399),(0.626659,6.644893),(0.635341,6.695381),(0.634307,6.711607),(0.625832,6.727756),(0.611259,6.741528),(0.593793,6.751114),(0.576636,6.754731),(0.570022,6.763516),(0.541083,6.817182),(0.528887,6.826535),(0.519275,6.832246),(0.516071,6.841806),(0.522789,6.862838),(0.543873,6.897926),(0.54625,6.914773),(0.534468,6.935909),(0.506046,6.957819),(0.494574,6.973116),(0.509147,6.977611),(0.523823,6.978697),(0.565991,6.989652),(0.57891,6.996783),(0.59803,7.0312),(0.598754,7.074711),(0.59431,7.119722),(0.59772,7.158892),(0.621801,7.218837),(0.631103,7.265242),(0.644436,7.301933),(0.645676,7.323585),(0.629656,7.389162),(0.623042,7.397896),(0.586248,7.384357),(0.566404,7.380791),(0.548214,7.383271),(0.516692,7.411022),(0.500568,7.45505),(0.495608,7.504298),(0.499432,7.562382),(0.503049,7.574681),(0.50925,7.585378),(0.519379,7.595196),(0.532505,7.601036),(0.548524,7.605377),(0.562063,7.612301),(0.567748,7.625737),(0.567438,7.652919),(0.570538,7.683925),(0.583354,7.704285),(0.612293,7.699428),(0.609502,7.718961),(0.611673,7.771258),(0.602578,7.828412),(0.603405,7.888305),(0.602688,7.893132),(0.592863,7.959309),(0.593689,7.996567),(0.593173,8.015739),(0.583974,8.05305),(0.580254,8.100075),(0.574983,8.124621),(0.579943,8.131701),(0.587798,8.137721),(0.593276,8.150666),(0.591519,8.16449),(0.584594,8.173068),(0.576843,8.180484),(0.572709,8.191),(0.573846,8.203945),(0.579013,8.207821),(0.586661,8.208751),(0.595033,8.21273),(0.628313,8.24247),(0.645056,8.253425),(0.689187,8.272855),(0.705207,8.282751),(0.712752,8.29797),(0.708825,8.322568),(0.705104,8.325979),(0.693115,8.327891),(0.689187,8.331301),(0.688567,8.33603),(0.689394,8.346055),(0.686914,8.360731),(0.687224,8.372203),(0.685053,8.382564),(0.646709,8.414165),(0.63379,8.452018),(0.616324,8.488759),(0.550798,8.519326),(0.524753,8.538033),(0.500568,8.560176),(0.483515,8.579787),(0.443518,8.606866),(0.403727,8.662082),(0.374426,8.724766),(0.368084,8.761481),(0.365874,8.774272),(0.372669,8.783754),(0.385278,8.78608),(0.397112,8.781532),(0.407809,8.759053),(0.4183,8.770603),(0.424966,8.78732),(0.419592,8.791247),(0.430134,8.794736),(0.439409,8.793444),(0.449512,8.790369),(0.462483,8.788302),(0.47349,8.793547),(0.477004,8.80675),(0.478451,8.822331),(0.483515,8.834811),(0.483629,8.834973),(0.505633,8.866333),(0.493127,8.915219),(0.444887,8.996455),(0.444887,8.996558),(0.44468,8.996558),(0.43127,9.02759),(0.441554,9.058182),(0.458478,9.08924),(0.463749,9.12146),(0.463646,9.137092),(0.469976,9.14673),(0.49261,9.166754),(0.504703,9.187166),(0.504393,9.203109),(0.49199,9.238895),(0.49292,9.258609),(0.501085,9.268195),(0.512351,9.274706),(0.522479,9.285067),(0.526613,9.297651),(0.528267,9.326951),(0.537569,9.377646),(0.531368,9.401107),(0.513281,9.416791),(0.483515,9.426842),(0.482792,9.427875),(0.482585,9.428857),(0.482792,9.429839),(0.489406,9.441027),(0.49168,9.451285),(0.489923,9.461129),(0.483515,9.470017),(0.430444,9.489189),(0.411659,9.492238),(0.371429,9.490016),(0.34895,9.486037),(0.333783,9.479474),(0.328796,9.471568),(0.325747,9.451336),(0.32182,9.442836),(0.314223,9.436479),(0.26849,9.420641),(0.249886,9.416946),(0.23136,9.418961),(0.226813,9.432345),(0.234977,9.443766),(0.227949,9.459734),(0.228053,9.473971),(0.26973,9.482342),(0.28531,9.488363),(0.2981,9.497096),(0.301924,9.507457),(0.293139,9.518283),(0.279006,9.519007),(0.253503,9.514252),(0.243116,9.518697),(0.23322,9.525595),(0.225908,9.531926),(0.223402,9.534794),(0.223066,9.541176),(0.227743,9.569339),(0.230197,9.575747),(0.28053,9.570166),(0.30456,9.571562),(0.32244,9.583137),(0.33616,9.574197),(0.354608,9.571096),(0.370809,9.575644),(0.377734,9.589416),(0.369155,9.610138),(0.349363,9.61391),(0.308797,9.603678),(0.277636,9.606986),(0.261694,9.627941),(0.260971,9.657164),(0.275285,9.685586),(0.301924,9.657835),(0.318719,9.648611),(0.336651,9.650833),(0.347089,9.663158),(0.34988,9.680651),(0.347606,9.698841),(0.342955,9.713543),(0.336289,9.72349),(0.329132,9.731293),(0.323887,9.742068),(0.32244,9.760671),(0.343886,9.838393),(0.344196,9.849762),(0.339674,9.889837),(0.341715,9.903789),(0.349777,9.918956),(0.362592,9.932676),(0.369569,9.938826),(0.370189,9.947017),(0.363393,9.966783),(0.35143,9.990451),(0.349777,9.997169),(0.35174,10.006419),(0.355125,10.01262),(0.355719,10.018976),(0.349777,10.02882),(0.367295,10.032128),(0.382746,10.029596),(0.393908,10.03249),(0.39457,10.035557),(0.398146,10.052127),(0.395149,10.072358),(0.387087,10.078947),(0.37608,10.081582),(0.363393,10.089669),(0.353601,10.115508),(0.358846,10.18633),(0.357192,10.219997),(0.364427,10.233407),(0.367295,10.249815),(0.372049,10.265137),(0.396596,10.283224),(0.376183,10.299941),(0.366597,10.304488),(0.32275,10.297254),(0.308797,10.297099),(0.317582,10.31733),(0.307066,10.333272),(0.290039,10.348491),(0.278825,10.366629),(0.28022,10.375182),(0.283553,10.385775),(0.283114,10.396808),(0.273244,10.406601),(0.263012,10.408926),(0.253943,10.406084),(0.244563,10.401537),(0.23322,10.398617),(0.223609,10.399961),(0.197073,10.41027),(0.194437,10.407376),(0.19175,10.400839),(0.187513,10.394948),(0.179865,10.394173),(0.176971,10.397687),(0.126018,10.491609),(0.110179,10.508249),(0.057262,10.541115),(0.04902,10.550959),(0.037341,10.57318),(0.029434,10.582533),(0.020339,10.588037),(-0.010925,10.598269),(-0.019968,10.604341),(-0.026221,10.610361),(-0.033352,10.615064),(-0.056452,10.618009),(-0.068363,10.621058),(-0.079344,10.626252),(-0.088129,10.633486),(-0.098336,10.654157),(-0.09769,10.675008),(-0.091564,10.700254),(-0.088129,10.714412),(-0.082807,10.756218),(-0.07521,10.773659),(-0.061103,10.791358),(-0.04069,10.805026),(-0.032061,10.813165),(-0.0302,10.823785),(-0.035316,10.843448),(-0.036091,10.853137),(-0.014439,10.953596),(-0.009581,10.963001),(-0.001571,10.971295),(0.007188,10.976799),(0.01419,10.983672),(0.016567,10.996203),(0.019409,11.031628),(0.016205,11.062582),(0.001116,11.085991),(-0.032267,11.098574),(-0.051077,11.098264),(-0.085029,11.089402),(-0.103348,11.087541),(-0.121745,11.092192),(-0.14208,11.103329),(-0.158668,11.118444),(-0.166109,11.13498),(-0.115062,11.124658),(-0.063118,11.114155),(0.059588,11.089402),(0.287558,11.043436),(0.374779,11.025808),(0.486616,11.003205),(0.488786,11.001784),(0.49013,10.999511),(0.490647,10.996358),(0.489303,10.991914),(0.48858,10.987754),(0.487133,10.983672),(0.483619,10.979693),(0.499742,10.975688),(0.487649,10.933236)] +Uganda [(34.108026,3.868938),(34.123736,3.872039),(34.163423,3.886198),(34.182854,3.886095),(34.204971,3.874545),(34.207555,3.860877),(34.196703,3.847389),(34.148954,3.822688),(34.150814,3.81721),(34.166524,3.811319),(34.17903,3.7961),(34.159082,3.783362),(34.152468,3.775636),(34.16518,3.77083),(34.173655,3.771399),(34.190915,3.775843),(34.210552,3.777135),(34.230396,3.782742),(34.240938,3.78362),(34.241558,3.778737),(34.263779,3.750056),(34.278868,3.709723),(34.290444,3.70316),(34.295095,3.707346),(34.299436,3.716932),(34.309874,3.726699),(34.337056,3.734579),(34.35504,3.727371),(34.387492,3.692747),(34.406303,3.682929),(34.425009,3.677193),(34.439686,3.667736),(34.446403,3.646704),(34.443923,3.566295),(34.434518,3.52622),(34.415501,3.497023),(34.406199,3.492294),(34.395967,3.489607),(34.386872,3.485628),(34.381291,3.476869),(34.382118,3.466043),(34.394417,3.444623),(34.398551,3.433642),(34.397001,3.424159),(34.386976,3.399664),(34.383978,3.388347),(34.386562,3.376384),(34.394417,3.365661),(34.403822,3.355404),(34.41116,3.344707),(34.424079,3.304812),(34.434001,3.182029),(34.444853,3.159136),(34.46573,3.145856),(34.512859,3.132368),(34.53384,3.118467),(34.545556,3.097501),(34.545622,3.097383),(34.574664,2.946126),(34.58469,2.928711),(34.616419,2.893416),(34.631405,2.869542),(34.6405,2.860137),(34.654143,2.856519),(34.660344,2.858638),(34.671506,2.867785),(34.67564,2.8698),(34.678121,2.871557),(34.682565,2.87936),(34.685045,2.880962),(34.688869,2.879154),(34.69104,2.875691),(34.692693,2.872229),(34.694657,2.87042),(34.696517,2.867733),(34.724836,2.854142),(34.730107,2.85285),(34.736928,2.844375),(34.740959,2.835539),(34.76132,2.772493),(34.776512,2.685625),(34.81868,2.597982),(34.828086,2.588784),(34.841832,2.58775),(34.849893,2.59514),(34.856508,2.60346),(34.865603,2.604855),(34.875628,2.591212),(34.881312,2.541448),(34.8871,2.522379),(34.914385,2.494371),(34.923584,2.477318),(34.920896,2.454632),(34.906117,2.436907),(34.885963,2.425434),(34.867876,2.411482),(34.859091,2.38678),(34.865603,2.347506),(34.904284,2.254255),(34.922343,2.210719),(34.967509,2.101914),(34.967612,2.082561),(34.958207,2.037965),(34.956657,2.018508),(34.957897,1.997838),(34.962031,1.977813),(34.969162,1.960295),(34.977947,1.949908),(35.001408,1.927997),(35.006473,1.916861),(35.002752,1.906138),(34.984045,1.88247),(34.979704,1.8703),(34.978671,1.675945),(34.972676,1.654241),(34.940947,1.587036),(34.933712,1.575693),(34.92348,1.566107),(34.913558,1.56156),(34.892578,1.55727),(34.882553,1.552232),(34.859505,1.517919),(34.838421,1.437174),(34.778993,1.388547),(34.780747,1.371789),(34.782714,1.352993),(34.800077,1.312324),(34.810516,1.272533),(34.797907,1.231916),(34.766074,1.217498),(34.683805,1.209075),(34.663031,1.196362),(34.628925,1.163599),(34.580452,1.152541),(34.573631,1.134247),(34.571977,1.111716),(34.566883,1.103022),(34.561228,1.093371),(34.560065,1.093149),(34.540351,1.089392),(34.524021,1.098642),(34.507485,1.102518),(34.487021,1.082467),(34.477203,1.064587),(34.468831,1.044227),(34.463663,1.022936),(34.463043,0.978081),(34.457152,0.957617),(34.431211,0.893538),(34.402375,0.856073),(34.388009,0.815817),(34.370852,0.800211),(34.30667,0.768068),(34.298402,0.759283),(34.296252,0.746746),(34.292304,0.72373),(34.276181,0.680838),(34.2521,0.655),(34.219751,0.638567),(34.179133,0.623891),(34.149574,0.603634),(34.132417,0.572834),(34.131588,0.569433),(34.107509,0.470722),(34.104409,0.462247),(34.097381,0.451808),(34.080121,0.431344),(34.075677,0.422249),(34.07671,0.403852),(34.087976,0.367369),(34.085185,0.347008),(34.076607,0.333779),(34.04064,0.305874),(33.960266,0.198677),(33.951757,0.187328),(33.893569,0.109814),(33.890468,0.090073),(33.921578,-0.01297),(33.95248,-0.115702),(33.953514,-0.154356),(33.935117,-0.313106),(33.911346,-0.519295),(33.894809,-0.662749),(33.89853,-0.799072),(33.904214,-1.002573),(33.822255,-1.002573),(33.639269,-1.002573),(33.631777,-1.002573),(33.456128,-1.002573),(33.426415,-1.002573),(33.27309,-1.002573),(33.089949,-1.002573),(32.906963,-1.002573),(32.847225,-1.002573),(32.723873,-1.002573),(32.722268,-1.002573),(32.540835,-1.002573),(32.357642,-1.002573),(32.174552,-1.002573),(31.991411,-1.002573),(31.986193,-1.002573),(31.808373,-1.002573),(31.625335,-1.002573),(31.442246,-1.002573),(31.280493,-1.002573),(31.259156,-1.002573),(31.076118,-1.002573),(30.892977,-1.002573),(30.828381,-1.002573),(30.812465,-0.994719),(30.777118,-0.98583),(30.739498,-1.005467),(30.701567,-1.017456),(30.687098,-1.025001),(30.651338,-1.062828),(30.638626,-1.07337),(30.614544,-1.065825),(30.592737,-1.063448),(30.542301,-1.068099),(30.523697,-1.07244),(30.511657,-1.07337),(30.506024,-1.070786),(30.500856,-1.065205),(30.493415,-1.060244),(30.481012,-1.059107),(30.472951,-1.065619),(30.471786,-1.066837),(30.460829,-1.063428),(30.445614,-1.058694),(30.432023,-1.060554),(30.418897,-1.066445),(30.403188,-1.070373),(30.386341,-1.068202),(30.369288,-1.063241),(30.352752,-1.060761),(30.337455,-1.066239),(30.329032,-1.080501),(30.322572,-1.121843),(30.317405,-1.137035),(30.311307,-1.1421),(30.294564,-1.149644),(30.29095,-1.152621),(30.287536,-1.155432),(30.284642,-1.161427),(30.28242,-1.175793),(30.280508,-1.182407),(30.269759,-1.200494),(30.256685,-1.217237),(30.212192,-1.259509),(30.19674,-1.268707),(30.189351,-1.270877),(30.181392,-1.271497),(30.173434,-1.272841),(30.165579,-1.277492),(30.158448,-1.291135),(30.15235,-1.329892),(30.147183,-1.345085),(30.136331,-1.355213),(30.095506,-1.37113),(30.065984,-1.386945),(30.06078,-1.389733),(30.047757,-1.403169),(30.038662,-1.424977),(30.028327,-1.427147),(29.960424,-1.464767),(29.938462,-1.472932),(29.917429,-1.475206),(29.897896,-1.469625),(29.880739,-1.453605),(29.871024,-1.432418),(29.868647,-1.391283),(29.864203,-1.370303),(29.836091,-1.329478),(29.825135,-1.323897),(29.825024,-1.323881),(29.816143,-1.322554),(29.807462,-1.325138),(29.798212,-1.330925),(29.789168,-1.341674),(29.783174,-1.361414),(29.774906,-1.366272),(29.767981,-1.363792),(29.74669,-1.350872),(29.734805,-1.348185),(29.710517,-1.352526),(29.693774,-1.361208),(29.678322,-1.37237),(29.657703,-1.383945),(29.6391,-1.38901),(29.618119,-1.39056),(29.577915,-1.38839),(29.58732,-1.329685),(29.587113,-1.310565),(29.583186,-1.299299),(29.571507,-1.279249),(29.57099,-1.268604),(29.580447,-1.243282),(29.581429,-1.234807),(29.575538,-1.213206),(29.565254,-1.19791),(29.557038,-1.181787),(29.556934,-1.157706),(29.56913,-1.095901),(29.57006,-1.077918),(29.565926,-1.058591),(29.551198,-1.020143),(29.54846,-1.002573),(29.551353,-0.990584),(29.551518,-0.990305),(29.556521,-0.981799),(29.560345,-0.972084),(29.559157,-0.957305),(29.555281,-0.938495),(29.554661,-0.928573),(29.556004,-0.919478),(29.567166,-0.901908),(29.596725,-0.891882),(29.607991,-0.878447),(29.610781,-0.863977),(29.613365,-0.803826),(29.611091,-0.782742),(29.602203,-0.743778),(29.60303,-0.7229),(29.615536,-0.644146),(29.618843,-0.638978),(29.624424,-0.634844),(29.629281,-0.62978),(29.630573,-0.622028),(29.628248,-0.616034),(29.620496,-0.605388),(29.618843,-0.599394),(29.622874,-0.588438),(29.632175,-0.585751),(29.642821,-0.585028),(29.650882,-0.57955),(29.653053,-0.565597),(29.649745,-0.504309),(29.645094,-0.48891),(29.634615,-0.466968),(29.631865,-0.461211),(29.629385,-0.442401),(29.650981,-0.316455),(29.653983,-0.298947),(29.670569,-0.200867),(29.676617,-0.165105),(29.694032,-0.063096),(29.709018,-0.026302),(29.714341,-0.007492),(29.713462,0.011628),(29.701628,0.055243),(29.703075,0.072503),(29.711809,0.099582),(29.755785,0.16087),(29.761263,0.172135),(29.773045,0.167484),(29.780383,0.16118),(29.787205,0.158493),(29.797127,0.164797),(29.800641,0.172445),(29.832628,0.336983),(29.839605,0.358481),(29.851077,0.377187),(29.903909,0.438229),(29.922907,0.46018),(29.926083,0.467073),(29.940477,0.498317),(29.937996,0.537281),(29.919496,0.618103),(29.920013,0.63867),(29.932312,0.723161),(29.926834,0.774889),(29.928281,0.785018),(29.947298,0.824602),(29.960217,0.832095),(29.982194,0.849017),(29.996391,0.859949),(30.038352,0.878914),(30.145116,0.90315),(30.154831,0.90868),(30.165683,0.921444),(30.18377,0.955137),(30.18687,0.958754),(30.191521,0.974877),(30.214052,0.998545),(30.220977,1.017097),(30.215602,1.057766),(30.215292,1.077093),(30.228005,1.08903),(30.231519,1.097764),(30.234102,1.108099),(30.236169,1.129493),(30.238857,1.136004),(30.269346,1.167268),(30.277976,1.171609),(30.286502,1.174296),(30.295701,1.172643),(30.306553,1.163909),(30.323813,1.155848),(30.33606,1.16887),(30.348204,1.189024),(30.364947,1.202047),(30.376626,1.20308),(30.39926,1.2006),(30.412696,1.202047),(30.43161,1.207008),(30.445562,1.212795),(30.458275,1.221684),(30.478274,1.238634),(30.553704,1.335632),(30.597284,1.391673),(30.681724,1.500349),(30.817013,1.609515),(30.95442,1.720671),(31.025837,1.778239),(31.096018,1.866363),(31.119113,1.895363),(31.183295,1.976211),(31.242826,2.051168),(31.271455,2.102999),(31.280096,2.151441),(31.280447,2.15341),(31.27874,2.156021),(31.267476,2.173253),(31.21089,2.205345),(31.190116,2.221519),(31.182468,2.238728),(31.179058,2.25976),(31.177559,2.30291),(31.129242,2.284668),(31.112602,2.282084),(31.099063,2.282704),(31.055241,2.290249),(31.040668,2.297897),(31.035501,2.30694),(31.038808,2.310971),(31.044389,2.313917),(31.045939,2.319653),(31.043562,2.327043),(31.041288,2.331228),(30.984858,2.394635),(30.968011,2.405436),(30.930907,2.405591),(30.914474,2.378151),(30.900573,2.345956),(30.87179,2.332055),(30.854943,2.339703),(30.83634,2.356343),(30.819803,2.37598),(30.809675,2.392362),(30.806987,2.406986),(30.807142,2.422179),(30.80492,2.434374),(30.794998,2.440111),(30.724925,2.440782),(30.710559,2.445123),(30.707665,2.46228),(30.71676,2.483105),(30.729369,2.503466),(30.737017,2.519537),(30.737844,2.537469),(30.73402,2.574469),(30.73526,2.593073),(30.739395,2.603305),(30.758928,2.633794),(30.761254,2.641597),(30.762013,2.645781),(30.764303,2.658392),(30.797686,2.74836),(30.798926,2.753528),(30.799133,2.76345),(30.801613,2.769083),(30.80585,2.771873),(30.817943,2.774199),(30.82187,2.776162),(30.828691,2.786084),(30.853393,2.853367),(30.85484,2.89321),(30.843988,2.932794),(30.82094,2.973153),(30.803628,2.989069),(30.757068,3.02147),(30.745079,3.036302),(30.743839,3.055474),(30.74787,3.076713),(30.763416,3.123437),(30.804197,3.246005),(30.822129,3.281403),(30.825746,3.283677),(30.837786,3.286416),(30.842437,3.288741),(30.845641,3.293909),(30.846882,3.304399),(30.84869,3.309256),(30.868482,3.343337),(30.897318,3.375015),(30.904933,3.386035),(30.91003,3.393412),(30.916335,3.414806),(30.914474,3.426484),(30.904449,3.447465),(30.902899,3.458911),(30.909617,3.487178),(30.909307,3.496144),(30.896388,3.519967),(30.880161,3.514412),(30.861248,3.498211),(30.839543,3.490202),(30.843781,3.505911),(30.865692,3.548958),(30.931734,3.645102),(30.936282,3.656858),(30.939382,3.668408),(30.944447,3.679286),(30.955505,3.689001),(30.965996,3.692618),(30.985788,3.692127),(30.995968,3.693522),(31.009559,3.699775),(31.040358,3.724218),(31.04966,3.727991),(31.068677,3.731737),(31.077668,3.735303),(31.104408,3.756175),(31.141489,3.785119),(31.167585,3.792405),(31.214818,3.792354),(31.255745,3.786669),(31.29502,3.774189),(31.377702,3.729308),(31.505446,3.659855),(31.523739,3.656083),(31.53452,3.665563),(31.535522,3.666444),(31.547201,3.680991),(31.564771,3.689802),(31.668537,3.70502),(31.68683,3.712824),(31.696132,3.721273),(31.775714,3.810699),(31.777884,3.816435),(31.780985,3.815815),(31.801107,3.806472),(31.80703,3.803722),(31.830697,3.783879),(31.901908,3.704297),(31.916274,3.680267),(31.920046,3.661302),(31.923095,3.615284),(31.93002,3.59836),(31.943662,3.591255),(32.022236,3.58642),(32.030168,3.585932),(32.041537,3.57986),(32.054226,3.559572),(32.060864,3.548958),(32.076161,3.53317),(32.093007,3.524463),(32.155846,3.511776),(32.16799,3.512242),(32.174552,3.520897),(32.175929,3.527234),(32.178997,3.541361),(32.179203,3.556864),(32.174863,3.59265),(32.175948,3.605595),(32.187782,3.61916),(32.371801,3.731065),(32.415571,3.741297),(32.599281,3.756283),(32.756429,3.769022),(32.840352,3.794291),(32.9189,3.83416),(32.979568,3.879196),(32.997241,3.885526),(33.01724,3.87718),(33.143486,3.774086),(33.164466,3.763053),(33.19542,3.757059),(33.286526,3.752537),(33.447343,3.744372),(33.490648,3.749746),(33.527716,3.771431),(33.532609,3.774293),(33.606196,3.848087),(33.701901,3.944076),(33.813677,4.056033),(33.896049,4.138353),(33.977078,4.219692),(34.006017,4.205713),(34.028548,4.188014),(34.041054,4.164812),(34.03971,4.134038),(34.04095,4.120421),(34.049735,4.109466),(34.060897,4.09926),(34.069269,4.08802),(34.072369,4.076419),(34.072679,4.064663),(34.069786,4.041357),(34.065858,4.02743),(34.061517,4.017921),(34.061104,4.007767),(34.068959,3.991876),(34.080844,3.980792),(34.09552,3.970999),(34.107096,3.959501),(34.109576,3.943352),(34.098931,3.917721),(34.086219,3.894673),(34.084772,3.877336),(34.108026,3.868938)] +Uruguay [(-56.906367,-30.108549),(-56.869211,-30.102968),(-56.831281,-30.102037),(-56.795159,-30.123845),(-56.776607,-30.150923),(-56.766995,-30.161362),(-56.704777,-30.198362),(-56.673745,-30.211281),(-56.656821,-30.221307),(-56.641783,-30.233916),(-56.632585,-30.247455),(-56.629278,-30.267712),(-56.63243,-30.278151),(-56.631345,-30.284662),(-56.615403,-30.293344),(-56.605196,-30.295617),(-56.595611,-30.295411),(-56.585818,-30.296548),(-56.575017,-30.302439),(-56.569617,-30.30802),(-56.560781,-30.320525),(-56.523754,-30.357319),(-56.5113,-30.366001),(-56.494557,-30.379333),(-56.441279,-30.408789),(-56.424639,-30.423568),(-56.400454,-30.458915),(-56.385985,-30.475761),(-56.372601,-30.48589),(-56.326531,-30.508318),(-56.267956,-30.551106),(-56.23509,-30.565368),(-56.215091,-30.581905),(-56.183517,-30.614564),(-56.177832,-30.62552),(-56.175171,-30.636062),(-56.170804,-30.645777),(-56.159642,-30.653942),(-56.140315,-30.664794),(-56.131685,-30.671925),(-56.125045,-30.680297),(-56.091894,-30.736107),(-56.076857,-30.752334),(-56.011357,-30.798222),(-55.995311,-30.825818),(-55.988955,-30.85579),(-55.993864,-30.885452),(-56.011357,-30.912634),(-56.015517,-30.934338),(-56.016344,-30.999864),(-56.02239,-31.045546),(-56.022183,-31.067147),(-56.017018,-31.074296),(-56.011357,-31.082133),(-56.009874,-31.081945),(-55.985157,-31.078825),(-55.919347,-31.082443),(-55.888186,-31.076965),(-55.86426,-31.076758),(-55.854596,-31.074588),(-55.846586,-31.069317),(-55.842142,-31.063943),(-55.838396,-31.058155),(-55.832479,-31.051747),(-55.778141,-31.020431),(-55.763594,-31.008442),(-55.755507,-30.992939),(-55.744887,-30.958626),(-55.731891,-30.945397),(-55.712745,-30.943433),(-55.688302,-30.947774),(-55.665822,-30.949324),(-55.652748,-30.938989),(-55.651069,-30.919972),(-55.654583,-30.878734),(-55.649673,-30.860958),(-55.634041,-30.847625),(-55.612906,-30.843388),(-55.591873,-30.848348),(-55.563865,-30.87646),(-55.527484,-30.894547),(-55.51131,-30.906123),(-55.489089,-30.929687),(-55.44258,-30.965551),(-55.368579,-31.037381),(-55.353852,-31.056294),(-55.348426,-31.072728),(-55.344963,-31.108488),(-55.338039,-31.125644),(-55.326928,-31.134946),(-55.2937,-31.153653),(-55.282228,-31.169052),(-55.268741,-31.2106),(-55.259981,-31.228687),(-55.244349,-31.244603),(-55.227554,-31.253492),(-55.18828,-31.266514),(-55.169625,-31.276436),(-55.122238,-31.31354),(-55.102446,-31.324288),(-55.087253,-31.326769),(-55.074256,-31.320568),(-55.061105,-31.304858),(-55.042346,-31.272612),(-55.029375,-31.268788),(-55.011495,-31.287805),(-54.995346,-31.311783),(-54.969637,-31.340825),(-54.940802,-31.36563),(-54.900288,-31.382063),(-54.887808,-31.393225),(-54.876155,-31.406351),(-54.863365,-31.417616),(-54.849903,-31.425057),(-54.819776,-31.435289),(-54.654127,-31.455753),(-54.619685,-31.45565),(-54.604543,-31.459784),(-54.591521,-31.471049),(-54.573848,-31.502469),(-54.562375,-31.515905),(-54.509665,-31.552285),(-54.495041,-31.565617),(-54.483155,-31.583911),(-54.47897,-31.601481),(-54.477368,-31.642098),(-54.467221,-31.664237),(-54.463725,-31.671864),(-54.436492,-31.694292),(-54.403677,-31.714652),(-54.373498,-31.73894),(-54.342957,-31.769326),(-54.274228,-31.823379),(-54.218779,-31.856659),(-54.169583,-31.895933),(-54.146277,-31.909886),(-54.135063,-31.908956),(-54.125503,-31.898517),(-54.107313,-31.883944),(-54.088451,-31.878156),(-54.068814,-31.879913),(-54.049745,-31.887148),(-54.03264,-31.898104),(-54.026646,-31.904821),(-54.017706,-31.919601),(-54.008714,-31.926526),(-53.998896,-31.92973),(-53.965978,-31.93252),(-53.948769,-31.936964),(-53.934352,-31.942545),(-53.905826,-31.959288),(-53.894148,-31.97014),(-53.889755,-31.980372),(-53.887275,-31.990501),(-53.881435,-32.00125),(-53.8711,-32.011482),(-53.858077,-32.021197),(-53.83043,-32.036441),(-53.771829,-32.047087),(-53.757308,-32.055045),(-53.751366,-32.068791),(-53.750022,-32.104034),(-53.721445,-32.162428),(-53.670595,-32.226404),(-53.658555,-32.254309),(-53.651837,-32.288312),(-53.648684,-32.338645),(-53.643879,-32.355595),(-53.634783,-32.368721),(-53.609307,-32.387841),(-53.59892,-32.399933),(-53.58197,-32.425772),(-53.5613,-32.449543),(-53.537632,-32.470213),(-53.474638,-32.508247),(-53.415624,-32.564161),(-53.35909,-32.580284),(-53.316043,-32.602712),(-53.299093,-32.607156),(-53.266899,-32.607363),(-53.233723,-32.624622),(-53.201477,-32.637232),(-53.186129,-32.64674),(-53.119776,-32.707408),(-53.110836,-32.722394),(-53.11404,-32.740584),(-53.126856,-32.754847),(-53.163081,-32.778722),(-53.182836,-32.799904),(-53.203854,-32.82244),(-53.270826,-32.863781),(-53.298835,-32.889102),(-53.307,-32.907189),(-53.309584,-32.944396),(-53.316302,-32.96269),(-53.327309,-32.973645),(-53.44911,-33.042065),(-53.48332,-33.067283),(-53.511535,-33.099219),(-53.511587,-33.099322),(-53.511639,-33.099426),(-53.520662,-33.124979),(-53.536857,-33.170842),(-53.536133,-33.244636),(-53.514016,-33.394911),(-53.536805,-33.559863),(-53.539647,-33.649263),(-53.511535,-33.690294),(-53.491071,-33.690294),(-53.473191,-33.6874),(-53.456707,-33.687503),(-53.440428,-33.697115),(-53.430817,-33.713445),(-53.423634,-33.731015),(-53.411283,-33.74228),(-53.379095,-33.740676),(-53.396352,-33.750584),(-53.414784,-33.764418),(-53.450917,-33.801528),(-53.473053,-33.834568),(-53.485585,-33.869317),(-53.505523,-33.952325),(-53.524648,-34.002374),(-53.529937,-34.04811),(-53.539459,-34.062433),(-53.574452,-34.082696),(-53.591217,-34.095473),(-53.639963,-34.147638),(-53.693593,-34.181736),(-53.711008,-34.198826),(-53.746653,-34.25742),(-53.755971,-34.267673),(-53.75829,-34.278497),(-53.779897,-34.336033),(-53.763661,-34.372491),(-53.764882,-34.390395),(-53.805776,-34.400974),(-53.898305,-34.443943),(-53.972239,-34.487237),(-54.124623,-34.610447),(-54.13679,-34.623956),(-54.14094,-34.641046),(-54.140492,-34.656427),(-54.145904,-34.667576),(-54.236806,-34.684503),(-54.259674,-34.685968),(-54.255605,-34.677504),(-54.249501,-34.670994),(-54.23233,-34.658136),(-54.239329,-34.65309),(-54.245676,-34.646905),(-54.250478,-34.639337),(-54.252838,-34.630792),(-54.25121,-34.618341),(-54.241078,-34.594008),(-54.238596,-34.589776),(-54.253285,-34.577569),(-54.280344,-34.567966),(-54.308949,-34.562188),(-54.328603,-34.561782),(-54.317372,-34.568617),(-54.280141,-34.582289),(-54.288157,-34.594822),(-54.304433,-34.608575),(-54.32311,-34.619399),(-54.33849,-34.623956),(-54.344635,-34.630629),(-54.344797,-34.64422),(-54.337392,-34.654718),(-54.321156,-34.65252),(-54.322581,-34.644708),(-54.307688,-34.647393),(-54.289215,-34.660252),(-54.280141,-34.682306),(-54.288075,-34.695001),(-54.306467,-34.707696),(-54.530792,-34.806899),(-54.542063,-34.811782),(-54.604156,-34.82643),(-54.636464,-34.84881),(-54.65689,-34.856622),(-54.699452,-34.867446),(-54.872711,-34.936212),(-54.893707,-34.939223),(-54.913726,-34.945245),(-54.93932,-34.969903),(-54.958608,-34.973403),(-54.953969,-34.963311),(-54.951812,-34.956964),(-54.951772,-34.952895),(-54.962229,-34.93963),(-54.975738,-34.928481),(-54.99356,-34.920994),(-55.03307,-34.916762),(-55.035471,-34.912856),(-55.034535,-34.906508),(-55.041127,-34.897638),(-55.051259,-34.891371),(-55.060374,-34.887791),(-55.082143,-34.883966),(-55.129791,-34.885919),(-55.22175,-34.903741),(-55.260243,-34.897638),(-55.286488,-34.876235),(-55.338287,-34.81878),(-55.376943,-34.801446),(-55.401926,-34.799981),(-55.468204,-34.795402),(-55.509636,-34.799065),(-55.561173,-34.787834),(-55.601794,-34.772415),(-55.646731,-34.7811),(-55.693448,-34.764741),(-55.756503,-34.782666),(-55.792051,-34.774134),(-55.858786,-34.793061),(-55.889101,-34.803475),(-55.954432,-34.839402),(-56.004052,-34.869102),(-56.069634,-34.901003),(-56.105198,-34.898416),(-56.135633,-34.912829),(-56.149892,-34.920343),(-56.156088,-34.941188),(-56.17729,-34.916325),(-56.19451,-34.913509),(-56.213002,-34.907693),(-56.204661,-34.898696),(-56.203455,-34.887503),(-56.214589,-34.879588),(-56.230551,-34.87775),(-56.236508,-34.892884),(-56.256337,-34.906183),(-56.265824,-34.906266),(-56.287976,-34.903489),(-56.311269,-34.906183),(-56.342763,-34.883966),(-56.402943,-34.85475),(-56.418446,-34.843032),(-56.420766,-34.82822),(-56.403751,-34.816051),(-56.386848,-34.80187),(-56.361282,-34.796636),(-56.37612,-34.782729),(-56.395738,-34.77588),(-56.448432,-34.758272),(-56.485088,-34.75355),(-56.520444,-34.754821),(-56.5419,-34.767022),(-56.558013,-34.765069),(-56.573598,-34.758966),(-56.610951,-34.739435),(-56.628529,-34.732599),(-56.646362,-34.722642),(-56.713544,-34.707037),(-56.795289,-34.698492),(-56.873891,-34.67018),(-56.890696,-34.660089),(-56.904164,-34.635512),(-56.919749,-34.623224),(-56.95287,-34.603448),(-56.976577,-34.581046),(-56.997417,-34.564069),(-57.015788,-34.552091),(-57.042717,-34.538125),(-57.057425,-34.527127),(-57.055898,-34.513442),(-57.062408,-34.506524),(-57.077016,-34.498142),(-57.08316,-34.493585),(-57.101959,-34.475844),(-57.120025,-34.462986),(-57.151964,-34.450932),(-57.203198,-34.442073),(-57.292158,-34.440333),(-57.346942,-34.443459),(-57.3652,-34.43044),(-57.411428,-34.431506),(-57.436974,-34.444576),(-57.44913,-34.431538),(-57.474663,-34.429541),(-57.502635,-34.440582),(-57.537914,-34.453614),(-57.569475,-34.426504),(-57.594997,-34.425473),(-57.624177,-34.430452),(-57.664324,-34.445438),(-57.7203,-34.463373),(-57.738535,-34.461318),(-57.764115,-34.474295),(-57.793302,-34.472197),(-57.82251,-34.475109),(-57.855354,-34.470967),(-57.845585,-34.462979),(-57.854048,-34.447882),(-57.882019,-34.440724),(-57.90019,-34.416525),(-57.8976,-34.376339),(-57.92276,-34.353692),(-57.942738,-34.326267),(-58.016916,-34.253106),(-58.049794,-34.240004),(-58.061391,-34.224705),(-58.076975,-34.19199),(-58.094594,-34.17783),(-58.119374,-34.169203),(-58.145904,-34.165134),(-58.169097,-34.163995),(-58.196197,-34.159438),(-58.20873,-34.147638),(-58.220326,-34.11004),(-58.231842,-34.0888),(-58.316518,-33.986505),(-58.334828,-33.973321),(-58.372426,-33.95436),(-58.388824,-33.942071),(-58.402699,-33.922784),(-58.410024,-33.902276),(-58.434641,-33.784926),(-58.439361,-33.6985),(-58.425771,-33.612888),(-58.429026,-33.592055),(-58.435048,-33.572361),(-58.438344,-33.551446),(-58.433217,-33.527765),(-58.419586,-33.508233),(-58.385365,-33.47031),(-58.37857,-33.448663),(-58.384877,-33.429132),(-58.412587,-33.409601),(-58.418935,-33.389907),(-58.412587,-33.371677),(-58.397206,-33.355645),(-58.361195,-33.325779),(-58.350738,-33.305759),(-58.349233,-33.28281),(-58.366038,-33.196059),(-58.366933,-33.153741),(-58.351389,-33.121677),(-58.310292,-33.108819),(-58.217356,-33.113539),(-58.174428,-33.110447),(-58.137766,-33.095147),(-58.100168,-33.065606),(-58.08373,-33.04754),(-58.076975,-33.030694),(-58.075307,-33.007501),(-58.070668,-32.989516),(-58.055816,-32.951837),(-58.048492,-32.911716),(-58.057118,-32.881768),(-58.077219,-32.857843),(-58.120473,-32.819268),(-58.130767,-32.802667),(-58.136138,-32.784356),(-58.137766,-32.763442),(-58.135854,-32.718357),(-58.137685,-32.695571),(-58.145172,-32.678155),(-58.137766,-32.670668),(-58.14623,-32.644952),(-58.157216,-32.575128),(-58.169097,-32.560805),(-58.177113,-32.545017),(-58.197418,-32.469822),(-58.200103,-32.447198),(-58.200112,-32.44713),(-58.199724,-32.444789),(-58.189958,-32.433936),(-58.164946,-32.389495),(-58.101591,-32.31136),(-58.096527,-32.280974),(-58.106914,-32.251829),(-58.17523,-32.174107),(-58.186547,-32.15292),(-58.180863,-32.132456),(-58.158797,-32.101554),(-58.148306,-32.0629),(-58.145309,-32.01789),(-58.14903,-31.975205),(-58.158797,-31.943889),(-58.190319,-31.913296),(-58.202618,-31.893143),(-58.196004,-31.872575),(-58.168615,-31.846014),(-58.152854,-31.835988),(-58.13084,-31.827824),(-58.083453,-31.819762),(-58.059268,-31.811494),(-58.048881,-31.797128),(-57.988626,-31.642822),(-57.979583,-31.598794),(-57.986818,-31.554145),(-58.013328,-31.52562),(-58.038978,-31.508637),(-58.050793,-31.500815),(-58.075236,-31.475184),(-58.062575,-31.444281),(-58.043558,-31.430639),(-58.005938,-31.411001),(-57.990228,-31.399323),(-57.980513,-31.380512),(-57.975552,-31.33514),(-57.966354,-31.314573),(-57.959481,-31.307959),(-57.942996,-31.296797),(-57.935606,-31.290285),(-57.914832,-31.252458),(-57.905117,-31.240986),(-57.905014,-31.215044),(-57.911732,-31.170603),(-57.899019,-31.126471),(-57.87375,-31.093088),(-57.855249,-31.058982),(-57.863311,-31.012266),(-57.905479,-30.958833),(-57.911732,-30.947361),(-57.90398,-30.929687),(-57.885325,-30.918835),(-57.842795,-30.909223),(-57.819644,-30.9116),(-57.807242,-30.90757),(-57.801868,-30.89248),(-57.796132,-30.868399),(-57.794995,-30.85796),(-57.796028,-30.816206),(-57.799397,-30.791461),(-57.801868,-30.773314),(-57.808659,-30.747331),(-57.817887,-30.712026),(-57.826207,-30.689702),(-57.848531,-30.647947),(-57.863311,-30.62862),(-57.88579,-30.589863),(-57.889769,-30.550796),(-57.877109,-30.514829),(-57.849617,-30.48527),(-57.652729,-30.329104),(-57.631077,-30.297064),(-57.623739,-30.2581),(-57.63795,-30.215105),(-57.642446,-30.193091),(-57.633971,-30.183583),(-57.611698,-30.182963),(-57.586842,-30.204047),(-57.567463,-30.256343),(-57.535992,-30.27443),(-57.510981,-30.276704),(-57.467211,-30.269883),(-57.44313,-30.269469),(-57.429797,-30.275464),(-57.414811,-30.295721),(-57.399257,-30.299131),(-57.389386,-30.294894),(-57.366597,-30.277221),(-57.353833,-30.27195),(-57.334299,-30.272673),(-57.321742,-30.279804),(-57.310993,-30.288279),(-57.296472,-30.293344),(-57.288617,-30.29076),(-57.276215,-30.277737),(-57.270376,-30.275154),(-57.262469,-30.278668),(-57.250067,-30.29045),(-57.245054,-30.293344),(-57.212601,-30.287349),(-57.183714,-30.267505),(-57.163819,-30.23929),(-57.158341,-30.207871),(-57.150848,-30.182343),(-57.129557,-30.149993),(-57.102272,-30.121158),(-57.077106,-30.106068),(-57.067235,-30.106792),(-57.048529,-30.114543),(-57.037883,-30.114647),(-57.018298,-30.105758),(-57.01127,-30.103484),(-56.97458,-30.09749),(-56.954529,-30.09687),(-56.906367,-30.108549)] +Vatican [(12.453137,41.902752),(12.452714,41.903016),(12.452767,41.903439),(12.453031,41.903915),(12.453983,41.903862),(12.454035,41.902752),(12.453137,41.902752)] +Akrotiri Sovereign Base Area [(32.840809,34.699467),(32.845992,34.699467),(32.853766,34.699467),(32.85969,34.700578),(32.86043,34.687621),(32.865613,34.678735),(32.884504,34.666607),(32.913667,34.66028),(32.917246,34.667136),(32.929752,34.662485),(32.936056,34.657731),(32.942258,34.667136),(32.954712,34.677316),(32.987526,34.673389),(32.9898,34.646103),(32.970266,34.646103),(32.965615,34.651581),(32.95404,34.642951),(32.95559,34.628895),(32.962515,34.625019),(32.969543,34.632047),(32.99073,34.634425),(33.015635,34.634425),(33.009939,34.624905),(33.009125,34.597398),(33.030284,34.574774),(33.030284,34.568549),(32.940929,34.568549),(32.940929,34.574774),(32.944672,34.593695),(32.915863,34.63939),(32.913585,34.656684),(32.857432,34.669013),(32.834321,34.670966),(32.812836,34.668647),(32.760671,34.653225),(32.760102,34.66911),(32.766766,34.676144),(32.778613,34.673182),(32.798604,34.670961),(32.806009,34.68577),(32.819336,34.687621),(32.822668,34.691323),(32.827481,34.696506),(32.832294,34.700948),(32.835626,34.699838),(32.840809,34.699467)] +Zambia [(31.119836,-8.616631),(31.141024,-8.606192),(31.161384,-8.591723),(31.182675,-8.580767),(31.206756,-8.580767),(31.218435,-8.588725),(31.237349,-8.613943),(31.248046,-8.621902),(31.260913,-8.623969),(31.269388,-8.621075),(31.277088,-8.61601),(31.328816,-8.597717),(31.340391,-8.595237),(31.347523,-8.592446),(31.350107,-8.588519),(31.353311,-8.587175),(31.362199,-8.592343),(31.36592,-8.598647),(31.369227,-8.616837),(31.372638,-8.623865),(31.38597,-8.632547),(31.398838,-8.633787),(31.412428,-8.63234),(31.427518,-8.633477),(31.443228,-8.641539),(31.464725,-8.666137),(31.480641,-8.676162),(31.519089,-8.687014),(31.539036,-8.70355),(31.54596,-8.728975),(31.545857,-8.766286),(31.55335,-8.809074),(31.576449,-8.839666),(31.672671,-8.913047),(31.689621,-8.919558),(31.709775,-8.919661),(31.730238,-8.912426),(31.764345,-8.894133),(31.787599,-8.892169),(31.936634,-8.93258),(31.917824,-8.973095),(31.917721,-9.022497),(31.938081,-9.061771),(31.980559,-9.0719),(32.001385,-9.063322),(32.015802,-9.052676),(32.031719,-9.045958),(32.057247,-9.049576),(32.086031,-9.066112),(32.096418,-9.069109),(32.105823,-9.068283),(32.125046,-9.063735),(32.134141,-9.064148),(32.145574,-9.070265),(32.154812,-9.075207),(32.191606,-9.112208),(32.211294,-9.12678),(32.231448,-9.133808),(32.252739,-9.136495),(32.383015,-9.133912),(32.423426,-9.143834),(32.459703,-9.168018),(32.470658,-9.181867),(32.490089,-9.227343),(32.504455,-9.249253),(32.518046,-9.258245),(32.555614,-9.261242),(32.641604,-9.279846),(32.713228,-9.28584),(32.725837,-9.292558),(32.739686,-9.307338),(32.743407,-9.314986),(32.746507,-9.329972),(32.752295,-9.337413),(32.759633,-9.339997),(32.776996,-9.33824),(32.784334,-9.339687),(32.83074,-9.370176),(32.905464,-9.398185),(32.920863,-9.4079),(32.923034,-9.466294),(32.927788,-9.479834),(32.937503,-9.487792),(32.943601,-9.485725),(32.950267,-9.480867),(32.961895,-9.48035),(32.968613,-9.484381),(32.983082,-9.497714),(32.99197,-9.501848),(32.992384,-9.529133),(32.97471,-9.601273),(32.986906,-9.628455),(33.000135,-9.632796),(33.011194,-9.627835),(33.022253,-9.62029),(33.03574,-9.616983),(33.046747,-9.622047),(33.050778,-9.632693),(33.053052,-9.644785),(33.058323,-9.654293),(33.08044,-9.662251),(33.089225,-9.643958),(33.092533,-9.614399),(33.09832,-9.588458),(33.121471,-9.599516),(33.175422,-9.602307),(33.19542,-9.616259),(33.209838,-9.641374),(33.214282,-9.654707),(33.215781,-9.6699),(33.21299,-9.680648),(33.207823,-9.68871),(33.204567,-9.698115),(33.207254,-9.712894),(33.216711,-9.727054),(33.241774,-9.74235),(33.25273,-9.754029),(33.267199,-9.781211),(33.275777,-9.793303),(33.287766,-9.803845),(33.299962,-9.810253),(33.336962,-9.823689),(33.343473,-9.83144),(33.359183,-9.870921),(33.365591,-9.898826),(33.35846,-9.91991),(33.328797,-9.965489),(33.309987,-10.012721),(33.304716,-10.037939),(33.304096,-10.063777),(33.317532,-10.082071),(33.399181,-10.117934),(33.420161,-10.135608),(33.436491,-10.153281),(33.454578,-10.16806),(33.480519,-10.177052),(33.499123,-10.201237),(33.518967,-10.214983),(33.533281,-10.231209),(33.535606,-10.262732),(33.529302,-10.318646),(33.532919,-10.342623),(33.559171,-10.404325),(33.567646,-10.416004),(33.595551,-10.440602),(33.603199,-10.44918),(33.622733,-10.494035),(33.638184,-10.511605),(33.665418,-10.515119),(33.665573,-10.541371),(33.672652,-10.559561),(33.673523,-10.569367),(33.673849,-10.573048),(33.674203,-10.577028),(33.657769,-10.601316),(33.642266,-10.615268),(33.603096,-10.643277),(33.59028,-10.648961),(33.576947,-10.657643),(33.528268,-10.711593),(33.51199,-10.751797),(33.500983,-10.769161),(33.480519,-10.781563),(33.465326,-10.784354),(33.447136,-10.802234),(33.43401,-10.808125),(33.418663,-10.807298),(33.385538,-10.80089),(33.37174,-10.803267),(33.357839,-10.808745),(33.332621,-10.813602),(33.319082,-10.81815),(33.306886,-10.828589),(33.288128,-10.856701),(33.2734,-10.865589),(33.261204,-10.865279),(33.250766,-10.862488),(33.241412,-10.865692),(33.232576,-10.883262),(33.231697,-10.897628),(33.239604,-10.903106),(33.252109,-10.903106),(33.265855,-10.901142),(33.280325,-10.913338),(33.28787,-10.944861),(33.29096,-10.975086),(33.293967,-11.004495),(33.303682,-11.034571),(33.3181,-11.062269),(33.3366,-11.087384),(33.358873,-11.109398),(33.390912,-11.164795),(33.382231,-11.194664),(33.368485,-11.222673),(33.298308,-11.32923),(33.29681,-11.335741),(33.300272,-11.347007),(33.298928,-11.353104),(33.293347,-11.357755),(33.278051,-11.364266),(33.273503,-11.369641),(33.27185,-11.383697),(33.273814,-11.396616),(33.273607,-11.409432),(33.265184,-11.423074),(33.239707,-11.402404),(33.230302,-11.416563),(33.234953,-11.501726),(33.233816,-11.514025),(33.227305,-11.532732),(33.212629,-11.563841),(33.215936,-11.571592),(33.232679,-11.57769),(33.249319,-11.577793),(33.266889,-11.575623),(33.283219,-11.578414),(33.296758,-11.593606),(33.302649,-11.60973),(33.314018,-11.7722),(33.310607,-11.808787),(33.297378,-11.846511),(33.297481,-11.862531),(33.308747,-11.884441),(33.312674,-11.898704),(33.309315,-11.91431),(33.303579,-11.930227),(33.294226,-11.981283),(33.2549,-12.072647),(33.251283,-12.105823),(33.25273,-12.139516),(33.260274,-12.155743),(33.288386,-12.182201),(33.299962,-12.195947),(33.312467,-12.228606),(33.330141,-12.298266),(33.349468,-12.327929),(33.384608,-12.340021),(33.458298,-12.31811),(33.497366,-12.331546),(33.514109,-12.331029),(33.525581,-12.335267),(33.527131,-12.355627),(33.51814,-12.37175),(33.513887,-12.374281),(33.487754,-12.389837),(33.480519,-12.406373),(33.465326,-12.409061),(33.460779,-12.416502),(33.459952,-12.4411),(33.451115,-12.452986),(33.420781,-12.464974),(33.409412,-12.475206),(33.393755,-12.498254),(33.373239,-12.518511),(33.350398,-12.532671),(33.32828,-12.537632),(33.320322,-12.535048),(33.311951,-12.52988),(33.302236,-12.525126),(33.28973,-12.524196),(33.263168,-12.528536),(33.255107,-12.531947),(33.243634,-12.544763),(33.226995,-12.579076),(33.21299,-12.588584),(33.202913,-12.591788),(33.196816,-12.595406),(33.192371,-12.599023),(33.187307,-12.60233),(33.181313,-12.608222),(33.178005,-12.615043),(33.173251,-12.620004),(33.163019,-12.620417),(33.158782,-12.615353),(33.146896,-12.593235),(33.13992,-12.586311),(33.13036,-12.583727),(33.122815,-12.584554),(33.107002,-12.588688),(33.099044,-12.593235),(33.089949,-12.60078),(33.081267,-12.604811),(33.074239,-12.5983),(33.070002,-12.590445),(33.064627,-12.584967),(33.057703,-12.583417),(33.049538,-12.586827),(33.035378,-12.599126),(33.024836,-12.612666),(32.994141,-12.672507),(32.958071,-12.725217),(32.944635,-12.752399),(32.941121,-12.769865),(32.947012,-12.843246),(32.953523,-12.854098),(32.980498,-12.870738),(33.005044,-12.892959),(33.013571,-12.917247),(33.00892,-12.945049),(32.981532,-13.00613),(32.965925,-13.116821),(32.967114,-13.134184),(32.9713,-13.150927),(32.979051,-13.167877),(32.995071,-13.190873),(32.998171,-13.202449),(32.992797,-13.216401),(32.962721,-13.22498),(32.937865,-13.255882),(32.919623,-13.294846),(32.905487,-13.351391),(32.892131,-13.404814),(32.874251,-13.443158),(32.845829,-13.45804),(32.827432,-13.460831),(32.819061,-13.471683),(32.816891,-13.487393),(32.817511,-13.505583),(32.813066,-13.528217),(32.800044,-13.537105),(32.763199,-13.54248),(32.749814,-13.550851),(32.722839,-13.573382),(32.71023,-13.575346),(32.691627,-13.569145),(32.677261,-13.567801),(32.667649,-13.575553),(32.663308,-13.596327),(32.67509,-13.628056),(32.706716,-13.635084),(32.743407,-13.635394),(32.769865,-13.646866),(32.807795,-13.699163),(32.813377,-13.711152),(32.80485,-13.722004),(32.768108,-13.739057),(32.757359,-13.750219),(32.763044,-13.777194),(32.791879,-13.789803),(32.828776,-13.797038),(32.85942,-13.808097),(32.874148,-13.820602),(32.923912,-13.880444),(32.927891,-13.895636),(32.930062,-13.910519),(32.93616,-13.926229),(32.944428,-13.932947),(32.962515,-13.932017),(32.970576,-13.936047),(32.976261,-13.944522),(32.976674,-13.949793),(32.974814,-13.955478),(32.9713,-14.005914),(32.976467,-14.021107),(32.999825,-14.050459),(33.01817,-14.046222),(33.049434,-13.996612),(33.062974,-13.981729),(33.076926,-13.974495),(33.111601,-13.964573),(33.120645,-13.955891),(33.130256,-13.93057),(33.140282,-13.924989),(33.154544,-13.936564),(33.185654,-13.993822),(33.202707,-14.013872),(33.13005,-14.038057),(33.042923,-14.067099),(32.917143,-14.10906),(32.744957,-14.166421),(32.576802,-14.222542),(32.425493,-14.272978),(32.320383,-14.308014),(32.227366,-14.33902),(32.147061,-14.353386),(32.108768,-14.364859),(32.033269,-14.398758),(31.932913,-14.431108),(31.801345,-14.473586),(31.658408,-14.519578),(31.589679,-14.554821),(31.496661,-14.60257),(31.410878,-14.633576),(31.306802,-14.658174),(31.178024,-14.68856),(31.074465,-14.713054),(31.056585,-14.714398),(30.915094,-14.746024),(30.815772,-14.768245),(30.676969,-14.817647),(30.591807,-14.848136),(30.48556,-14.885964),(30.392491,-14.931025),(30.318438,-14.966992),(30.230898,-14.977224),(30.214465,-14.981462),(30.214421,-14.981966),(30.213845,-14.98849),(30.220977,-15.018359),(30.220977,-15.063007),(30.225834,-15.106312),(30.263145,-15.231266),(30.287949,-15.278911),(30.320505,-15.299478),(30.334871,-15.304749),(30.347481,-15.317875),(30.357919,-15.335652),(30.364947,-15.354152),(30.369185,-15.374719),(30.371768,-15.439832),(30.374921,-15.451304),(30.389648,-15.471148),(30.392852,-15.480759),(30.390165,-15.490785),(30.371768,-15.525408),(30.365257,-15.547422),(30.367428,-15.561271),(30.395953,-15.590623),(30.401224,-15.598478),(30.412696,-15.627934),(30.410371,-15.630414),(30.396263,-15.635995),(30.356679,-15.651498),(30.32805,-15.652428),(30.296196,-15.639042),(30.280094,-15.632275),(30.254876,-15.628864),(30.246091,-15.632068),(30.231002,-15.644677),(30.223147,-15.649741),(30.207231,-15.653152),(30.195552,-15.649121),(30.16992,-15.632171),(30.130129,-15.623696),(30.090029,-15.629381),(30.050238,-15.640129),(30.010654,-15.646227),(29.967504,-15.641473),(29.881773,-15.618839),(29.837331,-15.614808),(29.814283,-15.619666),(29.773252,-15.638062),(29.73005,-15.644677),(29.672793,-15.663281),(29.648505,-15.666588),(29.62799,-15.663591),(29.608559,-15.658423),(29.587217,-15.655736),(29.563446,-15.662144),(29.526239,-15.692839),(29.508462,-15.703588),(29.422059,-15.71103),(29.406969,-15.714233),(29.186311,-15.812832),(29.150964,-15.848799),(29.141869,-15.854483),(29.121716,-15.859341),(29.102182,-15.870916),(29.086162,-15.884559),(29.076344,-15.895411),(29.055053,-15.934375),(29.042341,-15.946261),(29.018053,-15.950602),(28.972784,-15.951428),(28.951287,-15.955252),(28.946862,-15.957235),(28.932373,-15.963727),(28.898887,-15.995457),(28.877183,-16.022018),(28.874082,-16.028943),(28.860336,-16.049407),(28.857236,-16.060466),(28.859303,-16.069561),(28.86385,-16.076589),(28.868501,-16.08217),(28.870981,-16.087234),(28.8654,-16.121237),(28.852481,-16.162785),(28.847107,-16.202679),(28.86416,-16.231205),(28.840286,-16.284741),(28.836772,-16.306342),(28.840492,-16.323602),(28.857029,-16.36546),(28.857236,-16.388198),(28.833051,-16.426438),(28.829124,-16.434603),(28.822509,-16.470776),(28.808866,-16.486279),(28.769282,-16.515218),(28.761117,-16.532271),(28.741377,-16.550668),(28.73285,-16.55811),(28.718794,-16.56028),(28.690734,-16.56028),(28.643295,-16.568755),(28.280113,-16.706524),(28.21252,-16.748589),(28.113922,-16.827551),(28.022993,-16.865393),(27.868562,-16.929663),(27.816886,-16.959636),(27.777301,-17.001183),(27.641186,-17.198484),(27.624856,-17.233314),(27.604495,-17.312792),(27.577314,-17.363125),(27.524294,-17.415112),(27.422078,-17.504822),(27.157081,-17.769302),(27.146952,-17.783875),(27.145299,-17.794107),(27.146539,-17.818911),(27.149019,-17.842476),(27.11543,-17.882163),(27.078171,-17.916993),(27.048457,-17.944278),(27.021275,-17.958541),(27.006289,-17.962675),(26.95916,-17.964742),(26.94867,-17.968876),(26.912031,-17.992027),(26.88826,-17.984586),(26.794002,-18.026237),(26.769714,-18.029028),(26.753591,-18.032955),(26.740569,-18.0405),(26.71194,-18.065821),(26.700003,-18.069232),(26.685689,-18.066751),(26.628844,-18.049181),(26.612721,-18.041223),(26.598872,-18.029958),(26.583369,-18.013215),(26.570243,-18.002879),(26.553604,-17.996471),(26.527145,-17.992027),(26.485494,-17.979315),(26.408599,-17.939007),(26.362711,-17.930636),(26.325504,-17.93601),(26.318269,-17.934356),(26.311965,-17.928362),(26.3038,-17.922781),(26.294291,-17.918543),(26.248299,-17.913376),(26.239204,-17.910172),(26.233933,-17.903971),(26.228249,-17.894669),(26.221117,-17.886297),(26.211919,-17.882783),(26.203031,-17.887227),(26.167477,-17.913582),(26.158589,-17.918337),(26.135438,-17.922574),(26.118591,-17.931566),(26.101228,-17.935803),(26.095234,-17.938077),(26.0942,-17.941901),(26.096164,-17.954614),(26.095234,-17.958541),(26.081178,-17.962365),(26.062471,-17.962882),(26.046554,-17.966292),(26.04056,-17.978488),(26.033739,-17.971563),(25.978548,-17.998952),(25.966973,-18.000502),(25.924495,-17.998952),(25.86362,-17.971563),(25.853491,-17.959988),(25.846153,-17.943658),(25.847497,-17.929395),(25.86362,-17.923814),(25.849667,-17.906658),(25.804399,-17.888158),(25.794683,-17.872655),(25.786002,-17.862216),(25.765951,-17.849814),(25.743834,-17.839375),(25.70642,-17.829867),(25.694224,-17.819428),(25.681409,-17.81147),(25.657017,-17.81395),(25.603997,-17.836171),(25.536818,-17.848677),(25.530927,-17.850951),(25.522142,-17.860149),(25.516458,-17.862319),(25.510153,-17.861183),(25.500748,-17.856015),(25.49558,-17.854878),(25.420288,-17.854878),(25.409539,-17.853018),(25.376466,-17.841235),(25.345254,-17.842579),(25.335538,-17.841235),(25.315901,-17.83214),(25.285412,-17.809299),(25.266705,-17.800928),(25.259781,-17.794107),(25.253476,-17.781497),(25.242417,-17.770335),(25.228878,-17.762481),(25.215132,-17.759277),(25.198182,-17.75845),(25.190741,-17.755349),(25.177822,-17.738813),(25.172448,-17.735092),(25.161182,-17.729408),(25.156841,-17.72517),(25.155291,-17.719382),(25.156428,-17.70667),(25.153327,-17.700986),(25.138548,-17.686103),(25.131416,-17.686516),(25.122631,-17.697885),(25.120048,-17.691064),(25.115087,-17.684242),(25.107955,-17.678868),(25.098757,-17.676801),(25.096897,-17.67215),(25.088525,-17.642695),(25.085218,-17.640938),(25.067028,-17.625331),(25.064237,-17.621507),(25.052558,-17.621404),(25.045324,-17.619957),(25.040053,-17.616133),(25.033851,-17.608485),(25.033851,-17.60156),(25.040569,-17.584507),(25.036952,-17.5812),(25.02672,-17.58275),(25.008013,-17.588538),(24.998505,-17.588021),(24.982588,-17.576549),(24.971116,-17.560736),(24.969987,-17.559962),(24.95799,-17.551744),(24.93763,-17.560736),(24.924917,-17.542959),(24.898252,-17.531074),(24.829523,-17.517741),(24.79738,-17.519085),(24.786838,-17.516914),(24.780017,-17.512263),(24.775056,-17.507612),(24.769785,-17.505442),(24.684415,-17.49242),(24.639457,-17.49242),(24.629742,-17.49552),(24.622817,-17.502341),(24.617443,-17.509163),(24.606487,-17.515157),(24.591294,-17.528386),(24.580752,-17.532831),(24.571244,-17.533451),(24.562459,-17.53221),(24.546543,-17.526526),(24.537861,-17.520325),(24.53166,-17.5134),(24.523598,-17.507819),(24.498173,-17.503478),(24.47926,-17.494487),(24.449288,-17.489112),(24.407016,-17.474539),(24.388929,-17.471336),(24.371256,-17.473713),(24.329398,-17.485081),(24.321337,-17.488699),(24.310278,-17.482601),(24.257361,-17.480844),(24.238758,-17.478157),(24.220464,-17.4795),(24.190905,-17.485288),(24.148117,-17.493763),(24.105329,-17.502238),(24.062541,-17.510713),(24.01965,-17.519085),(23.976965,-17.52756),(23.934177,-17.536034),(23.891389,-17.544406),(23.848497,-17.552881),(23.805606,-17.561356),(23.762818,-17.569727),(23.72003,-17.578202),(23.677242,-17.586677),(23.634557,-17.595049),(23.591769,-17.603524),(23.548774,-17.611999),(23.505986,-17.620474),(23.47622,-17.626365),(23.45741,-17.626778),(23.422373,-17.633496),(23.381652,-17.641144),(23.375968,-17.628225),(23.375141,-17.615409),(23.382273,-17.601043),(23.359432,-17.582853),(23.340621,-17.560736),(23.320158,-17.54637),(23.305378,-17.539548),(23.290805,-17.535414),(23.258352,-17.532831),(23.241299,-17.535104),(23.224246,-17.539342),(23.206986,-17.541202),(23.189726,-17.536551),(23.177531,-17.524046),(23.17691,-17.509783),(23.179081,-17.494177),(23.176187,-17.478157),(23.165748,-17.467408),(23.121513,-17.450872),(23.097639,-17.432165),(23.073041,-17.405086),(23.054127,-17.375321),(23.046376,-17.348449),(23.040381,-17.33708),(22.998627,-17.293775),(22.984157,-17.285817),(22.936512,-17.273311),(22.876154,-17.248093),(22.849179,-17.23104),(22.809388,-17.196417),(22.778278,-17.180397),(22.765153,-17.169649),(22.755851,-17.154869),(22.744792,-17.108257),(22.730736,-17.081592),(22.710479,-17.055444),(22.665624,-17.008625),(22.651671,-16.998703),(22.592037,-16.975449),(22.579324,-16.975345),(22.573433,-16.971004),(22.569196,-16.962426),(22.569299,-16.944959),(22.567232,-16.936898),(22.554519,-16.924185),(22.522894,-16.914677),(22.508527,-16.906202),(22.499742,-16.89349),(22.489097,-16.865378),(22.416647,-16.75448),(22.408895,-16.745798),(22.399594,-16.740424),(22.383574,-16.73753),(22.377993,-16.734843),(22.372618,-16.728849),(22.365797,-16.71686),(22.350088,-16.696292),(22.343473,-16.683167),(22.333654,-16.673658),(22.306989,-16.669214),(22.303062,-16.66694),(22.295621,-16.659189),(22.290763,-16.656398),(22.287352,-16.658259),(22.283735,-16.661359),(22.274123,-16.663633),(22.259034,-16.669214),(22.251282,-16.670041),(22.237743,-16.665493),(22.15165,-16.597694),(22.145139,-16.584051),(22.142452,-16.567101),(22.138111,-16.552632),(22.127259,-16.546431),(22.108138,-16.54395),(22.104004,-16.536716),(22.106588,-16.525967),(22.107312,-16.512324),(22.101731,-16.497958),(22.084574,-16.470156),(22.079923,-16.457754),(22.08075,-16.441011),(22.086021,-16.422304),(22.094289,-16.404734),(22.103591,-16.391918),(22.105555,-16.379413),(22.089122,-16.371971),(22.055842,-16.364633),(22.054188,-16.358639),(22.053672,-16.336521),(22.052018,-16.326806),(22.048607,-16.322362),(22.036618,-16.312233),(22.032174,-16.306342),(22.02773,-16.291666),(22.025973,-16.278954),(22.022356,-16.266345),(22.01171,-16.252289),(22.019875,-16.253115),(22.045197,-16.252289),(22.010367,-16.198132),(21.983805,-16.165886),(21.981531,-16.144285),(21.981531,-16.128162),(21.981531,-16.067494),(21.981531,-16.004035),(21.980601,-16.001244),(21.980808,-15.956079),(21.980911,-15.853967),(21.981221,-15.751957),(21.981428,-15.649948),(21.981531,-15.547835),(21.981531,-15.503807),(21.981531,-15.473525),(21.981531,-15.452337),(21.981531,-15.412546),(21.981428,-15.261858),(21.981325,-15.11117),(21.981221,-14.960481),(21.981118,-14.809793),(21.981014,-14.659104),(21.980911,-14.508416),(21.980808,-14.357624),(21.980704,-14.206935),(21.980601,-14.05635),(21.980498,-13.905558),(21.980394,-13.754973),(21.980353,-13.694822),(21.980291,-13.604181),(21.980188,-13.453493),(21.980084,-13.302701),(21.979981,-13.152168),(21.979878,-13.001479),(22.104211,-13.001479),(22.228545,-13.001479),(22.352775,-13.001479),(22.477005,-13.001479),(22.601235,-13.001479),(22.725465,-13.001479),(22.849799,-13.001479),(22.974029,-13.001479),(23.098362,-13.001479),(23.222696,-13.001479),(23.346926,-13.001479),(23.471259,-13.001479),(23.595593,-13.001479),(23.719823,-13.001479),(23.844157,-13.001479),(23.968283,-13.001479),(24.000633,-13.001479),(23.988851,-12.965099),(23.971797,-12.93337),(23.949576,-12.904638),(23.895109,-12.849757),(23.874749,-12.821749),(23.865654,-12.789709),(23.872269,-12.750125),(23.891699,-12.705063),(23.910716,-12.631269),(23.928699,-12.561609),(23.940791,-12.532774),(23.98606,-12.467662),(24.019856,-12.419189),(24.028021,-12.402136),(24.030812,-12.385083),(24.020993,-12.340021),(24.016859,-12.278939),(24.006627,-12.253721),(23.981306,-12.227676),(23.959602,-12.19667),(23.954331,-12.151919),(23.961049,-12.011669),(23.967043,-11.882891),(23.98854,-11.834212),(23.990194,-11.824083),(23.985543,-11.799485),(23.981306,-11.724761),(23.972727,-11.700577),(23.962289,-11.68156),(23.954641,-11.662233),(23.954641,-11.636911),(23.959912,-11.617171),(23.977688,-11.577277),(24.005387,-11.535212),(24.009728,-11.52343),(24.009831,-11.507203),(24.007247,-11.483122),(24.007557,-11.470513),(24.009935,-11.459454),(24.020787,-11.444572),(24.052102,-11.42049),(24.061714,-11.406951),(24.061094,-11.394962),(24.016963,-11.298431),(24.011175,-11.272903),(24.015309,-11.130482),(23.995775,-11.127382),(23.990091,-11.113532),(23.994535,-11.074982),(23.993708,-11.019585),(23.997325,-11.001705),(24.003733,-10.982481),(24.000013,-10.967805),(23.980582,-10.938349),(23.974278,-10.921399),(23.967457,-10.872307),(24.00146,-10.873444),(24.048382,-10.882332),(24.09148,-10.897835),(24.114218,-10.919229),(24.114321,-10.927911),(24.10874,-10.945791),(24.108016,-10.954989),(24.110497,-10.965945),(24.117525,-10.986098),(24.119385,-10.99757),(24.117732,-11.03085),(24.124243,-11.043252),(24.144397,-11.040359),(24.16455,-11.033951),(24.181294,-11.034467),(24.218294,-11.045216),(24.238034,-11.048007),(24.275138,-11.047903),(24.293845,-11.05028),(24.316376,-11.060099),(24.345315,-11.078289),(24.370533,-11.1002),(24.381798,-11.12056),(24.378284,-11.132136),(24.369913,-11.140921),(24.362471,-11.150533),(24.361748,-11.164692),(24.367432,-11.176268),(24.384382,-11.191254),(24.391307,-11.199832),(24.396578,-11.217402),(24.397818,-11.238279),(24.396061,-11.259673),(24.392237,-11.279104),(24.384485,-11.295227),(24.352446,-11.345043),(24.33994,-11.358065),(24.298289,-11.370571),(24.285473,-11.381216),(24.293948,-11.3992),(24.310071,-11.406641),(24.351722,-11.407055),(24.370223,-11.410155),(24.392547,-11.423384),(24.426447,-11.45408),(24.446497,-11.463589),(24.469648,-11.465552),(24.490939,-11.461522),(24.532693,-11.446122),(24.542512,-11.445398),(24.554191,-11.446329),(24.564733,-11.444675),(24.571244,-11.436407),(24.574448,-11.425141),(24.578582,-11.415633),(24.584576,-11.407365),(24.593258,-11.399613),(24.60225,-11.395686),(24.624677,-11.390828),(24.635219,-11.385867),(24.645038,-11.376049),(24.663331,-11.351657),(24.67408,-11.341632),(24.712527,-11.326026),(24.787975,-11.325819),(24.826732,-11.317551),(24.901043,-11.281274),(24.942901,-11.268562),(24.981245,-11.271869),(25.124285,-11.259157),(25.184023,-11.246651),(25.278798,-11.199935),(25.31032,-11.194768),(25.322516,-11.205413),(25.324583,-11.227841),(25.323343,-11.253472),(25.32541,-11.273936),(25.324893,-11.283651),(25.317142,-11.290473),(25.296264,-11.298431),(25.284689,-11.307319),(25.290166,-11.315897),(25.301329,-11.324476),(25.306496,-11.333054),(25.298021,-11.351451),(25.286342,-11.360649),(25.277971,-11.371811),(25.279004,-11.396306),(25.286652,-11.416563),(25.309287,-11.455424),(25.316728,-11.472994),(25.315385,-11.482502),(25.301742,-11.498418),(25.297711,-11.507927),(25.297505,-11.517229),(25.300398,-11.535005),(25.327373,-11.616654),(25.336779,-11.633501),(25.344943,-11.642182),(25.351971,-11.64611),(25.360446,-11.647247),(25.373159,-11.647143),(25.386388,-11.64983),(25.392796,-11.656445),(25.39755,-11.66492),(25.406335,-11.673085),(25.463593,-11.70006),(25.481163,-11.715253),(25.482816,-11.72042),(25.483281,-11.725795),(25.482816,-11.731169),(25.474135,-11.756181),(25.480439,-11.769823),(25.49558,-11.776541),(25.515217,-11.775818),(25.524519,-11.77096),(25.530617,-11.764242),(25.537645,-11.758351),(25.550254,-11.756594),(25.561003,-11.753287),(25.56493,-11.743985),(25.567824,-11.733753),(25.575679,-11.727345),(25.621464,-11.728895),(25.655777,-11.750496),(25.687403,-11.778711),(25.725644,-11.800519),(25.744041,-11.803826),(25.801608,-11.80424),(25.812667,-11.802999),(25.832511,-11.793801),(25.839849,-11.791941),(25.850701,-11.793801),(25.855765,-11.797212),(25.859589,-11.801966),(25.914159,-11.845581),(25.935553,-11.853642),(25.949816,-11.863978),(25.963562,-11.895087),(25.981132,-11.903045),(25.994051,-11.904802),(26.16665,-11.902425),(26.189078,-11.9109),(26.209335,-11.923612),(26.229592,-11.933121),(26.265559,-11.930847),(26.28623,-11.940562),(26.298012,-11.941182),(26.309174,-11.936531),(26.328811,-11.923302),(26.339146,-11.918961),(26.376353,-11.912863),(26.414594,-11.91183),(26.438365,-11.919065),(26.455418,-11.931984),(26.470715,-11.94697),(26.489111,-11.960819),(26.524871,-11.972291),(26.6059,-11.977769),(26.643521,-11.985521),(26.662744,-11.996579),(26.679797,-12.009602),(26.697057,-12.017457),(26.717418,-12.013012),(26.732559,-11.998336),(26.744186,-11.98118),(26.759379,-11.968674),(26.785011,-11.968364),(26.831726,-11.973325),(26.874204,-11.964333),(26.912755,-11.942526),(26.947688,-11.909143),(26.967325,-11.870385),(26.971356,-11.78853),(26.981071,-11.749049),(26.996367,-11.727035),(27.011147,-11.713186),(27.021482,-11.69789),(27.023239,-11.671121),(27.010837,-11.62885),(27.010268,-11.609833),(27.023756,-11.59557),(27.032437,-11.59433),(27.054452,-11.597534),(27.064373,-11.59712),(27.102201,-11.584925),(27.144989,-11.581307),(27.173617,-11.570559),(27.180129,-11.569629),(27.197182,-11.59371),(27.20762,-11.639392),(27.211961,-11.688278),(27.209998,-11.721971),(27.234182,-11.809097),(27.420734,-11.921959),(27.467553,-12.001644),(27.47179,-12.041641),(27.52047,-12.179617),(27.536076,-12.200081),(27.589836,-12.242958),(27.595297,-12.247313),(27.638189,-12.293615),(27.666197,-12.30271),(27.710742,-12.306328),(27.756734,-12.304261),(27.788309,-12.296509),(27.807274,-12.28142),(27.818281,-12.267777),(27.831407,-12.259922),(27.856676,-12.262403),(27.877037,-12.269948),(27.933881,-12.303331),(27.948454,-12.321417),(27.952226,-12.346532),(27.958686,-12.367823),(27.98101,-12.374541),(27.998993,-12.37144),(28.014031,-12.37051),(28.08767,-12.377538),(28.096869,-12.383016),(28.100434,-12.391491),(28.10245,-12.401206),(28.106997,-12.410197),(28.131285,-12.429214),(28.145961,-12.423117),(28.160741,-12.408751),(28.185752,-12.402446),(28.204976,-12.410818),(28.220065,-12.42539),(28.237532,-12.437069),(28.263887,-12.436966),(28.283834,-12.434072),(28.303678,-12.435416),(28.322488,-12.4411),(28.339748,-12.450505),(28.42274,-12.521302),(28.436434,-12.542799),(28.455916,-12.592098),(28.468267,-12.614629),(28.502012,-12.649563),(28.512295,-12.668373),(28.511624,-12.694418),(28.500151,-12.710954),(28.483977,-12.72222),(28.474003,-12.736482),(28.480928,-12.762114),(28.501598,-12.788469),(28.523613,-12.810173),(28.539425,-12.833841),(28.542836,-12.885621),(28.553378,-12.894922),(28.568468,-12.895543),(28.583971,-12.888721),(28.593686,-12.876732),(28.608155,-12.847897),(28.621178,-12.839422),(28.667893,-12.849344),(28.707994,-12.889755),(28.77569,-12.976571),(28.793363,-12.991557),(28.800598,-13.002409),(28.809435,-13.038376),(28.813621,-13.04282),(28.827057,-13.047575),(28.830881,-13.051812),(28.83026,-13.056876),(28.825506,-13.067832),(28.8253,-13.072379),(28.826023,-13.076823),(28.824628,-13.087262),(28.825816,-13.092843),(28.829744,-13.097184),(28.835428,-13.098941),(28.840906,-13.100078),(28.844213,-13.102352),(28.85367,-13.137078),(28.86323,-13.142659),(28.882712,-13.143589),(28.891859,-13.14731),(28.903434,-13.162296),(28.93413,-13.309626),(28.950356,-13.350967),(28.980846,-13.380216),(28.993971,-13.395925),(29.010301,-13.399439),(29.028491,-13.395512),(29.046681,-13.388897),(29.065386,-13.388676),(29.072933,-13.388587),(29.098048,-13.38466),(29.122129,-13.38435),(29.144453,-13.394478),(29.153393,-13.406984),(29.160163,-13.422074),(29.168948,-13.433856),(29.184141,-13.436853),(29.194786,-13.430962),(29.21401,-13.408328),(29.227446,-13.400783),(29.250183,-13.391585),(29.308267,-13.353654),(29.449551,-13.300324),(29.470015,-13.287818),(29.527996,-13.234075),(29.551043,-13.224153),(29.574401,-13.225393),(29.592798,-13.235625),(29.609851,-13.249474),(29.629075,-13.261463),(29.641064,-13.262807),(29.649745,-13.259913),(29.657497,-13.26012),(29.666592,-13.271178),(29.669176,-13.281204),(29.667522,-13.291952),(29.663595,-13.301874),(29.658892,-13.309522),(29.651502,-13.314587),(29.633622,-13.318928),(29.626594,-13.326369),(29.625044,-13.334844),(29.627008,-13.354894),(29.625147,-13.364196),(29.618946,-13.367297),(29.609438,-13.369054),(29.601686,-13.374428),(29.601686,-13.388381),(29.60551,-13.399956),(29.610678,-13.411015),(29.617396,-13.421247),(29.626078,-13.429825),(29.641477,-13.438507),(29.663078,-13.446878),(29.702869,-13.457627),(29.767154,-13.458351),(29.782244,-13.455663),(29.797643,-13.424244),(29.797747,-13.31376),(29.797953,-13.164363),(29.798212,-13.02277),(29.79847,-12.873012),(29.798677,-12.698345),(29.798987,-12.54869),(29.799142,-12.382292),(29.7994,-12.265813),(29.799607,-12.159463),(29.799582,-12.159036),(29.799397,-12.15582),(29.799297,-12.154089),(29.756095,-12.157603),(29.734908,-12.164838),(29.701267,-12.189022),(29.648918,-12.212793),(29.631865,-12.215997),(29.621117,-12.21021),(29.603185,-12.192846),(29.590317,-12.188092),(29.576727,-12.188092),(29.56758,-12.191709),(29.553059,-12.205145),(29.533473,-12.216721),(29.489548,-12.2315),(29.474252,-12.242662),(29.467948,-12.255272),(29.455907,-12.294339),(29.451825,-12.3178),(29.448156,-12.326792),(29.446554,-12.33506),(29.450378,-12.342915),(29.480453,-12.380535),(29.49606,-12.386323),(29.511459,-12.387356),(29.523448,-12.392524),(29.528202,-12.410508),(29.524688,-12.429214),(29.514663,-12.44389),(29.499677,-12.453089),(29.480453,-12.454949),(29.473012,-12.452469),(29.468774,-12.448438),(29.46526,-12.444201),(29.459886,-12.441307),(29.453323,-12.44079),(29.439216,-12.44203),(29.432601,-12.441307),(29.405936,-12.431695),(29.364388,-12.409267),(29.356533,-12.407614),(29.316432,-12.406683),(29.304857,-12.404823),(29.295503,-12.400999),(29.283049,-12.390457),(29.265066,-12.370923),(29.254989,-12.366169),(29.173392,-12.367616),(29.148949,-12.373714),(29.128123,-12.382809),(29.11107,-12.393454),(29.100218,-12.374024),(29.084405,-12.376401),(29.067249,-12.384773),(29.052779,-12.383842),(29.042651,-12.378778),(29.035106,-12.378882),(29.030352,-12.376194),(29.028595,-12.363069),(29.026114,-12.353043),(28.944672,-12.206076),(28.918731,-12.174346),(28.859509,-12.14179),(28.850414,-12.130008),(28.84597,-12.111301),(28.835015,-12.092181),(28.821475,-12.075748),(28.808866,-12.064585),(28.773623,-12.045879),(28.759877,-12.035233),(28.754193,-12.020144),(28.751092,-11.992238),(28.741997,-11.98428),(28.707064,-11.989448),(28.686032,-11.984074),(28.636887,-11.957615),(28.623865,-11.947797),(28.606191,-11.91028),(28.592652,-11.900461),(28.569191,-11.91369),(28.566091,-11.904492),(28.554205,-11.885062),(28.549451,-11.879584),(28.540562,-11.872039),(28.531571,-11.866458),(28.521132,-11.865735),(28.507851,-11.872763),(28.497154,-11.857363),(28.488886,-11.808684),(28.476794,-11.798245),(28.460671,-11.793388),(28.452506,-11.780779),(28.442687,-11.711635),(28.439587,-11.701507),(28.425117,-11.688071),(28.418399,-11.678873),(28.42212,-11.674738),(28.42274,-11.664713),(28.40548,-11.605182),(28.399589,-11.596087),(28.384913,-11.581307),(28.37742,-11.571076),(28.365586,-11.54162),(28.360315,-11.533558),(28.355664,-11.518159),(28.354424,-11.464725),(28.357008,-11.446949),(28.408581,-11.372431),(28.411991,-11.368401),(28.434212,-11.351244),(28.439587,-11.348247),(28.43199,-11.31104),(28.436176,-11.289129),(28.445581,-11.274556),(28.45509,-11.263704),(28.473693,-11.22567),(28.472453,-11.191977),(28.473693,-11.181229),(28.476225,-11.175441),(28.484752,-11.162832),(28.487336,-11.153427),(28.486922,-11.140921),(28.476174,-11.087694),(28.476794,-11.077979),(28.490953,-11.058652),(28.504079,-11.034364),(28.507851,-11.023615),(28.508626,-11.013487),(28.506663,-10.992093),(28.507851,-10.982068),(28.513794,-10.972869),(28.531364,-10.955092),(28.535085,-10.944447),(28.537358,-10.934112),(28.547177,-10.913751),(28.549451,-10.902899),(28.549451,-10.858561),(28.554412,-10.834996),(28.563507,-10.811949),(28.576529,-10.790658),(28.593479,-10.772881),(28.60092,-10.763166),(28.608052,-10.741359),(28.623245,-10.716864),(28.627585,-10.711696),(28.633477,-10.708906),(28.646189,-10.709836),(28.651873,-10.708389),(28.665878,-10.697434),(28.681536,-10.681931),(28.694351,-10.663327),(28.699622,-10.643174),(28.694248,-10.636766),(28.67089,-10.619092),(28.665516,-10.608964),(28.66717,-10.597388),(28.672699,-10.576098),(28.672337,-10.564315),(28.648049,-10.53765),(28.634924,-10.51946),(28.634717,-10.505714),(28.638748,-10.496206),(28.630479,-10.481013),(28.634717,-10.471608),(28.640608,-10.462616),(28.644535,-10.451041),(28.646086,-10.438431),(28.644949,-10.426546),(28.637714,-10.407012),(28.628619,-10.391096),(28.620868,-10.373319),(28.617767,-10.348308),(28.620713,-10.327327),(28.626449,-10.311411),(28.629239,-10.295908),(28.623865,-10.276374),(28.622108,-10.275857),(28.613323,-10.27069),(28.610842,-10.268829),(28.608052,-10.263558),(28.605985,-10.252913),(28.604021,-10.248366),(28.569915,-10.219633),(28.57932,-10.201133),(28.604021,-10.172711),(28.619627,-10.141912),(28.628516,-10.102741),(28.631255,-10.023056),(28.623865,-9.951019),(28.627947,-9.929419),(28.658695,-9.864823),(28.668462,-9.821622),(28.678073,-9.803845),(28.696522,-9.796507),(28.698486,-9.791959),(28.672337,-9.765501),(28.66996,-9.750928),(28.663656,-9.745037),(28.654974,-9.741937),(28.644949,-9.735115),(28.631255,-9.715582),(28.625157,-9.695634),(28.623865,-9.649126),(28.621798,-9.638274),(28.612909,-9.6175),(28.610842,-9.607888),(28.606502,-9.594349),(28.587588,-9.573161),(28.583557,-9.563756),(28.588621,-9.558279),(28.611101,-9.551044),(28.617767,-9.543292),(28.586296,-9.544016),(28.5741,-9.539158),(28.569191,-9.525929),(28.568726,-9.508979),(28.566866,-9.495957),(28.562783,-9.484898),(28.5556,-9.474459),(28.531571,-9.456889),(28.519685,-9.445624),(28.514724,-9.430018),(28.516274,-9.415548),(28.518135,-9.397461),(28.515964,-9.378341),(28.495397,-9.353226),(28.460464,-9.335036),(28.411371,-9.324908),(28.368532,-9.308578),(28.35246,-9.271991),(28.372304,-9.235094),(28.415092,-9.207085),(28.506198,-9.164401),(28.59906,-9.096395),(28.765407,-8.934027),(28.893099,-8.765769),(28.930461,-8.679883),(28.935474,-8.590792),(28.892789,-8.501909),(28.889172,-8.483099),(28.915268,-8.472867),(29.035106,-8.45478),(29.208119,-8.428528),(29.365938,-8.40455),(29.575844,-8.372729),(29.592281,-8.370237),(29.858105,-8.329826),(30.123618,-8.289519),(30.32495,-8.258926),(30.581781,-8.219962),(30.752107,-8.194124),(30.778255,-8.289105),(30.828278,-8.388117),(30.891892,-8.479171),(30.959536,-8.550485),(30.992351,-8.57591),(31.03364,-8.600301),(31.077824,-8.61632),(31.119836,-8.616631)] +Zimbabwe [(30.010654,-15.646227),(30.050238,-15.640129),(30.090029,-15.629381),(30.130129,-15.623696),(30.16992,-15.632171),(30.195552,-15.649121),(30.207231,-15.653152),(30.223147,-15.649741),(30.231002,-15.644677),(30.246091,-15.632068),(30.254876,-15.628864),(30.280094,-15.632275),(30.296196,-15.639042),(30.32805,-15.652428),(30.356679,-15.651498),(30.396263,-15.635995),(30.39771,-15.716817),(30.39926,-15.812005),(30.401327,-15.931688),(30.402568,-16.001244),(30.514809,-16.000418),(30.586587,-16.000004),(30.74973,-15.998867),(30.857424,-15.998144),(30.901865,-16.007136),(30.942173,-16.034524),(30.958296,-16.05106),(30.973075,-16.062016),(30.989767,-16.06429),(31.012039,-16.054885),(31.023718,-16.045169),(31.042218,-16.024912),(31.056895,-16.017574),(31.065421,-16.019641),(31.073328,-16.025532),(31.080872,-16.025946),(31.089037,-16.01189),(31.1141,-15.996904),(31.15849,-16.000211),(31.259983,-16.023465),(31.278897,-16.030287),(31.29533,-16.041655),(31.309592,-16.059019),(31.328351,-16.092815),(31.340908,-16.106664),(31.360339,-16.116896),(31.37026,-16.123718),(31.374601,-16.132916),(31.377754,-16.142218),(31.384006,-16.148832),(31.387727,-16.149556),(31.395582,-16.147695),(31.399613,-16.147282),(31.404315,-16.149866),(31.404057,-16.154517),(31.402713,-16.159374),(31.404574,-16.162268),(31.424107,-16.164749),(31.445708,-16.164955),(31.465655,-16.167746),(31.480641,-16.177978),(31.519192,-16.196478),(31.686107,-16.207227),(31.710705,-16.217872),(31.738197,-16.239783),(31.798761,-16.303655),(31.818088,-16.319571),(31.86005,-16.340759),(31.871935,-16.35037),(31.88072,-16.368044),(31.88563,-16.406284),(31.894363,-16.421477),(31.910279,-16.428919),(32.014149,-16.444938),(32.211759,-16.440184),(32.290463,-16.45176),(32.393661,-16.491757),(32.5521,-16.553355),(32.671783,-16.599761),(32.6831,-16.609889),(32.687906,-16.624255),(32.68863,-16.647303),(32.698655,-16.686784),(32.725217,-16.706421),(32.73095,-16.708656),(32.731314,-16.708798),(32.739893,-16.703217),(32.753845,-16.697946),(32.769348,-16.695466),(32.800664,-16.697326),(32.862004,-16.710452),(32.893372,-16.712415),(32.909598,-16.708075),(32.93957,-16.689781),(32.95621,-16.683063),(32.968509,-16.681616),(32.961585,-16.710348),(32.933369,-16.815768),(32.916213,-16.847911),(32.900503,-16.867755),(32.828776,-16.935141),(32.83012,-16.941549),(32.886757,-17.038184),(32.928512,-17.109497),(32.954143,-17.167168),(32.967786,-17.22887),(32.96909,-17.266115),(32.969439,-17.276102),(32.973212,-17.297909),(32.983599,-17.317753),(32.992384,-17.324678),(33.014656,-17.336667),(33.021633,-17.345555),(33.022459,-17.361471),(33.016258,-17.377181),(33.011651,-17.383991),(32.997448,-17.404983),(32.958174,-17.478467),(32.951663,-17.486218),(32.942981,-17.491593),(32.936573,-17.498311),(32.936676,-17.509369),(32.947218,-17.543166),(32.951663,-17.551434),(32.969129,-17.56456),(33.006646,-17.580993),(33.020392,-17.598563),(33.024526,-17.619233),(33.020599,-17.638457),(33.004063,-17.675561),(33.000238,-17.713905),(33.003184,-17.757726),(32.999102,-17.794313),(32.973573,-17.810643),(32.957037,-17.817981),(32.946082,-17.834724),(32.939674,-17.855498),(32.936883,-17.875032),(32.938433,-17.894566),(32.950267,-17.922574),(32.952128,-17.940247),(32.948149,-17.95327),(32.940397,-17.959988),(32.932439,-17.964949),(32.927375,-17.972907),(32.928977,-17.982312),(32.941224,-17.996265),(32.940294,-18.004843),(32.934919,-18.024583),(32.93709,-18.047114),(32.972282,-18.150261),(32.975537,-18.183333),(32.974865,-18.190775),(32.965925,-18.212169),(32.958174,-18.225398),(32.952283,-18.233046),(32.950526,-18.241314),(32.95497,-18.256301),(32.970163,-18.277488),(33.016878,-18.313661),(33.034965,-18.332885),(33.042768,-18.352005),(33.038066,-18.363064),(33.00923,-18.383941),(32.988198,-18.41319),(32.985356,-18.412467),(32.986803,-18.422285),(32.999515,-18.436651),(33.003029,-18.446883),(32.996414,-18.46714),(32.978586,-18.48006),(32.956624,-18.489878),(32.937142,-18.50104),(32.919313,-18.510032),(32.900296,-18.515303),(32.88314,-18.522124),(32.870737,-18.535767),(32.868257,-18.552613),(32.871668,-18.57318),(32.884483,-18.609044),(32.914559,-18.665888),(32.92231,-18.693173),(32.920243,-18.726246),(32.913267,-18.753014),(32.902518,-18.774512),(32.885207,-18.787844),(32.858852,-18.790015),(32.817924,-18.787018),(32.787642,-18.791255),(32.69142,-18.83425),(32.68987,-18.843241),(32.696794,-18.897192),(32.703202,-18.911868),(32.71576,-18.919826),(32.705063,-18.927474),(32.692247,-18.934295),(32.682532,-18.942667),(32.681085,-18.954966),(32.68863,-18.97729),(32.690283,-18.988246),(32.68863,-19.000958),(32.691058,-19.01429),(32.698965,-19.022249),(32.710282,-19.025969),(32.723873,-19.026589),(32.785988,-19.017701),(32.803351,-19.019561),(32.814203,-19.023799),(32.819991,-19.028346),(32.822988,-19.035168),(32.825262,-19.046847),(32.830223,-19.059146),(32.83813,-19.066897),(32.847483,-19.073925),(32.855906,-19.083744),(32.862262,-19.118057),(32.83322,-19.241977),(32.832187,-19.266678),(32.828673,-19.284558),(32.820715,-19.301301),(32.806142,-19.323419),(32.768831,-19.363623),(32.766454,-19.373442),(32.768521,-19.402794),(32.762217,-19.443412),(32.763354,-19.463979),(32.773947,-19.475864),(32.793119,-19.476691),(32.811309,-19.474521),(32.825365,-19.479172),(32.832187,-19.500876),(32.832497,-19.519273),(32.825365,-19.59162),(32.825675,-19.600818),(32.828156,-19.610636),(32.829603,-19.623659),(32.825365,-19.633271),(32.819474,-19.641952),(32.81627,-19.652081),(32.819629,-19.674302),(32.83105,-19.685154),(32.849137,-19.689081),(32.872184,-19.690218),(32.894715,-19.684327),(32.924584,-19.655285),(32.943188,-19.64929),(32.960964,-19.658799),(32.962411,-19.679056),(32.954143,-19.717813),(32.962411,-19.735383),(32.979051,-19.751403),(33.0006,-19.764322),(33.022769,-19.773107),(33.032795,-19.784166),(33.029642,-19.80339),(33.022873,-19.826851),(33.021322,-19.868088),(33.001995,-19.927),(32.998378,-20.000897),(33.004373,-20.024255),(33.007266,-20.032006),(32.95373,-20.030249),(32.940087,-20.041515),(32.934299,-20.072107),(32.926548,-20.086473),(32.910683,-20.091124),(32.894405,-20.094018),(32.88531,-20.10301),(32.877869,-20.151689),(32.872908,-20.167192),(32.859265,-20.190859),(32.857095,-20.200575),(32.858335,-20.207499),(32.865053,-20.220935),(32.86557,-20.228893),(32.858438,-20.259486),(32.852961,-20.273852),(32.845209,-20.286668),(32.800767,-20.338551),(32.735862,-20.414205),(32.704443,-20.471773),(32.671783,-20.531821),(32.646462,-20.557969),(32.603674,-20.56479),(32.556545,-20.559312),(32.513136,-20.564583),(32.481614,-20.603031),(32.471072,-20.645509),(32.469108,-20.68685),(32.483474,-20.794233),(32.49722,-20.898103),(32.491019,-20.936344),(32.467661,-20.980165),(32.417122,-21.040937),(32.339814,-21.134058),(32.345343,-21.142843),(32.359864,-21.151421),(32.368856,-21.162997),(32.373352,-21.163617),(32.377744,-21.16341),(32.380638,-21.165477),(32.380535,-21.172195),(32.376866,-21.178499),(32.37299,-21.183977),(32.37175,-21.187905),(32.444613,-21.304693),(32.445849,-21.308994),(32.447197,-21.313685),(32.408543,-21.290327),(32.37299,-21.327948),(32.324517,-21.378177),(32.272221,-21.432541),(32.219718,-21.486904),(32.167318,-21.541268),(32.114814,-21.595632),(32.062415,-21.649995),(32.010015,-21.704462),(31.957615,-21.758826),(31.905215,-21.813189),(31.852712,-21.867553),(31.800312,-21.92202),(31.747808,-21.976384),(31.695512,-22.030747),(31.643112,-22.085214),(31.590712,-22.139578),(31.538209,-22.193941),(31.485809,-22.248305),(31.433822,-22.302048),(31.36871,-22.345043),(31.288922,-22.39734),(31.265616,-22.365507),(31.255642,-22.357962),(31.24572,-22.357549),(31.229597,-22.363957),(31.221536,-22.364887),(31.213474,-22.36189),(31.197868,-22.352588),(31.190685,-22.350624),(31.183657,-22.34556),(31.163348,-22.322616),(31.152599,-22.316414),(31.137717,-22.318482),(31.10454,-22.333364),(31.097048,-22.334922),(31.087642,-22.336878),(31.07033,-22.333674),(31.036121,-22.319618),(30.927187,-22.295744),(30.867087,-22.289646),(30.83789,-22.282308),(30.805282,-22.294504),(30.693919,-22.302772),(30.674282,-22.30856),(30.647411,-22.32644),(30.632424,-22.330677),(30.625551,-22.32861),(30.610307,-22.318688),(30.601108,-22.316414),(30.57217,-22.316621),(30.507367,-22.309593),(30.488454,-22.310213),(30.46923,-22.315071),(30.431713,-22.331194),(30.412696,-22.336878),(30.372078,-22.343493),(30.334975,-22.344733),(30.300765,-22.336982),(30.269346,-22.316414),(30.25529,-22.304736),(30.240407,-22.296157),(30.2217,-22.290886),(30.196999,-22.289129),(30.15266,-22.294814),(30.13509,-22.293574),(30.111113,-22.282308),(30.082587,-22.262878),(30.067911,-22.25709),(30.038145,-22.253783),(30.035872,-22.250579),(30.034528,-22.246135),(30.015511,-22.227014),(30.005279,-22.22226),(29.983782,-22.217713),(29.973963,-22.213992),(29.946678,-22.198282),(29.932105,-22.194355),(29.896035,-22.191358),(29.871489,-22.179265),(29.837331,-22.172444),(29.779246,-22.136374),(29.758886,-22.130896),(29.691448,-22.1341),(29.679614,-22.138338),(29.661424,-22.126452),(29.641064,-22.129242),(29.60396,-22.145055),(29.570164,-22.141955),(29.551043,-22.145986),(29.542517,-22.162522),(29.53182,-22.172444),(29.506912,-22.170067),(29.456889,-22.158801),(29.436115,-22.163142),(29.399528,-22.182159),(29.378031,-22.192908),(29.363251,-22.192288),(29.356947,-22.190944),(29.350074,-22.186707),(29.273644,-22.125108),(29.26734,-22.115807),(29.259588,-22.096066),(29.254111,-22.087074),(29.244395,-22.075706),(29.239331,-22.072605),(29.144867,-22.075292),(29.10797,-22.069194),(29.070763,-22.051004),(29.040532,-22.020929),(29.021567,-21.982791),(29.013815,-21.940417),(29.017949,-21.898145),(29.028905,-21.876648),(29.045441,-21.852567),(29.057637,-21.829209),(29.05526,-21.809985),(29.038723,-21.797893),(28.998726,-21.786008),(28.980846,-21.774845),(28.951907,-21.768334),(28.891032,-21.764924),(28.860853,-21.757379),(28.714195,-21.693507),(28.66841,-21.679968),(28.629704,-21.651339),(28.6157,-21.647101),(28.585934,-21.644414),(28.553998,-21.636559),(28.542939,-21.638316),(28.532501,-21.643071),(28.497309,-21.651546),(28.481393,-21.657437),(28.464598,-21.660331),(28.443101,-21.655783),(28.361762,-21.616302),(28.321919,-21.603486),(28.284867,-21.596872),(28.165702,-21.595218),(28.090771,-21.581266),(28.032893,-21.577855),(28.016563,-21.572894),(28.002559,-21.564212),(27.990415,-21.551913),(27.984731,-21.542922),(27.975739,-21.522561),(27.970571,-21.514396),(27.963698,-21.510469),(27.958066,-21.511502),(27.953208,-21.510469),(27.949281,-21.500754),(27.954448,-21.487835),(27.950418,-21.482047),(27.943338,-21.479876),(27.939876,-21.478016),(27.941943,-21.468508),(27.949642,-21.456519),(27.953001,-21.448664),(27.950211,-21.438329),(27.920549,-21.381174),(27.904219,-21.364741),(27.897811,-21.35544),(27.896157,-21.347895),(27.896674,-21.332392),(27.8944,-21.32433),(27.884995,-21.310171),(27.849132,-21.269657),(27.823604,-21.231726),(27.793838,-21.197413),(27.724385,-21.149664),(27.709192,-21.134471),(27.674775,-21.090133),(27.666611,-21.071219),(27.666817,-21.053753),(27.678961,-21.000733),(27.680356,-20.979649),(27.672657,-20.923528),(27.672605,-20.913709),(27.675085,-20.891282),(27.674775,-20.879913),(27.676016,-20.866684),(27.681803,-20.857589),(27.689038,-20.849011),(27.694412,-20.837745),(27.709605,-20.756716),(27.707332,-20.716719),(27.682475,-20.637344),(27.690382,-20.60148),(27.702629,-20.566134),(27.705575,-20.526653),(27.698133,-20.509083),(27.683767,-20.49606),(27.66599,-20.489136),(27.625786,-20.488619),(27.590853,-20.473323),(27.534112,-20.483038),(27.45391,-20.473323),(27.340739,-20.473013),(27.306012,-20.477354),(27.268392,-20.49575),(27.283998,-20.35147),(27.266015,-20.234164),(27.214907,-20.110451),(27.201781,-20.092984),(27.183746,-20.082339),(27.16292,-20.076551),(27.141888,-20.073347),(27.129692,-20.072934),(27.119771,-20.073864),(27.109642,-20.073244),(27.097343,-20.068903),(27.086491,-20.060532),(27.069231,-20.03738),(27.060136,-20.027562),(27.02665,-20.010095),(26.9943,-20.006788),(26.961072,-20.007201),(26.925054,-20.000897),(26.811882,-19.94643),(26.774469,-19.939815),(26.750801,-19.939609),(26.730957,-19.935888),(26.713904,-19.927413),(26.698608,-19.91253),(26.684758,-19.894547),(26.67717,-19.886815),(26.673803,-19.883385),(26.659437,-19.875737),(26.614065,-19.863438),(26.595565,-19.855583),(26.581922,-19.842147),(26.574791,-19.819513),(26.566316,-19.800806),(26.549263,-19.784063),(26.508852,-19.759258),(26.489731,-19.75192),(26.450251,-19.743342),(26.431854,-19.73652),(26.412837,-19.71957),(26.385242,-19.679056),(26.362711,-19.667584),(26.332325,-19.662416),(26.324367,-19.659109),(26.312171,-19.651358),(26.312481,-19.649601),(26.319096,-19.646293),(26.326331,-19.633891),(26.333462,-19.613014),(26.330981,-19.604952),(26.32106,-19.592033),(26.313205,-19.584178),(26.30349,-19.577254),(26.292638,-19.572499),(26.239101,-19.571466),(26.194452,-19.5602),(26.155488,-19.537153),(26.13027,-19.501082),(26.034359,-19.243734),(26.011414,-19.199809),(25.981132,-19.161775),(25.956534,-19.122088),(25.948576,-19.103277),(25.944855,-19.079196),(25.948059,-19.058732),(25.964389,-19.021629),(25.9678,-19.000958),(25.967449,-18.999925),(25.940721,-18.921273),(25.815251,-18.813993),(25.779491,-18.738752),(25.773393,-18.665578),(25.761921,-18.630335),(25.736909,-18.608734),(25.698255,-18.590234),(25.669523,-18.566049),(25.622084,-18.501143),(25.608442,-18.487708),(25.574439,-18.465693),(25.508499,-18.399134),(25.49558,-18.378877),(25.490516,-18.365545),(25.481163,-18.323377),(25.473204,-18.303429),(25.440855,-18.2532),(25.408816,-18.175995),(25.387525,-18.138995),(25.357449,-18.115844),(25.323446,-18.09662),(25.296368,-18.068612),(25.255026,-18.001122),(25.226088,-17.931876),(25.21937,-17.908001),(25.21937,-17.879786),(25.259781,-17.794107),(25.266705,-17.800928),(25.285412,-17.809299),(25.315901,-17.83214),(25.335538,-17.841235),(25.345254,-17.842579),(25.376466,-17.841235),(25.409539,-17.853018),(25.420288,-17.854878),(25.49558,-17.854878),(25.500748,-17.856015),(25.510153,-17.861183),(25.516458,-17.862319),(25.522142,-17.860149),(25.530927,-17.850951),(25.536818,-17.848677),(25.603997,-17.836171),(25.657017,-17.81395),(25.681409,-17.81147),(25.694224,-17.819428),(25.70642,-17.829867),(25.743834,-17.839375),(25.765951,-17.849814),(25.786002,-17.862216),(25.794683,-17.872655),(25.804399,-17.888158),(25.849667,-17.906658),(25.86362,-17.923814),(25.847497,-17.929395),(25.846153,-17.943658),(25.853491,-17.959988),(25.86362,-17.971563),(25.924495,-17.998952),(25.966973,-18.000502),(25.978548,-17.998952),(26.033739,-17.971563),(26.04056,-17.978488),(26.046554,-17.966292),(26.062471,-17.962882),(26.081178,-17.962365),(26.095234,-17.958541),(26.096164,-17.954614),(26.0942,-17.941901),(26.095234,-17.938077),(26.101228,-17.935803),(26.118591,-17.931566),(26.135438,-17.922574),(26.158589,-17.918337),(26.167477,-17.913582),(26.203031,-17.887227),(26.211919,-17.882783),(26.221117,-17.886297),(26.228249,-17.894669),(26.233933,-17.903971),(26.239204,-17.910172),(26.248299,-17.913376),(26.294291,-17.918543),(26.3038,-17.922781),(26.311965,-17.928362),(26.318269,-17.934356),(26.325504,-17.93601),(26.362711,-17.930636),(26.408599,-17.939007),(26.485494,-17.979315),(26.527145,-17.992027),(26.553604,-17.996471),(26.570243,-18.002879),(26.583369,-18.013215),(26.598872,-18.029958),(26.612721,-18.041223),(26.628844,-18.049181),(26.685689,-18.066751),(26.700003,-18.069232),(26.71194,-18.065821),(26.740569,-18.0405),(26.753591,-18.032955),(26.769714,-18.029028),(26.794002,-18.026237),(26.88826,-17.984586),(26.912031,-17.992027),(26.94867,-17.968876),(26.95916,-17.964742),(27.006289,-17.962675),(27.021275,-17.958541),(27.048457,-17.944278),(27.078171,-17.916993),(27.11543,-17.882163),(27.149019,-17.842476),(27.146539,-17.818911),(27.145299,-17.794107),(27.146952,-17.783875),(27.157081,-17.769302),(27.422078,-17.504822),(27.524294,-17.415112),(27.577314,-17.363125),(27.604495,-17.312792),(27.624856,-17.233314),(27.641186,-17.198484),(27.777301,-17.001183),(27.816886,-16.959636),(27.868562,-16.929663),(28.022993,-16.865393),(28.113922,-16.827551),(28.21252,-16.748589),(28.280113,-16.706524),(28.643295,-16.568755),(28.690734,-16.56028),(28.718794,-16.56028),(28.73285,-16.55811),(28.741377,-16.550668),(28.761117,-16.532271),(28.769282,-16.515218),(28.808866,-16.486279),(28.822509,-16.470776),(28.829124,-16.434603),(28.833051,-16.426438),(28.857236,-16.388198),(28.857029,-16.36546),(28.840492,-16.323602),(28.836772,-16.306342),(28.840286,-16.284741),(28.86416,-16.231205),(28.847107,-16.202679),(28.852481,-16.162785),(28.8654,-16.121237),(28.870981,-16.087234),(28.868501,-16.08217),(28.86385,-16.076589),(28.859303,-16.069561),(28.857236,-16.060466),(28.860336,-16.049407),(28.874082,-16.028943),(28.877183,-16.022018),(28.898887,-15.995457),(28.932373,-15.963727),(28.946862,-15.957235),(28.951287,-15.955252),(28.972784,-15.951428),(29.018053,-15.950602),(29.042341,-15.946261),(29.055053,-15.934375),(29.076344,-15.895411),(29.086162,-15.884559),(29.102182,-15.870916),(29.121716,-15.859341),(29.141869,-15.854483),(29.150964,-15.848799),(29.186311,-15.812832),(29.406969,-15.714233),(29.422059,-15.71103),(29.508462,-15.703588),(29.526239,-15.692839),(29.563446,-15.662144),(29.587217,-15.655736),(29.608559,-15.658423),(29.62799,-15.663591),(29.648505,-15.666588),(29.672793,-15.663281),(29.73005,-15.644677),(29.773252,-15.638062),(29.814283,-15.619666),(29.837331,-15.614808),(29.881773,-15.618839),(29.967504,-15.641473),(30.010654,-15.646227)] diff --git a/tests/queries/0_stateless/format_schemas/00825_protobuf_format_array_3dim.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_array_3dim.proto new file mode 100644 index 00000000000..8673924c929 --- /dev/null +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_array_3dim.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +message ABC +{ + message nested + { + message nested + { + repeated int32 c = 1; + } + repeated nested b = 1; + } + repeated nested a = 1; +} \ No newline at end of file diff --git a/tests/queries/0_stateless/format_schemas/00825_protobuf_format_array_of_arrays.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_array_of_arrays.proto new file mode 100644 index 00000000000..8f84164da2a --- /dev/null +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_array_of_arrays.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +message AA { + message nested_array { + repeated double c = 2; + } + string a = 1; + repeated nested_array b = 2; +} \ No newline at end of file diff --git a/tests/queries/0_stateless/format_schemas/00825_protobuf_format_enum_mapping.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_enum_mapping.proto new file mode 100644 index 00000000000..ba558dbbadb --- /dev/null +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_enum_mapping.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +message Message +{ + enum Enum + { + FIRST = 0; + SECOND = 1; + TEN = 10; + HUNDRED = 100; + }; + Enum x = 1; +}; \ No newline at end of file diff --git a/tests/queries/0_stateless/format_schemas/00825_protobuf_format_map.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_map.proto new file mode 100644 index 00000000000..561b409b733 --- /dev/null +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_map.proto @@ -0,0 +1,5 @@ +syntax = "proto3"; + +message Message { + map a = 1; +}; diff --git a/tests/queries/0_stateless/format_schemas/00825_protobuf_format_nested_in_nested.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_nested_in_nested.proto new file mode 100644 index 00000000000..f9617572f94 --- /dev/null +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_nested_in_nested.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +message MessageType { + message XType { + message YType { + int32 z=3; + }; + repeated YType y=2; + }; + repeated XType x=1; +}; \ No newline at end of file diff --git a/tests/queries/0_stateless/format_schemas/00825_protobuf_format_nested_optional.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_nested_optional.proto new file mode 100644 index 00000000000..052741f504b --- /dev/null +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_nested_optional.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +message Repeated { + string foo = 1; + int64 bar = 2; +} + +message Message { + repeated Repeated messages = 1; +}; \ No newline at end of file diff --git a/tests/queries/0_stateless/format_schemas/00825_protobuf_format_no_length_delimiter.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_no_length_delimiter.proto new file mode 100644 index 00000000000..9726d0dede1 --- /dev/null +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_no_length_delimiter.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +message Message { + int32 x = 1; + string str = 2; +}; diff --git a/tests/queries/0_stateless/00825_protobuf_format.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_persons.proto similarity index 97% rename from tests/queries/0_stateless/00825_protobuf_format.proto rename to tests/queries/0_stateless/format_schemas/00825_protobuf_format_persons.proto index 0d9bdd83ccd..b588619f488 100644 --- a/tests/queries/0_stateless/00825_protobuf_format.proto +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_persons.proto @@ -143,9 +143,3 @@ message StrPerson { MeasureUnits measureUnits = 21; NestinessA nestiness_a = 22; }; - -message NumberAndSquare -{ - uint32 number = 1; - uint64 square = 2; -}; diff --git a/tests/queries/0_stateless/00825_protobuf_format_syntax2.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_persons_syntax2.proto similarity index 100% rename from tests/queries/0_stateless/00825_protobuf_format_syntax2.proto rename to tests/queries/0_stateless/format_schemas/00825_protobuf_format_persons_syntax2.proto diff --git a/tests/queries/0_stateless/format_schemas/00825_protobuf_format_squares.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_squares.proto new file mode 100644 index 00000000000..bca321568f3 --- /dev/null +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_squares.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +message NumberAndSquare { + uint32 number = 1; + uint64 square = 2; +}; diff --git a/tests/queries/0_stateless/format_schemas/00825_protobuf_format_syntax2.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_syntax2.proto new file mode 100644 index 00000000000..d4abea38d4e --- /dev/null +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_syntax2.proto @@ -0,0 +1,63 @@ +syntax = "proto2"; + +message Syntax2Person { + enum Gender { + female = 0; + male = 1; + }; + + enum ZodiacSign { + aries = 0; + taurus = 1; + gemini = 2; + cancer = 3; + leo = 4; + virgo = 5; + libra = 6; + scorpius = 7; + sagittarius = 8; + capricorn = 9; + aquarius = 10; + pisces = 11; + }; + + required string uuid = 1; + required string name = 2; + required string surname = 3; + required Gender gender = 4; + required uint32 birthDate = 5; + optional bytes photo = 6; + optional string phoneNumber = 7; + optional bool isOnline = 8; + optional fixed32 visitTime = 9; + optional uint32 age = 10; + optional ZodiacSign zodiacSign = 11; + repeated string songs = 12; + repeated uint32 color = 13; + optional string hometown = 14 [default='Moscow']; + repeated float location = 15 [packed=true]; + optional double pi = 16; + optional double lotteryWin = 17; + optional float someRatio = 18; + optional float temperature = 19; + optional sint64 randomBigNumber = 20; + optional group MeasureUnits = 21 { + repeated float coef = 1; + repeated string unit = 2; + }; + optional group Nestiness = 22 + { + optional group A = 1 { + message SubB { + optional group C = 1 { + optional uint32 d = 1; + repeated uint32 e = 2; + }; + }; + optional SubB b = 100; + }; + }; + optional string newFieldStr = 23 [default='abc']; + optional int32 newFieldInt = 24 [default=-11]; + optional bool newBool = 25 [default=true]; +}; diff --git a/tests/queries/0_stateless/format_schemas/00825_protobuf_format_table_default.proto b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_table_default.proto new file mode 100644 index 00000000000..08e6049ffe0 --- /dev/null +++ b/tests/queries/0_stateless/format_schemas/00825_protobuf_format_table_default.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +message Message { + sint32 x = 1; + sint32 z = 2; +}; \ No newline at end of file diff --git a/tests/queries/0_stateless/helpers/protobuf_length_delimited_encoder.py b/tests/queries/0_stateless/helpers/protobuf_length_delimited_encoder.py new file mode 100755 index 00000000000..86c5048c8a3 --- /dev/null +++ b/tests/queries/0_stateless/helpers/protobuf_length_delimited_encoder.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 + +# The protobuf compiler protoc doesn't support encoding or decoding length-delimited protobuf message. +# To do that this script has been written. + +import argparse +import os.path +import struct +import subprocess +import sys +import tempfile + +def read_varint(input): + res = 0 + multiplier = 1 + while True: + c = input.read(1) + if len(c) == 0: + return None + b = c[0] + if b < 0x80: + res += b * multiplier + break + b -= 0x80 + res += b * multiplier + multiplier *= 0x80 + return res + +def write_varint(output, value): + while True: + if value < 0x80: + b = value + output.write(b.to_bytes(1, byteorder='little')) + break + b = (value & 0x7F) + 0x80 + output.write(b.to_bytes(1, byteorder='little')) + value = value >> 7 + +def write_hexdump(output, data): + with subprocess.Popen(["hexdump", "-C"], stdin=subprocess.PIPE, stdout=output, shell=False) as proc: + proc.communicate(data) + if proc.returncode != 0: + raise RuntimeError("hexdump returned code " + str(proc.returncode)) + output.flush() + +class FormatSchemaSplitted: + def __init__(self, format_schema): + self.format_schema = format_schema + splitted = self.format_schema.split(':') + if len(splitted) < 2: + raise RuntimeError('The format schema must have the format "schemafile:MessageType"') + path = splitted[0] + self.schemadir = os.path.dirname(path) + self.schemaname = os.path.basename(path) + if not self.schemaname.endswith(".proto"): + self.schemaname = self.schemaname + ".proto" + self.message_type = splitted[1] + +def decode(input, output, format_schema): + if not type(format_schema) is FormatSchemaSplitted: + format_schema = FormatSchemaSplitted(format_schema) + msgindex = 1 + while True: + sz = read_varint(input) + if sz is None: + break + output.write("MESSAGE #{msgindex} AT 0x{msgoffset:08X}\n".format(msgindex=msgindex, msgoffset=input.tell()).encode()) + output.flush() + msg = input.read(sz) + if len(msg) < sz: + raise EOFError('Unexpected end of file') + with subprocess.Popen(["protoc", + "--decode", format_schema.message_type, format_schema.schemaname], + cwd=format_schema.schemadir, + stdin=subprocess.PIPE, + stdout=output, + shell=False) as proc: + proc.communicate(msg) + if proc.returncode != 0: + raise RuntimeError("protoc returned code " + str(proc.returncode)) + output.flush() + msgindex = msgindex + 1 + +def encode(input, output, format_schema): + if not type(format_schema) is FormatSchemaSplitted: + format_schema = FormatSchemaSplitted(format_schema) + line_offset = input.tell() + line = input.readline() + while True: + if len(line) == 0: + break + if not line.startswith(b"MESSAGE #"): + raise RuntimeError("The line at 0x{line_offset:08X} must start with the text 'MESSAGE #'".format(line_offset=line_offset)) + msg = b"" + while True: + line_offset = input.tell() + line = input.readline() + if line.startswith(b"MESSAGE #") or len(line) == 0: + break + msg += line + with subprocess.Popen(["protoc", + "--encode", format_schema.message_type, format_schema.schemaname], + cwd=format_schema.schemadir, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + shell=False) as proc: + msgbin = proc.communicate(msg)[0] + if proc.returncode != 0: + raise RuntimeError("protoc returned code " + str(proc.returncode)) + write_varint(output, len(msgbin)) + output.write(msgbin) + output.flush() + +def decode_and_check(input, output, format_schema): + input_data = input.read() + output.write(b"Binary representation:\n") + output.flush() + write_hexdump(output, input_data) + output.write(b"\n") + output.flush() + + with tempfile.TemporaryFile() as tmp_input, tempfile.TemporaryFile() as tmp_decoded, tempfile.TemporaryFile() as tmp_encoded: + tmp_input.write(input_data) + tmp_input.flush() + tmp_input.seek(0) + decode(tmp_input, tmp_decoded, format_schema) + tmp_decoded.seek(0) + decoded_text = tmp_decoded.read() + output.write(decoded_text) + output.flush() + tmp_decoded.seek(0) + encode(tmp_decoded, tmp_encoded, format_schema) + tmp_encoded.seek(0) + encoded_data = tmp_encoded.read() + + if encoded_data == input_data: + output.write(b"\nBinary representation is as expected\n") + output.flush() + else: + output.write(b"\nBinary representation differs from the expected one (listed below):\n") + output.flush() + write_hexdump(output, encoded_data) + sys.exit(1) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Encodes or decodes length-delimited protobuf messages.') + parser.add_argument('--input', help='The input file, the standard input will be used if not specified.') + parser.add_argument('--output', help='The output file, the standard output will be used if not specified') + parser.add_argument('--format_schema', required=True, help='Format schema in the format "schemafile:MessageType"') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('--encode', action='store_true', help='Specify to encode length-delimited messages.' + 'The utility will read text-format messages of the given type from the input and write it in binary to the output.') + group.add_argument('--decode', action='store_true', help='Specify to decode length-delimited messages.' + 'The utility will read messages in binary from the input and write text-format messages to the output.') + group.add_argument('--decode_and_check', action='store_true', help='The same as --decode, and the utility will then encode ' + ' the decoded data back to the binary form to check that the result of that encoding is the same as the input was.') + args = parser.parse_args() + + custom_input_file = None + custom_output_file = None + try: + if args.input: + custom_input_file = open(args.input, "rb") + if args.output: + custom_output_file = open(args.output, "wb") + input = custom_input_file if custom_input_file else sys.stdin.buffer + output = custom_output_file if custom_output_file else sys.stdout.buffer + + if args.encode: + encode(input, output, args.format_schema) + elif args.decode: + decode(input, output, args.format_schema) + elif args.decode_and_check: + decode_and_check(input, output, args.format_schema) + + finally: + if custom_input_file: + custom_input_file.close() + if custom_output_file: + custom_output_file.close() diff --git a/tests/queries/1_stateful/00158_cache_dictionary_has.reference b/tests/queries/1_stateful/00158_cache_dictionary_has.reference index f8d5cd4f53d..ad4bce6bec5 100644 --- a/tests/queries/1_stateful/00158_cache_dictionary_has.reference +++ b/tests/queries/1_stateful/00158_cache_dictionary_has.reference @@ -1,6 +1,6 @@ +100 6410 -6410 -25323 +100 25323 -1774655 +100 1774655 diff --git a/tests/queries/1_stateful/00158_cache_dictionary_has.sql b/tests/queries/1_stateful/00158_cache_dictionary_has.sql index 063e7843fd4..8461728c58e 100644 --- a/tests/queries/1_stateful/00158_cache_dictionary_has.sql +++ b/tests/queries/1_stateful/00158_cache_dictionary_has.sql @@ -6,15 +6,15 @@ CREATE DICTIONARY db_dict.cache_hits PRIMARY KEY WatchID SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'hits' PASSWORD '' DB 'test')) LIFETIME(MIN 300 MAX 600) -LAYOUT(CACHE(SIZE_IN_CELLS 100000 QUERY_WAIT_TIMEOUT_MILLISECONDS 600000)); +LAYOUT(CACHE(SIZE_IN_CELLS 100 QUERY_WAIT_TIMEOUT_MILLISECONDS 600000)); -SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 1400 == 0); +SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 1400 == 0 LIMIT 100); SELECT count() from test.hits PREWHERE WatchID % 1400 == 0; -SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 350 == 0); +SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 350 == 0 LIMIT 100); SELECT count() from test.hits PREWHERE WatchID % 350 == 0; -SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 5 == 0); +SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 5 == 0 LIMIT 100); SELECT count() from test.hits PREWHERE WatchID % 5 == 0; DROP DICTIONARY IF EXISTS db_dict.cache_hits; diff --git a/tests/queries/query_test.py b/tests/queries/query_test.py index 3dea639187e..b747ac2944e 100644 --- a/tests/queries/query_test.py +++ b/tests/queries/query_test.py @@ -26,14 +26,14 @@ SKIP_LIST = [ "00990_metric_log_table_not_empty", "01014_lazy_database_concurrent_recreate_reattach_and_show_tables", "01018_Distributed__shard_num", - "01018_ip_dictionary", + "01018_ip_dictionary_long", "01050_clickhouse_dict_source_with_subquery", "01053_ssd_dictionary", "01054_cache_dictionary_overflow_cell", "01057_http_compression_prefer_brotli", "01080_check_for_error_incorrect_size_of_nested_column", "01083_expressions_in_engine_arguments", - "01086_odbc_roundtrip", + # "01086_odbc_roundtrip", "01088_benchmark_query_id", "01098_temporary_and_external_tables", "01099_parallel_distributed_insert_select", @@ -46,7 +46,7 @@ SKIP_LIST = [ "01293_client_interactive_vertical_singleline", # expect-test "01293_system_distribution_queue", # FLAKY "01293_show_clusters", - "01294_lazy_database_concurrent_recreate_reattach_and_show_tables", + "01294_lazy_database_concurrent_recreate_reattach_and_show_tables_long", "01294_system_distributed_on_cluster", "01300_client_save_history_when_terminated", # expect-test "01304_direct_io", diff --git a/tests/queries/shell_config.sh b/tests/queries/shell_config.sh index eed77fb107d..d20b5669cc5 100644 --- a/tests/queries/shell_config.sh +++ b/tests/queries/shell_config.sh @@ -54,6 +54,8 @@ export CLICKHOUSE_PORT_HTTP=${CLICKHOUSE_PORT_HTTP:="8123"} export CLICKHOUSE_PORT_HTTPS=${CLICKHOUSE_PORT_HTTPS:=$(${CLICKHOUSE_EXTRACT_CONFIG} --try --key=https_port 2>/dev/null)} 2>/dev/null export CLICKHOUSE_PORT_HTTPS=${CLICKHOUSE_PORT_HTTPS:="8443"} export CLICKHOUSE_PORT_HTTP_PROTO=${CLICKHOUSE_PORT_HTTP_PROTO:="http"} +export CLICKHOUSE_PORT_MYSQL=${CLICKHOUSE_PORT_MYSQL:=$(${CLICKHOUSE_EXTRACT_CONFIG} --try --key=mysql_port 2>/dev/null)} 2>/dev/null +export CLICKHOUSE_PORT_MYSQL=${CLICKHOUSE_PORT_MYSQL:="9004"} # Add database and log comment to url params if [ -v CLICKHOUSE_URL_PARAMS ] @@ -87,6 +89,17 @@ export CLICKHOUSE_CURL=${CLICKHOUSE_CURL:="${CLICKHOUSE_CURL_COMMAND} -q -s --ma export CLICKHOUSE_TMP=${CLICKHOUSE_TMP:="."} mkdir -p ${CLICKHOUSE_TMP} +export MYSQL_CLIENT_BINARY=${MYSQL_CLIENT_BINARY:="mysql"} +export MYSQL_CLIENT_CLICKHOUSE_USER=${MYSQL_CLIENT_CLICKHOUSE_USER:="default"} +# Avoids "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'" when connecting to localhost +[ -v CLICKHOUSE_HOST ] && MYSQL_CLIENT_OPT0+=" --protocol tcp " +[ -v CLICKHOUSE_HOST ] && MYSQL_CLIENT_OPT0+=" --host ${CLICKHOUSE_HOST} " +[ -v CLICKHOUSE_PORT_MYSQL ] && MYSQL_CLIENT_OPT0+=" --port ${CLICKHOUSE_PORT_MYSQL} " +[ -v CLICKHOUSE_DATABASE ] && MYSQL_CLIENT_OPT0+=" --database ${CLICKHOUSE_DATABASE} " +MYSQL_CLIENT_OPT0+=" --user ${MYSQL_CLIENT_CLICKHOUSE_USER} " +export MYSQL_CLIENT_OPT="${MYSQL_CLIENT_OPT0:-} ${MYSQL_CLIENT_OPT:-}" +export MYSQL_CLIENT=${MYSQL_CLIENT:="$MYSQL_CLIENT_BINARY ${MYSQL_CLIENT_OPT:-}"} + function clickhouse_client_removed_host_parameter() { # removing only `--host=value` and `--host value` (removing '-hvalue' feels to dangerous) with python regex. diff --git a/tests/queries/skip_list.json b/tests/queries/skip_list.json index 53fcfe8b13f..974ef48ef3c 100644 --- a/tests/queries/skip_list.json +++ b/tests/queries/skip_list.json @@ -17,7 +17,8 @@ "functions_bad_arguments", /// Too long for TSan "01603_read_with_backoff_bug", /// Too long for TSan "01646_system_restart_replicas_smoke", /// RESTART REPLICAS can acquire too much locks, while only 64 is possible from one thread under TSan - "01641_memory_tracking_insert_optimize" /// INSERT lots of rows is too heavy for TSan + "01641_memory_tracking_insert_optimize", /// INSERT lots of rows is too heavy for TSan + "01017_uniqCombined_memory_usage" /// Fine thresholds on memory usage ], "address-sanitizer": [ "00877", @@ -27,7 +28,8 @@ "01103_check_cpu_instructions_at_startup", "01473_event_time_microseconds", "01526_max_untracked_memory", /// requires TraceCollector, does not available under sanitizers - "01193_metadata_loading" + "01193_metadata_loading", + "01017_uniqCombined_memory_usage" /// Fine thresholds on memory usage ], "ub-sanitizer": [ "capnproto", @@ -48,7 +50,8 @@ "00877_memory_limit_for_new_delete", /// memory limits don't work correctly under msan because it replaces malloc/free "01473_event_time_microseconds", "01526_max_untracked_memory", /// requires TraceCollector, does not available under sanitizers - "01193_metadata_loading" + "01193_metadata_loading", + "01017_uniqCombined_memory_usage" /// Fine thresholds on memory usage ], "debug-build": [ "query_profiler", @@ -102,8 +105,168 @@ "00510_materizlized_view_and_deduplication_zookeeper", "00738_lock_for_inner_table" ], + "database-replicated": [ + /// Tests with DETACH TABLE (it's not allowed) + /// and tests with SET (session and query settings are not supported) + "memory_tracking", + "memory_usage", + "live_view", + "01720_type_map_and_casts", + "01413_alter_update_supertype", + "01149_zookeeper_mutation_stuck_after_replace_partition", + "00836_indices_alter_replicated_zookeeper", + "00652_mutations_alter_update", + "01715_tuple_insert_null_as_default", + "00825_protobuf_format_map", + "00152_insert_different_granularity", + "01715_background_checker_blather_zookeeper", + "01714_alter_drop_version", + "01114_materialize_clear_index_compact_parts", + "00814_replicated_minimalistic_part_header_zookeeper", + "01188_attach_table_from_pat", + "01415_sticking_mutations", + "01130_in_memory_parts", + "01110_dictionary_layout_without_arguments", + "01018_ddl_dictionaries_create", + "01018_ddl_dictionaries_select", + "01414_freeze_does_not_prevent_alters", + "01018_ddl_dictionaries_bad_queries", + "01686_rocksdb", + "01550_mutation_subquery", + "01070_mutations_with_dependencies", + "01070_materialize_ttl", + "01055_compact_parts", + "01017_mutations_with_nondeterministic_functions_zookeeper", + "00926_adaptive_index_granularity_pk", + "00910_zookeeper_test_alter_compression_codecs", + "00908_bloom_filter_index", + "00616_final_single_part", + "00446_clear_column_in_partition_zookeeper", + "01533_multiple_nested", + "01213_alter_rename_column_zookeeper", + "01575_disable_detach_table_of_dictionary", + "01457_create_as_table_function_structure", + "01415_inconsistent_merge_tree_settings", + "01413_allow_non_metadata_alters", + "01378_alter_rename_with_ttl_zookeeper", + "01349_mutation_datetime_key", + "01325_freeze_mutation_stuck", + "01272_suspicious_codecs", + "01181_db_atomic_drop_on_cluster", + "00957_delta_diff_bug", + "00910_zookeeper_custom_compression_codecs_replicated", + "00899_long_attach_memory_limit", + "00804_test_custom_compression_codes_log_storages", + "00804_test_alter_compression_codecs", + "00804_test_delta_codec_no_type_alter", + "00804_test_custom_compression_codecs", + "00753_alter_attach", + "00715_fetch_merged_or_mutated_part_zookeeper", + "00688_low_cardinality_serialization", + "01575_disable_detach_table_of_dictionary", + "00738_lock_for_inner_table", + "01666_blns", + "01652_ignore_and_low_cardinality", + "01651_map_functions", + "01650_fetch_patition_with_macro_in_zk_path", + "01648_mutations_and_escaping", + "01640_marks_corruption_regression", + "01622_byte_size", + "01611_string_to_low_cardinality_key_alter", + "01602_show_create_view", + "01600_log_queries_with_extensive_info", + "01560_ttl_remove_empty_parts", + "01554_bloom_filter_index_big_integer_uuid", + "01550_type_map_formats_input", + "01550_type_map_formats", + "01550_create_map_type", + "01532_primary_key_without_order_by_zookeeper", + "01511_alter_version_versioned_collapsing_merge_tree_zookeeper", + "01509_parallel_quorum_insert_no_replicas", + "01504_compression_multiple_streams", + "01494_storage_join_persistency", + "01493_storage_set_persistency", + "01493_alter_remove_properties_zookeeper", + "01475_read_subcolumns_storages", + "01475_read_subcolumns", + "01451_replicated_detach_drop_part", + "01451_detach_drop_part", + "01440_big_int_exotic_casts", + "01430_modify_sample_by_zookeeper", + "01417_freeze_partition_verbose_zookeeper", + "01417_freeze_partition_verbose", + "01396_inactive_replica_cleanup_nodes_zookeeper", + "01375_compact_parts_codecs", + "01357_version_collapsing_attach_detach_zookeeper", + "01355_alter_column_with_order", + "01291_geo_types", + "01270_optimize_skip_unused_shards_low_cardinality", + "01182_materialized_view_different_structure", + "01150_ddl_guard_rwr", + "01148_zookeeper_path_macros_unfolding", + "01135_default_and_alter_zookeeper", + "01130_in_memory_parts_partitons", + "01127_month_partitioning_consistency_select", + "01114_database_atomic", + "01083_expressions_in_engine_arguments", + "01073_attach_if_not_exists", + "01072_optimize_skip_unused_shards_const_expr_eval", + "01071_prohibition_secondary_index_with_old_format_merge_tree", + "01062_alter_on_mutataion_zookeeper", + "01060_shutdown_table_after_detach", + "01056_create_table_as", + "01035_avg", + "01021_only_tuple_columns", + "01019_alter_materialized_view_query", + "01019_alter_materialized_view_consistent", + "01019_alter_materialized_view_atomic", + "01015_attach_part", + "00989_parallel_parts_loading", + "00980_zookeeper_merge_tree_alter_settings", + "00980_merge_alter_settings", + "00955_test_final_mark", + "00933_reserved_word", + "00926_zookeeper_adaptive_index_granularity_replicated_merge_tree", + "00926_adaptive_index_granularity_replacing_merge_tree", + "00926_adaptive_index_granularity_merge_tree", + "00925_zookeeper_empty_replicated_merge_tree_optimize_final", + "00800_low_cardinality_distinct_numeric", + "00754_alter_modify_order_by_replicated_zookeeper", + "00751_low_cardinality_nullable_group_by", + "00751_default_databasename_for_view", + "00719_parallel_ddl_table", + "00718_low_cardinaliry_alter", + "00717_low_cardinaliry_distributed_group_by", + "00688_low_cardinality_syntax", + "00688_low_cardinality_nullable_cast", + "00688_low_cardinality_in", + "00652_replicated_mutations_zookeeper", + "00634_rename_view", + "00626_replace_partition_from_table", + "00625_arrays_in_nested", + "00623_replicated_truncate_table_zookeeper", + "00619_union_highlite", + "00599_create_view_with_subquery", + "00571_non_exist_database_when_create_materializ_view", + "00553_buff_exists_materlized_column", + "00516_deduplication_after_drop_partition_zookeeper", + "00508_materialized_view_to", + "00446_clear_column_in_partition_concurrent_zookeeper", + "00423_storage_log_single_thread", + "00311_array_primary_key", + "00236_replicated_drop_on_non_leader_zookeeper", + "00226_zookeeper_deduplication_and_unexpected_parts", + "00215_primary_key_order_zookeeper", + "00180_attach_materialized_view", + "00121_drop_column_zookeeper", + "00116_storage_set", + "00083_create_merge_tree_zookeeper", + "00062_replicated_merge_tree_alter_zookeeper", + "01720_constraints_complex_types", + "01747_alter_partition_key_enum_zookeeper" + ], "polymorphic-parts": [ - "01508_partition_pruning", /// bug, shoud be fixed + "01508_partition_pruning_long", /// bug, shoud be fixed "01482_move_to_prewhere_and_cast" /// bug, shoud be fixed ], "antlr": [ @@ -115,13 +278,23 @@ "00534_functions_bad_arguments4", "00534_functions_bad_arguments9", "00564_temporary_table_management", + "00600_replace_running_query", "00626_replace_partition_from_table_zookeeper", "00652_replicated_mutations_zookeeper", "00687_top_and_offset", "00746_sql_fuzzy", "00763_create_query_as_table_engine_bug", "00765_sql_compatibility_aliases", - "00825_protobuf_format_input", + "00825_protobuf_format_array_3dim", + "00825_protobuf_format_array_of_arrays", + "00825_protobuf_format_enum_mapping", + "00825_protobuf_format_map", + "00825_protobuf_format_nested_in_nested", + "00825_protobuf_format_nested_optional", + "00825_protobuf_format_no_length_delimiter", + "00825_protobuf_format_persons", + "00825_protobuf_format_squares", + "00825_protobuf_format_table_default", "00826_cross_to_inner_join", "00834_not_between", "00909_kill_not_initialized_query", @@ -152,6 +325,7 @@ "01015_attach_part", "01015_database_bad_tables", "01017_uniqCombined_memory_usage", + "01018_ddl_dictionaries_concurrent_requrests", /// Cannot parse ATTACH DICTIONARY IF NOT EXISTS "01019_alter_materialized_view_atomic", "01019_alter_materialized_view_consistent", "01019_alter_materialized_view_query", @@ -222,7 +396,7 @@ "01293_pretty_max_value_width", "01293_show_settings", "01294_create_settings_profile", - "01294_lazy_database_concurrent_recreate_reattach_and_show_tables", + "01294_lazy_database_concurrent_recreate_reattach_and_show_tables_long", "01295_create_row_policy", "01296_create_row_policy_in_current_database", "01297_create_quota", @@ -267,7 +441,7 @@ "01501_clickhouse_client_INSERT_exception", "01504_compression_multiple_streams", "01508_explain_header", - "01508_partition_pruning", + "01508_partition_pruning_long", "01509_check_parallel_quorum_inserts", "01509_parallel_quorum_and_merge", "01515_mv_and_array_join_optimisation_bag", @@ -281,7 +455,7 @@ "01530_drop_database_atomic_sync", "01532_execute_merges_on_single_replica", "01532_primary_key_without_order_by_zookeeper", - "01541_max_memory_usage_for_user", + "01541_max_memory_usage_for_user_long", "01551_mergetree_read_in_order_spread", "01552_dict_fixedstring", "01554_bloom_filter_index_big_integer_uuid", @@ -349,6 +523,7 @@ "00575_illegal_column_exception_when_drop_depen_column", "00599_create_view_with_subquery", "00604_show_create_database", + "00600_replace_running_query", "00612_http_max_query_size", "00619_union_highlite", "00620_optimize_on_nonleader_replica_zookeeper", @@ -358,6 +533,7 @@ "00626_replace_partition_from_table", "00626_replace_partition_from_table_zookeeper", "00633_materialized_view_and_too_many_parts_zookeeper", + "00643_cast_zookeeper", "00652_mergetree_mutations", "00652_replicated_mutations_zookeeper", "00682_empty_parts_merge", @@ -416,7 +592,7 @@ "01018_ddl_dictionaries_select", "01018_ddl_dictionaries_special", "01018_dictionaries_from_dictionaries", - "01018_ip_dictionary", + "01018_ip_dictionary_long", "01021_only_tuple_columns", "01023_materialized_view_query_context", "01031_mutations_interpreter_and_context", @@ -505,7 +681,7 @@ "01281_unsucceeded_insert_select_queries_counter", "01293_system_distribution_queue", "01294_lazy_database_concurrent", - "01294_lazy_database_concurrent_recreate_reattach_and_show_tables", + "01294_lazy_database_concurrent_recreate_reattach_and_show_tables_long", "01294_system_distributed_on_cluster", "01296_create_row_policy_in_current_database", "01297_create_quota", @@ -558,7 +734,7 @@ "01527_clickhouse_local_optimize", "01527_dist_sharding_key_dictGet_reload", "01530_drop_database_atomic_sync", - "01541_max_memory_usage_for_user", + "01541_max_memory_usage_for_user_long", "01542_dictionary_load_exception_race", "01575_disable_detach_table_of_dictionary", "01593_concurrent_alter_mutations_kill", @@ -571,8 +747,12 @@ "01602_show_create_view", "01603_rename_overwrite_bug", "01646_system_restart_replicas_smoke", // system restart replicas is a global query + "01656_test_query_log_factories_info", + "01669_columns_declaration_serde", "01676_dictget_in_default_expression", + "01700_system_zookeeper_path_in", "01715_background_checker_blather_zookeeper", + "01747_alter_partition_key_enum_zookeeper", "attach", "ddl_dictionaries", "dictionary", @@ -580,6 +760,16 @@ "live_view", "memory_leak", "memory_limit", - "polygon_dicts" // they use an explicitly specified database + "polygon_dicts", // they use an explicitly specified database + "01658_read_file_to_stringcolumn", + "01721_engine_file_truncate_on_insert", // It's ok to execute in parallel but not several instances of the same test. + "01702_system_query_log", // It's ok to execute in parallel with oter tests but not several instances of the same test. + "01748_dictionary_table_dot", // creates database + "00950_dict_get", + "01683_flat_dictionary", + "01681_cache_dictionary_simple_key", + "01682_cache_dictionary_complex_key", + "01684_ssd_cache_dictionary_simple_key", + "01685_ssd_cache_dictionary_complex_key" ] } diff --git a/tests/testflows/aes_encryption/configs/clickhouse/config.xml b/tests/testflows/aes_encryption/configs/clickhouse/config.xml index d34d2c35253..beeeafa5704 100644 --- a/tests/testflows/aes_encryption/configs/clickhouse/config.xml +++ b/tests/testflows/aes_encryption/configs/clickhouse/config.xml @@ -406,7 +406,7 @@ 86400 - 60 + 7200 diff --git a/tests/testflows/aes_encryption/docker-compose/docker-compose.yml b/tests/testflows/aes_encryption/docker-compose/docker-compose.yml index 04a51ad7ec0..124b53bf502 100644 --- a/tests/testflows/aes_encryption/docker-compose/docker-compose.yml +++ b/tests/testflows/aes_encryption/docker-compose/docker-compose.yml @@ -56,7 +56,7 @@ services: zookeeper: condition: service_healthy - # dummy service which does nothing, but allows to postpone + # dummy service which does nothing, but allows to postpone # 'docker-compose up -d' till all dependecies will go healthy all_services_ready: image: hello-world diff --git a/tests/testflows/aes_encryption/docker-compose/zookeeper-service.yml b/tests/testflows/aes_encryption/docker-compose/zookeeper-service.yml index f3df33358be..f27405b97a2 100644 --- a/tests/testflows/aes_encryption/docker-compose/zookeeper-service.yml +++ b/tests/testflows/aes_encryption/docker-compose/zookeeper-service.yml @@ -2,7 +2,7 @@ version: '2.3' services: zookeeper: - image: zookeeper:3.4.12 + image: zookeeper:3.6.2 expose: - "2181" environment: diff --git a/tests/testflows/example/docker-compose/docker-compose.yml b/tests/testflows/example/docker-compose/docker-compose.yml index e7e57386dc4..4edb415824f 100644 --- a/tests/testflows/example/docker-compose/docker-compose.yml +++ b/tests/testflows/example/docker-compose/docker-compose.yml @@ -20,7 +20,7 @@ services: zookeeper: condition: service_healthy - # dummy service which does nothing, but allows to postpone + # dummy service which does nothing, but allows to postpone # 'docker-compose up -d' till all dependecies will go healthy all_services_ready: image: hello-world diff --git a/tests/testflows/example/docker-compose/zookeeper-service.yml b/tests/testflows/example/docker-compose/zookeeper-service.yml index 6691a2df31c..ca732a48dbd 100644 --- a/tests/testflows/example/docker-compose/zookeeper-service.yml +++ b/tests/testflows/example/docker-compose/zookeeper-service.yml @@ -2,7 +2,7 @@ version: '2.3' services: zookeeper: - image: zookeeper:3.4.12 + image: zookeeper:3.6.2 expose: - "2181" environment: diff --git a/tests/testflows/helpers/cluster.py b/tests/testflows/helpers/cluster.py index 5e8717e7a8e..cc676134024 100755 --- a/tests/testflows/helpers/cluster.py +++ b/tests/testflows/helpers/cluster.py @@ -26,7 +26,7 @@ class Node(object): def repr(self): return f"Node(name='{self.name}')" - def restart(self, timeout=300, retries=5): + def restart(self, timeout=300, retries=5, safe=True): """Restart node. """ with self.cluster.lock: @@ -48,7 +48,7 @@ class Node(object): if r.exitcode == 0: break - def stop(self, timeout=300, retries=5): + def stop(self, timeout=300, retries=5, safe=True): """Stop node. """ with self.cluster.lock: @@ -65,6 +65,44 @@ class Node(object): def command(self, *args, **kwargs): return self.cluster.command(self.name, *args, **kwargs) + def cmd(self, cmd, message=None, exitcode=None, steps=True, shell_command="bash --noediting", no_checks=False, + raise_on_exception=False, step=By, *args, **kwargs): + """Execute and check command. + :param cmd: command + :param message: expected message that should be in the output, default: None + :param exitcode: expected exitcode, default: None + """ + + command = f"{cmd}" + with Step("executing command", description=command, format_description=False) if steps else NullStep(): + try: + r = self.cluster.bash(self.name, command=shell_command)(command, *args, **kwargs) + except ExpectTimeoutError: + self.cluster.close_bash(self.name) + raise + + if no_checks: + return r + + if exitcode is not None: + with Then(f"exitcode should be {exitcode}") if steps else NullStep(): + assert r.exitcode == exitcode, error(r.output) + + if message is not None: + with Then(f"output should contain message", description=message) if steps else NullStep(): + assert message in r.output, error(r.output) + + if message is None or "Exception:" not in message: + with Then("check if output has exception") if steps else NullStep(): + if "Exception:" in r.output: + if raise_on_exception: + raise QueryRuntimeException(r.output) + assert False, error(r.output) + + return r + + + class ClickHouseNode(Node): """Node with ClickHouse server. """ @@ -163,7 +201,7 @@ class ClickHouseNode(Node): echo -e \"{sql[:100]}...\" > {query.name} {command} """ - with step("executing command", description=description, format_description=False) if steps else NullStep(): + with Step("executing command", description=description, format_description=False) if steps else NullStep(): try: r = self.cluster.bash(None)(command, *args, **kwargs) except ExpectTimeoutError: @@ -173,7 +211,7 @@ class ClickHouseNode(Node): for setting in settings: name, value = setting command += f" --{name} \"{value}\"" - with step("executing command", description=command, format_description=False) if steps else NullStep(): + with Step("executing command", description=command, format_description=False) if steps else NullStep(): try: r = self.cluster.bash(self.name)(command, *args, **kwargs) except ExpectTimeoutError: @@ -227,7 +265,7 @@ class Cluster(object): self.configs_dir = caller_configs_dir if not os.path.exists(self.configs_dir): - raise TypeError("configs directory '{self.configs_dir}' does not exist") + raise TypeError(f"configs directory '{self.configs_dir}' does not exist") # auto set docker-compose project directory if docker_compose_project_dir is None: @@ -256,7 +294,7 @@ class Cluster(object): shell.timeout = timeout return shell - def bash(self, node, timeout=300): + def bash(self, node, timeout=300, command="bash --noediting"): """Returns thread-local bash terminal to a specific node. :param node: name of the service @@ -278,7 +316,7 @@ class Cluster(object): self._bash[id] = Shell().__enter__() else: self._bash[id] = Shell(command=[ - "/bin/bash", "--noediting", "-c", f"{self.docker_compose} exec {node} bash --noediting" + "/bin/bash", "--noediting", "-c", f"{self.docker_compose} exec {node} {command}" ], name=node).__enter__() self._bash[id].timeout = timeout diff --git a/tests/testflows/kerberos/configs/clickhouse/common.xml b/tests/testflows/kerberos/configs/clickhouse/common.xml new file mode 100644 index 00000000000..df952b28c82 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/common.xml @@ -0,0 +1,6 @@ + + Europe/Moscow + 0.0.0.0 + /var/lib/clickhouse/ + /var/lib/clickhouse/tmp/ + diff --git a/tests/testflows/kerberos/configs/clickhouse/config.d/logs.xml b/tests/testflows/kerberos/configs/clickhouse/config.d/logs.xml new file mode 100644 index 00000000000..bdf1bbc11c1 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/config.d/logs.xml @@ -0,0 +1,17 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + + system + part_log
+ 500 +
+
diff --git a/tests/testflows/kerberos/configs/clickhouse/config.d/ports.xml b/tests/testflows/kerberos/configs/clickhouse/config.d/ports.xml new file mode 100644 index 00000000000..fbc6cea74c0 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/config.d/ports.xml @@ -0,0 +1,5 @@ + + + 8443 + 9440 + \ No newline at end of file diff --git a/tests/testflows/kerberos/configs/clickhouse/config.d/remote.xml b/tests/testflows/kerberos/configs/clickhouse/config.d/remote.xml new file mode 100644 index 00000000000..51be2a6e8e3 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/config.d/remote.xml @@ -0,0 +1,107 @@ + + + + + + true + + clickhouse1 + 9000 + + + clickhouse2 + 9000 + + + clickhouse3 + 9000 + + + + + + + true + + clickhouse1 + 9440 + 1 + + + clickhouse2 + 9440 + 1 + + + clickhouse3 + 9440 + 1 + + + + + + + clickhouse1 + 9000 + + + + + clickhouse2 + 9000 + + + + + clickhouse3 + 9000 + + + + + + + clickhouse1 + 9440 + 1 + + + + + clickhouse2 + 9440 + 1 + + + + + clickhouse3 + 9440 + 1 + + + + + diff --git a/tests/testflows/kerberos/configs/clickhouse/config.d/ssl.xml b/tests/testflows/kerberos/configs/clickhouse/config.d/ssl.xml new file mode 100644 index 00000000000..ca65ffd5e04 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/config.d/ssl.xml @@ -0,0 +1,17 @@ + + + + /etc/clickhouse-server/ssl/server.crt + /etc/clickhouse-server/ssl/server.key + none + true + + + true + none + + AcceptCertificateHandler + + + + diff --git a/tests/testflows/kerberos/configs/clickhouse/config.d/storage.xml b/tests/testflows/kerberos/configs/clickhouse/config.d/storage.xml new file mode 100644 index 00000000000..618fd6b6d24 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/config.d/storage.xml @@ -0,0 +1,20 @@ + + + + + + 1024 + + + + + + + default + + + + + + + diff --git a/tests/testflows/kerberos/configs/clickhouse/config.d/zookeeper.xml b/tests/testflows/kerberos/configs/clickhouse/config.d/zookeeper.xml new file mode 100644 index 00000000000..96270e7b645 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/config.d/zookeeper.xml @@ -0,0 +1,10 @@ + + + + + zookeeper + 2181 + + 15000 + + diff --git a/tests/testflows/kerberos/configs/clickhouse/config.xml b/tests/testflows/kerberos/configs/clickhouse/config.xml new file mode 100644 index 00000000000..a0133238f25 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/config.xml @@ -0,0 +1,440 @@ + + + + + + trace + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + + 8123 + 9000 + + + + + + + + + /etc/clickhouse-server/server.crt + /etc/clickhouse-server/server.key + + /etc/clickhouse-server/dhparam.pem + none + true + true + sslv2,sslv3 + true + + + + true + true + sslv2,sslv3 + true + + + + RejectCertificateHandler + + + + + + + + + 9009 + + + + + + + + 0.0.0.0 + + + + + + + + + + + + 4096 + 3 + + + 100 + + + + + + 8589934592 + + + 5368709120 + + + + /var/lib/clickhouse/ + + + /var/lib/clickhouse/tmp/ + + + /var/lib/clickhouse/user_files/ + + + + + + users.xml + + + + /var/lib/clickhouse/access/ + + + + + default + + + + + + default + + + + + + + + + false + + + + + + + + localhost + 9000 + + + + + + + localhost + 9000 + + + + + localhost + 9000 + + + + + + + localhost + 9440 + 1 + + + + + + + localhost + 9000 + + + + + localhost + 1 + + + + + + + + + + + + + + + + + 3600 + + + + 3600 + + + 60 + + + + + + + + + + system + query_log
+ + toYYYYMM(event_date) + + 7500 +
+ + + + system + trace_log
+ + toYYYYMM(event_date) + 7500 +
+ + + + system + query_thread_log
+ toYYYYMM(event_date) + 7500 +
+ + + + + + + + + + + + + + + + *_dictionary.xml + + + + + + + + + + /clickhouse/task_queue/ddl + + + + + + + + + + + + + + + + click_cost + any + + 0 + 3600 + + + 86400 + 60 + + + + max + + 0 + 60 + + + 3600 + 300 + + + 86400 + 3600 + + + + + + /var/lib/clickhouse/format_schemas/ + + + +
diff --git a/tests/testflows/kerberos/configs/clickhouse/ssl/dhparam.pem b/tests/testflows/kerberos/configs/clickhouse/ssl/dhparam.pem new file mode 100644 index 00000000000..2e6cee0798d --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/ssl/dhparam.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAua92DDli13gJ+//ZXyGaggjIuidqB0crXfhUlsrBk9BV1hH3i7fR +XGP9rUdk2ubnB3k2ejBStL5oBrkHm9SzUFSQHqfDjLZjKoUpOEmuDc4cHvX1XTR5 +Pr1vf5cd0yEncJWG5W4zyUB8k++SUdL2qaeslSs+f491HBLDYn/h8zCgRbBvxhxb +9qeho1xcbnWeqkN6Kc9bgGozA16P9NLuuLttNnOblkH+lMBf42BSne/TWt3AlGZf +slKmmZcySUhF8aKfJnLKbkBCFqOtFRh8zBA9a7g+BT/lSANATCDPaAk1YVih2EKb +dpc3briTDbRsiqg2JKMI7+VdULY9bh3EawIBAg== +-----END DH PARAMETERS----- diff --git a/tests/testflows/kerberos/configs/clickhouse/ssl/server.crt b/tests/testflows/kerberos/configs/clickhouse/ssl/server.crt new file mode 100644 index 00000000000..7ade2d96273 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/ssl/server.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIC/TCCAeWgAwIBAgIJANjx1QSR77HBMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV +BAMMCWxvY2FsaG9zdDAgFw0xODA3MzAxODE2MDhaGA8yMjkyMDUxNDE4MTYwOFow +FDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAs9uSo6lJG8o8pw0fbVGVu0tPOljSWcVSXH9uiJBwlZLQnhN4SFSFohfI +4K8U1tBDTnxPLUo/V1K9yzoLiRDGMkwVj6+4+hE2udS2ePTQv5oaMeJ9wrs+5c9T +4pOtlq3pLAdm04ZMB1nbrEysceVudHRkQbGHzHp6VG29Fw7Ga6YpqyHQihRmEkTU +7UCYNA+Vk7aDPdMS/khweyTpXYZimaK9f0ECU3/VOeG3fH6Sp2X6FN4tUj/aFXEj +sRmU5G2TlYiSIUMF2JPdhSihfk1hJVALrHPTU38SOL+GyyBRWdNcrIwVwbpvsvPg +pryMSNxnpr0AK0dFhjwnupIv5hJIOQIDAQABo1AwTjAdBgNVHQ4EFgQUjPLb3uYC +kcamyZHK4/EV8jAP0wQwHwYDVR0jBBgwFoAUjPLb3uYCkcamyZHK4/EV8jAP0wQw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAM/ocuDvfPus/KpMVD51j +4IdlU8R0vmnYLQ+ygzOAo7+hUWP5j0yvq4ILWNmQX6HNvUggCgFv9bjwDFhb/5Vr +85ieWfTd9+LTjrOzTw4avdGwpX9G+6jJJSSq15tw5ElOIFb/qNA9O4dBiu8vn03C +L/zRSXrARhSqTW5w/tZkUcSTT+M5h28+Lgn9ysx4Ff5vi44LJ1NnrbJbEAIYsAAD ++UA+4MBFKx1r6hHINULev8+lCfkpwIaeS8RL+op4fr6kQPxnULw8wT8gkuc8I4+L +P9gg/xDHB44T3ADGZ5Ib6O0DJaNiToO6rnoaaxs0KkotbvDWvRoxEytSbXKoYjYp +0g== +-----END CERTIFICATE----- diff --git a/tests/testflows/kerberos/configs/clickhouse/ssl/server.key b/tests/testflows/kerberos/configs/clickhouse/ssl/server.key new file mode 100644 index 00000000000..f0fb61ac443 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/ssl/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCz25KjqUkbyjyn +DR9tUZW7S086WNJZxVJcf26IkHCVktCeE3hIVIWiF8jgrxTW0ENOfE8tSj9XUr3L +OguJEMYyTBWPr7j6ETa51LZ49NC/mhox4n3Cuz7lz1Pik62WreksB2bThkwHWdus +TKxx5W50dGRBsYfMenpUbb0XDsZrpimrIdCKFGYSRNTtQJg0D5WTtoM90xL+SHB7 +JOldhmKZor1/QQJTf9U54bd8fpKnZfoU3i1SP9oVcSOxGZTkbZOViJIhQwXYk92F +KKF+TWElUAusc9NTfxI4v4bLIFFZ01ysjBXBum+y8+CmvIxI3GemvQArR0WGPCe6 +ki/mEkg5AgMBAAECggEATrbIBIxwDJOD2/BoUqWkDCY3dGevF8697vFuZKIiQ7PP +TX9j4vPq0DfsmDjHvAPFkTHiTQXzlroFik3LAp+uvhCCVzImmHq0IrwvZ9xtB43f +7Pkc5P6h1l3Ybo8HJ6zRIY3TuLtLxuPSuiOMTQSGRL0zq3SQ5DKuGwkz+kVjHXUN +MR2TECFwMHKQ5VLrC+7PMpsJYyOMlDAWhRfUalxC55xOXTpaN8TxNnwQ8K2ISVY5 +212Jz/a4hn4LdwxSz3Tiu95PN072K87HLWx3EdT6vW4Ge5P/A3y+smIuNAlanMnu +plHBRtpATLiTxZt/n6npyrfQVbYjSH7KWhB8hBHtaQKBgQDh9Cq1c/KtqDtE0Ccr +/r9tZNTUwBE6VP+3OJeKdEdtsfuxjOCkS1oAjgBJiSDOiWPh1DdoDeVZjPKq6pIu +Mq12OE3Doa8znfCXGbkSzEKOb2unKZMJxzrz99kXt40W5DtrqKPNb24CNqTiY8Aa +CjtcX+3weat82VRXvph6U8ltMwKBgQDLxjiQQzNoY7qvg7CwJCjf9qq8jmLK766g +1FHXopqS+dTxDLM8eJSRrpmxGWJvNeNc1uPhsKsKgotqAMdBUQTf7rSTbt4MyoH5 +bUcRLtr+0QTK9hDWMOOvleqNXha68vATkohWYfCueNsC60qD44o8RZAS6UNy3ENq +cM1cxqe84wKBgQDKkHutWnooJtajlTxY27O/nZKT/HA1bDgniMuKaz4R4Gr1PIez +on3YW3V0d0P7BP6PWRIm7bY79vkiMtLEKdiKUGWeyZdo3eHvhDb/3DCawtau8L2K +GZsHVp2//mS1Lfz7Qh8/L/NedqCQ+L4iWiPnZ3THjjwn3CoZ05ucpvrAMwKBgB54 +nay039MUVq44Owub3KDg+dcIU62U+cAC/9oG7qZbxYPmKkc4oL7IJSNecGHA5SbU +2268RFdl/gLz6tfRjbEOuOHzCjFPdvAdbysanpTMHLNc6FefJ+zxtgk9sJh0C4Jh +vxFrw9nTKKzfEl12gQ1SOaEaUIO0fEBGbe8ZpauRAoGAMAlGV+2/K4ebvAJKOVTa +dKAzQ+TD2SJmeR1HZmKDYddNqwtZlzg3v4ZhCk4eaUmGeC1Bdh8MDuB3QQvXz4Dr +vOIP4UVaOr+uM+7TgAgVnP4/K6IeJGzUDhX93pmpWhODfdu/oojEKVcpCojmEmS1 +KCBtmIrQLqzMpnBpLNuSY+Q= +-----END PRIVATE KEY----- diff --git a/tests/testflows/kerberos/configs/clickhouse/users.xml b/tests/testflows/kerberos/configs/clickhouse/users.xml new file mode 100644 index 00000000000..86b2cd9e1e3 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse/users.xml @@ -0,0 +1,133 @@ + + + + + + + + 10000000000 + + + 0 + + + random + + + + + 1 + + + + + + + + + + + + + ::/0 + + + + default + + + default + + + 1 + + + + + + + + + + + + + + + + + 3600 + + + 0 + 0 + 0 + 0 + 0 + + + + diff --git a/tests/testflows/kerberos/configs/clickhouse1/config.d/kerberos.xml b/tests/testflows/kerberos/configs/clickhouse1/config.d/kerberos.xml new file mode 100644 index 00000000000..ceaa497c561 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse1/config.d/kerberos.xml @@ -0,0 +1,5 @@ + + + EXAMPLE.COM + + \ No newline at end of file diff --git a/tests/testflows/kerberos/configs/clickhouse1/config.d/macros.xml b/tests/testflows/kerberos/configs/clickhouse1/config.d/macros.xml new file mode 100644 index 00000000000..6cdcc1b440c --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse1/config.d/macros.xml @@ -0,0 +1,8 @@ + + + + clickhouse1 + 01 + 01 + + diff --git a/tests/testflows/kerberos/configs/clickhouse1/users.d/kerberos-users.xml b/tests/testflows/kerberos/configs/clickhouse1/users.d/kerberos-users.xml new file mode 100644 index 00000000000..7029f20217f --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse1/users.d/kerberos-users.xml @@ -0,0 +1,10 @@ + + + + + EXAMPLE.COM + + 1 + + + \ No newline at end of file diff --git a/tests/testflows/kerberos/configs/clickhouse2/config.d/kerberos.xml b/tests/testflows/kerberos/configs/clickhouse2/config.d/kerberos.xml new file mode 100644 index 00000000000..ceaa497c561 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse2/config.d/kerberos.xml @@ -0,0 +1,5 @@ + + + EXAMPLE.COM + + \ No newline at end of file diff --git a/tests/testflows/kerberos/configs/clickhouse2/config.d/macros.xml b/tests/testflows/kerberos/configs/clickhouse2/config.d/macros.xml new file mode 100644 index 00000000000..a114a9ce4ab --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse2/config.d/macros.xml @@ -0,0 +1,8 @@ + + + + clickhouse2 + 01 + 02 + + diff --git a/tests/testflows/kerberos/configs/clickhouse3/config.d/macros.xml b/tests/testflows/kerberos/configs/clickhouse3/config.d/macros.xml new file mode 100644 index 00000000000..904a27b0172 --- /dev/null +++ b/tests/testflows/kerberos/configs/clickhouse3/config.d/macros.xml @@ -0,0 +1,8 @@ + + + + clickhouse3 + 01 + 03 + + diff --git a/tests/testflows/kerberos/configs/kerberos/etc/krb5.conf b/tests/testflows/kerberos/configs/kerberos/etc/krb5.conf new file mode 100644 index 00000000000..b963fc25daa --- /dev/null +++ b/tests/testflows/kerberos/configs/kerberos/etc/krb5.conf @@ -0,0 +1,38 @@ +[kdc] + require-preauth = false + +[libdefaults] + default_realm = EXAMPLE.COM + ticket_lifetime = 24000 + dns_lookup_realm = false + dns_lookup_kdc = false + dns_fallback = false + rdns = false + +[realms] + EXAMPLE.COM = { + kdc = kerberos + admin_server = kerberos + } + OTHER.COM = { + kdc = kerberos + admin_server = kerberos + } + +[domain_realm] + docker-compose_default = EXAMPLE.COM + .docker-compose_default = EXAMPLE.COM + +[appdefaults] + validate = false + pam = { + debug = false + ticket_lifetime = 36000 + renew_lifetime = 36000 + forwardable = true + krb4_convert = false + } + +[logging] + kdc = FILE:/var/log/krb5kdc.log + admin_server = FILE:/var/log/kadmin.log diff --git a/tests/testflows/kerberos/configs/kerberos/etc/krb5kdc/kdc.conf b/tests/testflows/kerberos/configs/kerberos/etc/krb5kdc/kdc.conf new file mode 100644 index 00000000000..9afe5351467 --- /dev/null +++ b/tests/testflows/kerberos/configs/kerberos/etc/krb5kdc/kdc.conf @@ -0,0 +1,15 @@ +[kdcdefaults] + kdc_ports = 88 + +[realms] + EXAMPLE.COM = { + kadmind_port = 749 + max_life = 12h 0m 0s + max_renewable_life = 7d 0h 0m 0s + master_key_type = des3-hmac-sha1 + supported_enctypes = des3-hmac-sha1:normal des-cbc-crc:normal des-cbc-crc:v4 + } + +[logging] + kdc = FILE:/usr/local/var/krb5kdc/kdc.log + admin_server = FILE:/usr/local/var/krb5kdc/kadmin.log diff --git a/tests/testflows/kerberos/configs/kerberos/etc/supervisord.conf b/tests/testflows/kerberos/configs/kerberos/etc/supervisord.conf new file mode 100644 index 00000000000..bec4ae41077 --- /dev/null +++ b/tests/testflows/kerberos/configs/kerberos/etc/supervisord.conf @@ -0,0 +1,31 @@ +[inet_http_server] +port=9001 + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl = http://127.0.0.1:9001 + +[program:krb5kdc] +command = /usr/sbin/krb5kdc -n +startretries = 1 +startsecs = 5 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 + +[program:kadmind] +command = /usr/sbin/kadmind -nofork +startretries = 1 +startsecs = 5 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 + + +[supervisord] +logfile = /tmp/supervisord_zbx_server.log +loglevel = critical +nodaemon = true +user = root +pidfile = /tmp/supervisord_zbx_server.pid +directory = /tmp \ No newline at end of file diff --git a/tests/testflows/kerberos/docker-compose/clickhouse-service.yml b/tests/testflows/kerberos/docker-compose/clickhouse-service.yml new file mode 100644 index 00000000000..14736a264b8 --- /dev/null +++ b/tests/testflows/kerberos/docker-compose/clickhouse-service.yml @@ -0,0 +1,32 @@ +version: '2.3' + +services: + clickhouse: + image: yandex/clickhouse-integration-test:21454 + expose: + - "9000" + - "9009" + - "8123" + volumes: + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/ssl:/etc/clickhouse-server/ssl" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/config.xml:/etc/clickhouse-server/config.xml" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/users.xml:/etc/clickhouse-server/users.xml" + - "${CLICKHOUSE_TESTS_SERVER_BIN_PATH:-/usr/bin/clickhouse}:/usr/bin/clickhouse" + - "${CLICKHOUSE_TESTS_ODBC_BRIDGE_BIN_PATH:-/usr/bin/clickhouse-odbc-bridge}:/usr/bin/clickhouse-odbc-bridge" + - "${CLICKHOUSE_TESTS_DIR}/configs/kerberos/etc/krb5.conf:/etc/krb5.conf" + entrypoint: bash -c "clickhouse server --config-file=/etc/clickhouse-server/config.xml --log-file=/var/log/clickhouse-server/clickhouse-server.log --errorlog-file=/var/log/clickhouse-server/clickhouse-server.err.log" + healthcheck: + test: clickhouse client --query='select 1' + interval: 10s + timeout: 10s + retries: 3 + start_period: 300s + + environment: + KRB5_CLIENT_KTNAME: /etc/krb5.keytab + KRB5_KTNAME: /etc/krb5.keytab + + cap_add: + - SYS_PTRACE + security_opt: + - label:disable diff --git a/tests/testflows/kerberos/docker-compose/docker-compose.yml b/tests/testflows/kerberos/docker-compose/docker-compose.yml new file mode 100644 index 00000000000..d1a74662a83 --- /dev/null +++ b/tests/testflows/kerberos/docker-compose/docker-compose.yml @@ -0,0 +1,75 @@ +version: '2.3' + +services: + + zookeeper: + extends: + file: zookeeper-service.yml + service: zookeeper + + kerberos: + extends: + file: kerberos-service.yml + service: kerberos + hostname: kerberos + depends_on: + zookeeper: + condition: service_healthy + + clickhouse1: + extends: + file: clickhouse-service.yml + service: clickhouse + hostname: clickhouse1 + volumes: + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse1/database/:/var/lib/clickhouse/" + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse1/logs/:/var/log/clickhouse-server/" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse1/config.d:/etc/clickhouse-server/config.d" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse1/users.d:/etc/clickhouse-server/users.d" + depends_on: + zookeeper: + condition: service_healthy + + clickhouse2: + extends: + file: clickhouse-service.yml + service: clickhouse + hostname: clickhouse2 + volumes: + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse2/database/:/var/lib/clickhouse/" + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse2/logs/:/var/log/clickhouse-server/" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse2/config.d:/etc/clickhouse-server/config.d" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse2/users.d:/etc/clickhouse-server/users.d" + depends_on: + zookeeper: + condition: service_healthy + + clickhouse3: + extends: + file: clickhouse-service.yml + service: clickhouse + hostname: clickhouse3 + volumes: + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse3/database/:/var/lib/clickhouse/" + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse3/logs/:/var/log/clickhouse-server/" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse3/config.d:/etc/clickhouse-server/config.d" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse3/users.d:/etc/clickhouse-server/users.d" + depends_on: + zookeeper: + condition: service_healthy + + # dummy service which does nothing, but allows to postpone + # 'docker-compose up -d' till all dependecies will go healthy + all_services_ready: + image: hello-world + depends_on: + clickhouse1: + condition: service_healthy + clickhouse2: + condition: service_healthy + clickhouse3: + condition: service_healthy + zookeeper: + condition: service_healthy + kerberos: + condition: service_healthy diff --git a/tests/testflows/kerberos/docker-compose/kerberos-service.yml b/tests/testflows/kerberos/docker-compose/kerberos-service.yml new file mode 100644 index 00000000000..3f21e93e0b6 --- /dev/null +++ b/tests/testflows/kerberos/docker-compose/kerberos-service.yml @@ -0,0 +1,27 @@ +version: '2.3' + +services: + kerberos: + image: zvonand/docker-krb5-server:1.0.0 + restart: always + expose: + - "88" + - "464" + - "749" + healthcheck: + test: echo 1 + interval: 10s + timeout: 10s + retries: 3 + start_period: 300s + environment: + KRB5_PASS: pwd + KRB5_REALM: EXAMPLE.COM + KRB5_KDC: localhost + volumes: + - "${CLICKHOUSE_TESTS_DIR}/configs/kerberos/etc/krb5kdc/kdc.conf:/etc/krb5kdc/kdc.conf" + - "${CLICKHOUSE_TESTS_DIR}/_instances/kerberos/krb5kdc/log/kdc.log:/usr/local/var/krb5kdc/kdc.log" + - "${CLICKHOUSE_TESTS_DIR}/_instances/kerberos/krb5kdc/log/kadmin.log:/usr/local/var/krb5kdc/kadmin.log" + - "${CLICKHOUSE_TESTS_DIR}/_instances/kerberos/var/log:/var/log" + security_opt: + - label:disable diff --git a/tests/testflows/kerberos/docker-compose/zookeeper-service.yml b/tests/testflows/kerberos/docker-compose/zookeeper-service.yml new file mode 100644 index 00000000000..6691a2df31c --- /dev/null +++ b/tests/testflows/kerberos/docker-compose/zookeeper-service.yml @@ -0,0 +1,18 @@ +version: '2.3' + +services: + zookeeper: + image: zookeeper:3.4.12 + expose: + - "2181" + environment: + ZOO_TICK_TIME: 500 + ZOO_MY_ID: 1 + healthcheck: + test: echo stat | nc localhost 2181 + interval: 10s + timeout: 10s + retries: 3 + start_period: 300s + security_opt: + - label:disable diff --git a/tests/testflows/kerberos/regression.py b/tests/testflows/kerberos/regression.py new file mode 100644 index 00000000000..9675ba6e3c8 --- /dev/null +++ b/tests/testflows/kerberos/regression.py @@ -0,0 +1,38 @@ +import sys +from testflows.core import * + +append_path(sys.path, "..") + +from helpers.cluster import Cluster +from helpers.argparser import argparser +from kerberos.requirements.requirements import * + +xfails = { +} + + +@TestModule +@Name("kerberos") +@ArgumentParser(argparser) +@Requirements( + RQ_SRS_016_Kerberos("1.0") +) +@XFails(xfails) +def regression(self, local, clickhouse_binary_path, stress=None, parallel=None): + """ClickHouse Kerberos authentication test regression module. + """ + nodes = { + "clickhouse": ("clickhouse1", "clickhouse2", "clickhouse3"), + "kerberos": ("kerberos", ), + } + + with Cluster(local, clickhouse_binary_path, nodes=nodes) as cluster: + self.context.cluster = cluster + + Feature(run=load("kerberos.tests.generic", "generic"), flags=TE) + Feature(run=load("kerberos.tests.config", "config"), flags=TE) + Feature(run=load("kerberos.tests.parallel", "parallel"), flags=TE) + + +if main(): + regression() diff --git a/tests/testflows/kerberos/requirements/requirements.md b/tests/testflows/kerberos/requirements/requirements.md new file mode 100644 index 00000000000..2121dd343b8 --- /dev/null +++ b/tests/testflows/kerberos/requirements/requirements.md @@ -0,0 +1,281 @@ +# QA-SRS016 ClickHouse Kerberos Authentication +# Software Requirements Specification + +## Table of Contents + +* 1 [Revision History](#revision-history) +* 2 [Introduction](#introduction) +* 3 [Terminology](#terminology) +* 4 [Requirements](#requirements) + * 4.1 [Generic](#generic) + * 4.1.1 [RQ.SRS-016.Kerberos](#rqsrs-016kerberos) + * 4.2 [Configuration](#configuration) + * 4.2.1 [RQ.SRS-016.Kerberos.Configuration.MultipleAuthMethods](#rqsrs-016kerberosconfigurationmultipleauthmethods) + * 4.2.2 [RQ.SRS-016.Kerberos.Configuration.KerberosNotEnabled](#rqsrs-016kerberosconfigurationkerberosnotenabled) + * 4.2.3 [RQ.SRS-016.Kerberos.Configuration.MultipleKerberosSections](#rqsrs-016kerberosconfigurationmultiplekerberossections) + * 4.2.4 [RQ.SRS-016.Kerberos.Configuration.WrongUserRealm](#rqsrs-016kerberosconfigurationwronguserrealm) + * 4.2.5 [RQ.SRS-016.Kerberos.Configuration.PrincipalAndRealmSpecified](#rqsrs-016kerberosconfigurationprincipalandrealmspecified) + * 4.2.6 [RQ.SRS-016.Kerberos.Configuration.MultiplePrincipalSections](#rqsrs-016kerberosconfigurationmultipleprincipalsections) + * 4.2.7 [RQ.SRS-016.Kerberos.Configuration.MultipleRealmSections](#rqsrs-016kerberosconfigurationmultiplerealmsections) + * 4.3 [Valid User](#valid-user) + * 4.3.1 [RQ.SRS-016.Kerberos.ValidUser.XMLConfiguredUser](#rqsrs-016kerberosvaliduserxmlconfigureduser) + * 4.3.2 [RQ.SRS-016.Kerberos.ValidUser.RBACConfiguredUser](#rqsrs-016kerberosvaliduserrbacconfigureduser) + * 4.3.3 [RQ.SRS-016.Kerberos.ValidUser.KerberosNotConfigured](#rqsrs-016kerberosvaliduserkerberosnotconfigured) + * 4.4 [Invalid User](#invalid-user) + * 4.4.1 [RQ.SRS-016.Kerberos.InvalidUser](#rqsrs-016kerberosinvaliduser) + * 4.4.2 [RQ.SRS-016.Kerberos.InvalidUser.UserDeleted](#rqsrs-016kerberosinvaliduseruserdeleted) + * 4.5 [Kerberos Not Available](#kerberos-not-available) + * 4.5.1 [RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidServerTicket](#rqsrs-016kerberoskerberosnotavailableinvalidserverticket) + * 4.5.2 [RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidClientTicket](#rqsrs-016kerberoskerberosnotavailableinvalidclientticket) + * 4.5.3 [RQ.SRS-016.Kerberos.KerberosNotAvailable.ValidTickets](#rqsrs-016kerberoskerberosnotavailablevalidtickets) + * 4.6 [Kerberos Restarted](#kerberos-restarted) + * 4.6.1 [RQ.SRS-016.Kerberos.KerberosServerRestarted](#rqsrs-016kerberoskerberosserverrestarted) + * 4.7 [Performance](#performance) + * 4.7.1 [RQ.SRS-016.Kerberos.Performance](#rqsrs-016kerberosperformance) + * 4.8 [Parallel Requests processing](#parallel-requests-processing) + * 4.8.1 [RQ.SRS-016.Kerberos.Parallel](#rqsrs-016kerberosparallel) + * 4.8.2 [RQ.SRS-016.Kerberos.Parallel.ValidRequests.KerberosAndNonKerberos](#rqsrs-016kerberosparallelvalidrequestskerberosandnonkerberos) + * 4.8.3 [RQ.SRS-016.Kerberos.Parallel.ValidRequests.SameCredentials](#rqsrs-016kerberosparallelvalidrequestssamecredentials) + * 4.8.4 [RQ.SRS-016.Kerberos.Parallel.ValidRequests.DifferentCredentials](#rqsrs-016kerberosparallelvalidrequestsdifferentcredentials) + * 4.8.5 [RQ.SRS-016.Kerberos.Parallel.ValidInvalid](#rqsrs-016kerberosparallelvalidinvalid) + * 4.8.6 [RQ.SRS-016.Kerberos.Parallel.Deletion](#rqsrs-016kerberosparalleldeletion) +* 5 [References](#references) + +## Revision History + +This document is stored in an electronic form using [Git] source control management software +hosted in a [GitHub Repository]. +All the updates are tracked using the [Git]'s [Revision History]. + +## Introduction + +This document specifies the behavior for authenticating existing users via [Kerberos] authentication protocol. +Existing [ClickHouse] users, that are properly configured, have an ability to authenticate using [Kerberos]. Kerberos authentication is only supported for HTTP requests, and users configured to authenticate via Kerberos cannot be authenticated by any other means of authentication. + +In order to use Kerberos authentication, Kerberos needs to be properly configured in the environment: Kerberos server must be present and user's and server's credentials must be set up. Configuring the Kerberos environment is outside the scope of this document. + +## Terminology + +* **Principal** - + A unique identity that uses [Kerberos]. + +* **Realm** - + A logical group of resources and identities that use [Kerberos]. + +* **Ticket** - + An encrypted block of data that authenticates principal. + +* **Credentials** - + A Kerberos ticket and a session key. + +* **Kerberized request** - + A HTTP query to ClickHouse server, which uses GSS [SPNEGO] and [Kerberos] to authenticate client. + +* **Unkerberized request** - + A HTTP query to ClickHouse server, which uses any other mean of authentication than GSS [SPNEGO] or [Kerberos]. + +For a more detailed descriprion, visit [Kerberos terminology]. + +## Requirements + +### Generic + +#### RQ.SRS-016.Kerberos +version: 1.0 + +[ClickHouse] SHALL support user authentication using [Kerberos] server. + +### Configuration + +#### RQ.SRS-016.Kerberos.Configuration.MultipleAuthMethods +version: 1.0 + +[ClickHouse] SHALL generate an exception and TERMINATE in case some user in `users.xml` has a `` section specified alongside with any other authentication method's section, e.g. `ldap`, `password`. + +#### RQ.SRS-016.Kerberos.Configuration.KerberosNotEnabled +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication in case user is properly configured for using Kerberos, but Kerberos itself is not enabled in `config.xml`. For example: + +```xml + + + + +``` +```xml + + + + HTTP/clickhouse.example.com@EXAMPLE.COM + + +``` +```xml + + + + EXAMPLE.COM + + +``` + +#### RQ.SRS-016.Kerberos.Configuration.MultipleKerberosSections +version: 1.0 + +[ClickHouse] SHALL disable [Kerberos] and reject [Kerberos] authentication in case multiple `kerberos` sections are present in `config.xml`. + +#### RQ.SRS-016.Kerberos.Configuration.WrongUserRealm +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if user's realm specified in `users.xml` doesn't match the realm of the principal trying to authenticate. + +#### RQ.SRS-016.Kerberos.Configuration.PrincipalAndRealmSpecified +version: 1.0 + +[ClickHouse] SHALL generate an exception and disable [Kerberos] in case both `realm` and `principal` sections are defined in `config.xml`. + +#### RQ.SRS-016.Kerberos.Configuration.MultiplePrincipalSections +version: 1.0 + +[ClickHouse] SHALL generate an exception and disable [Kerberos] in case multiple `principal` sections are specified inside `kerberos` section in `config.xml`. + +#### RQ.SRS-016.Kerberos.Configuration.MultipleRealmSections +version: 1.0 + +[ClickHouse] SHALL generate an exception and disable [Kerberos] in case multiple `realm` sections are specified inside `kerberos` section in `config.xml`. + +### Valid User + +#### RQ.SRS-016.Kerberos.ValidUser.XMLConfiguredUser +version: 1.0 + +[ClickHouse] SHALL accept [Kerberos] authentication for a user that is configured in `users.xml` and has [Kerberos] enabled, i.e.: + +```xml + + + + + + + + EXAMPLE.COM + + + + +``` + +#### RQ.SRS-016.Kerberos.ValidUser.RBACConfiguredUser +version: 1.0 + +[ClickHouse] SHALL accept [Kerberos] authentication if user is configured to authenticate via [Kerberos] using SQL queries + +```sql +CREATE USER my_user IDENTIFIED WITH kerberos REALM 'EXAMPLE.COM' +``` + +or + +```sql +CREATE USER my_user IDENTIFIED WITH kerberos +``` + +#### RQ.SRS-016.Kerberos.ValidUser.KerberosNotConfigured +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if username is valid but [ClickHouse] user is not configured to be authenticated using [Kerberos]. + +### Invalid User + +#### RQ.SRS-016.Kerberos.InvalidUser +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if name of the principal attempting to authenticate does not translate to a valid [ClickHouse] username configured in `users.xml` or via SQL workflow. + +#### RQ.SRS-016.Kerberos.InvalidUser.UserDeleted +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if [ClickHouse] user was removed from the database using an SQL query. + +### Kerberos Not Available + +#### RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidServerTicket +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if [ClickHouse] user is configured to be authenticated using [Kerberos] and [Kerberos] server is unavailable, but [ClickHouse] doesn't have a valid Kerberos ticket or the ticket is expired. + +#### RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidClientTicket +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if [ClickHouse] user is configured to to be authenticated using [Kerberos] and [Kerberos] server is unavailable, but the client doesn't have a valid Kerberos ticket or the ticket is expired. + +#### RQ.SRS-016.Kerberos.KerberosNotAvailable.ValidTickets +version: 1.0 + +[ClickHouse] SHALL accept [Kerberos] authentication if no [Kerberos] server is reachable, but [ClickHouse] is configured to use valid credentials and [ClickHouse] has already processed some valid kerberized request (so it was granted a ticket), and the client has a valid ticket as well. + +### Kerberos Restarted + +#### RQ.SRS-016.Kerberos.KerberosServerRestarted +version: 1.0 + +[ClickHouse] SHALL accept [Kerberos] authentication if [Kerberos] server was restarted. + +### Performance + +#### RQ.SRS-016.Kerberos.Performance +version: 1.0 + +[ClickHouse]'s performance for [Kerberos] authentication SHALL be comparable to regular authentication. + +### Parallel Requests processing + +#### RQ.SRS-016.Kerberos.Parallel +version: 1.0 + +[ClickHouse] SHALL support parallel authentication using [Kerberos]. + +#### RQ.SRS-016.Kerberos.Parallel.ValidRequests.KerberosAndNonKerberos +version: 1.0 + +[ClickHouse] SHALL support processing of simultaneous kerberized (for users configured to authenticate via [Kerberos]) and non-kerberized (for users configured to authenticate with any other means) requests. + +#### RQ.SRS-016.Kerberos.Parallel.ValidRequests.SameCredentials +version: 1.0 + +[ClickHouse] SHALL support processing of simultaneously sent [Kerberos] requests under the same credentials. + +#### RQ.SRS-016.Kerberos.Parallel.ValidRequests.DifferentCredentials +version: 1.0 + +[ClickHouse] SHALL support processing of simultaneously sent [Kerberos] requests under different credentials. + +#### RQ.SRS-016.Kerberos.Parallel.ValidInvalid +version: 1.0 + +[ClickHouse] SHALL support parallel authentication of users using [Kerberos] server, some of which are valid and some invalid. Valid users' authentication should not be affected by invalid users' attempts. + +#### RQ.SRS-016.Kerberos.Parallel.Deletion +version: 1.0 + +[ClickHouse] SHALL not crash when two or more [Kerberos] users are simultaneously deleting one another. + +## References + +* **ClickHouse:** https://clickhouse.tech +* **GitHub Repository:** https://github.com/ClickHouse/ClickHouse/blob/master/tests/testflows/kerberos/requirements/requirements.md +* **Revision History:** https://github.com/ClickHouse/ClickHouse/commits/master/tests/testflows/kerberos/requirements/requirements.md +* **Git:** https://git-scm.com/ +* **Kerberos terminology:** https://web.mit.edu/kerberos/kfw-4.1/kfw-4.1/kfw-4.1-help/html/kerberos_terminology.htm + +[Kerberos]: https://en.wikipedia.org/wiki/Kerberos_(protocol) +[SPNEGO]: https://en.wikipedia.org/wiki/SPNEGO +[ClickHouse]: https://clickhouse.tech +[GitHub]: https://gitlab.com +[GitHub Repository]: https://github.com/ClickHouse/ClickHouse/blob/master/tests/testflows/kerberos/requirements/requirements.md +[Revision History]: https://github.com/ClickHouse/ClickHouse/commits/master/tests/testflows/kerberos/requirements/requirements.md +[Git]: https://git-scm.com/ +[Kerberos terminology]: https://web.mit.edu/kerberos/kfw-4.1/kfw-4.1/kfw-4.1-help/html/kerberos_terminology.htm + diff --git a/tests/testflows/kerberos/requirements/requirements.py b/tests/testflows/kerberos/requirements/requirements.py new file mode 100644 index 00000000000..5c49e7d127f --- /dev/null +++ b/tests/testflows/kerberos/requirements/requirements.py @@ -0,0 +1,800 @@ +# These requirements were auto generated +# from software requirements specification (SRS) +# document by TestFlows v1.6.201216.1172002. +# Do not edit by hand but re-generate instead +# using 'tfs requirements generate' command. +from testflows.core import Specification +from testflows.core import Requirement + +Heading = Specification.Heading + +RQ_SRS_016_Kerberos = Requirement( + name='RQ.SRS-016.Kerberos', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support user authentication using [Kerberos] server.\n' + '\n' + ), + link=None, + level=3, + num='4.1.1') + +RQ_SRS_016_Kerberos_Configuration_MultipleAuthMethods = Requirement( + name='RQ.SRS-016.Kerberos.Configuration.MultipleAuthMethods', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + "[ClickHouse] SHALL generate an exception and TERMINATE in case some user in `users.xml` has a `` section specified alongside with any other authentication method's section, e.g. `ldap`, `password`.\n" + '\n' + ), + link=None, + level=3, + num='4.2.1') + +RQ_SRS_016_Kerberos_Configuration_KerberosNotEnabled = Requirement( + name='RQ.SRS-016.Kerberos.Configuration.KerberosNotEnabled', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL reject [Kerberos] authentication in case user is properly configured for using Kerberos, but Kerberos itself is not enabled in `config.xml`. For example:\n' + '\n' + '```xml\n' + '\n' + ' \n' + ' \n' + '\n' + '```\n' + '```xml\n' + '\n' + ' \n' + ' \n' + ' HTTP/clickhouse.example.com@EXAMPLE.COM\n' + ' \n' + '\n' + '```\n' + '```xml\n' + '\n' + ' \n' + ' \n' + ' EXAMPLE.COM\n' + ' \n' + '\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='4.2.2') + +RQ_SRS_016_Kerberos_Configuration_MultipleKerberosSections = Requirement( + name='RQ.SRS-016.Kerberos.Configuration.MultipleKerberosSections', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL disable [Kerberos] and reject [Kerberos] authentication in case multiple `kerberos` sections are present in `config.xml`.\n' + '\n' + ), + link=None, + level=3, + num='4.2.3') + +RQ_SRS_016_Kerberos_Configuration_WrongUserRealm = Requirement( + name='RQ.SRS-016.Kerberos.Configuration.WrongUserRealm', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + "[ClickHouse] SHALL reject [Kerberos] authentication if user's realm specified in `users.xml` doesn't match the realm of the principal trying to authenticate.\n" + '\n' + ), + link=None, + level=3, + num='4.2.4') + +RQ_SRS_016_Kerberos_Configuration_PrincipalAndRealmSpecified = Requirement( + name='RQ.SRS-016.Kerberos.Configuration.PrincipalAndRealmSpecified', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL generate an exception and disable [Kerberos] in case both `realm` and `principal` sections are defined in `config.xml`.\n' + '\n' + ), + link=None, + level=3, + num='4.2.5') + +RQ_SRS_016_Kerberos_Configuration_MultiplePrincipalSections = Requirement( + name='RQ.SRS-016.Kerberos.Configuration.MultiplePrincipalSections', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL generate an exception and disable [Kerberos] in case multiple `principal` sections are specified inside `kerberos` section in `config.xml`.\n' + '\n' + ), + link=None, + level=3, + num='4.2.6') + +RQ_SRS_016_Kerberos_Configuration_MultipleRealmSections = Requirement( + name='RQ.SRS-016.Kerberos.Configuration.MultipleRealmSections', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL generate an exception and disable [Kerberos] in case multiple `realm` sections are specified inside `kerberos` section in `config.xml`.\n' + '\n' + ), + link=None, + level=3, + num='4.2.7') + +RQ_SRS_016_Kerberos_ValidUser_XMLConfiguredUser = Requirement( + name='RQ.SRS-016.Kerberos.ValidUser.XMLConfiguredUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL accept [Kerberos] authentication for a user that is configured in `users.xml` and has [Kerberos] enabled, i.e.:\n' + '\n' + '```xml\n' + '\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' EXAMPLE.COM\n' + ' \n' + ' \n' + ' \n' + '\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='4.3.1') + +RQ_SRS_016_Kerberos_ValidUser_RBACConfiguredUser = Requirement( + name='RQ.SRS-016.Kerberos.ValidUser.RBACConfiguredUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL accept [Kerberos] authentication if user is configured to authenticate via [Kerberos] using SQL queries\n' + '\n' + '```sql\n' + "CREATE USER my_user IDENTIFIED WITH kerberos REALM 'EXAMPLE.COM'\n" + '```\n' + '\n' + 'or\n' + '\n' + '```sql\n' + 'CREATE USER my_user IDENTIFIED WITH kerberos\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='4.3.2') + +RQ_SRS_016_Kerberos_ValidUser_KerberosNotConfigured = Requirement( + name='RQ.SRS-016.Kerberos.ValidUser.KerberosNotConfigured', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL reject [Kerberos] authentication if username is valid but [ClickHouse] user is not configured to be authenticated using [Kerberos].\n' + '\n' + ), + link=None, + level=3, + num='4.3.3') + +RQ_SRS_016_Kerberos_InvalidUser = Requirement( + name='RQ.SRS-016.Kerberos.InvalidUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL reject [Kerberos] authentication if name of the principal attempting to authenticate does not translate to a valid [ClickHouse] username configured in `users.xml` or via SQL workflow.\n' + '\n' + ), + link=None, + level=3, + num='4.4.1') + +RQ_SRS_016_Kerberos_InvalidUser_UserDeleted = Requirement( + name='RQ.SRS-016.Kerberos.InvalidUser.UserDeleted', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL reject [Kerberos] authentication if [ClickHouse] user was removed from the database using an SQL query.\n' + '\n' + ), + link=None, + level=3, + num='4.4.2') + +RQ_SRS_016_Kerberos_KerberosNotAvailable_InvalidServerTicket = Requirement( + name='RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidServerTicket', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + "[ClickHouse] SHALL reject [Kerberos] authentication if [ClickHouse] user is configured to be authenticated using [Kerberos] and [Kerberos] server is unavailable, but [ClickHouse] doesn't have a valid Kerberos ticket or the ticket is expired.\n" + '\n' + ), + link=None, + level=3, + num='4.5.1') + +RQ_SRS_016_Kerberos_KerberosNotAvailable_InvalidClientTicket = Requirement( + name='RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidClientTicket', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + "[ClickHouse] SHALL reject [Kerberos] authentication if [ClickHouse] user is configured to to be authenticated using [Kerberos] and [Kerberos] server is unavailable, but the client doesn't have a valid Kerberos ticket or the ticket is expired.\n" + '\n' + ), + link=None, + level=3, + num='4.5.2') + +RQ_SRS_016_Kerberos_KerberosNotAvailable_ValidTickets = Requirement( + name='RQ.SRS-016.Kerberos.KerberosNotAvailable.ValidTickets', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL accept [Kerberos] authentication if no [Kerberos] server is reachable, but [ClickHouse] is configured to use valid credentials and [ClickHouse] has already processed some valid kerberized request (so it was granted a ticket), and the client has a valid ticket as well.\n' + '\n' + ), + link=None, + level=3, + num='4.5.3') + +RQ_SRS_016_Kerberos_KerberosServerRestarted = Requirement( + name='RQ.SRS-016.Kerberos.KerberosServerRestarted', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL accept [Kerberos] authentication if [Kerberos] server was restarted.\n' + '\n' + ), + link=None, + level=3, + num='4.6.1') + +RQ_SRS_016_Kerberos_Performance = Requirement( + name='RQ.SRS-016.Kerberos.Performance', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + "[ClickHouse]'s performance for [Kerberos] authentication SHALL be comparable to regular authentication.\n" + '\n' + ), + link=None, + level=3, + num='4.7.1') + +RQ_SRS_016_Kerberos_Parallel = Requirement( + name='RQ.SRS-016.Kerberos.Parallel', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support parallel authentication using [Kerberos].\n' + '\n' + ), + link=None, + level=3, + num='4.8.1') + +RQ_SRS_016_Kerberos_Parallel_ValidRequests_KerberosAndNonKerberos = Requirement( + name='RQ.SRS-016.Kerberos.Parallel.ValidRequests.KerberosAndNonKerberos', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support processing of simultaneous kerberized (for users configured to authenticate via [Kerberos]) and non-kerberized (for users configured to authenticate with any other means) requests.\n' + '\n' + ), + link=None, + level=3, + num='4.8.2') + +RQ_SRS_016_Kerberos_Parallel_ValidRequests_SameCredentials = Requirement( + name='RQ.SRS-016.Kerberos.Parallel.ValidRequests.SameCredentials', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support processing of simultaneously sent [Kerberos] requests under the same credentials.\n' + '\n' + ), + link=None, + level=3, + num='4.8.3') + +RQ_SRS_016_Kerberos_Parallel_ValidRequests_DifferentCredentials = Requirement( + name='RQ.SRS-016.Kerberos.Parallel.ValidRequests.DifferentCredentials', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support processing of simultaneously sent [Kerberos] requests under different credentials.\n' + '\n' + ), + link=None, + level=3, + num='4.8.4') + +RQ_SRS_016_Kerberos_Parallel_ValidInvalid = Requirement( + name='RQ.SRS-016.Kerberos.Parallel.ValidInvalid', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + "[ClickHouse] SHALL support parallel authentication of users using [Kerberos] server, some of which are valid and some invalid. Valid users' authentication should not be affected by invalid users' attempts.\n" + '\n' + ), + link=None, + level=3, + num='4.8.5') + +RQ_SRS_016_Kerberos_Parallel_Deletion = Requirement( + name='RQ.SRS-016.Kerberos.Parallel.Deletion', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL not crash when two or more [Kerberos] users are simultaneously deleting one another.\n' + '\n' + ), + link=None, + level=3, + num='4.8.6') + +QA_SRS016_ClickHouse_Kerberos_Authentication = Specification( + name='QA-SRS016 ClickHouse Kerberos Authentication', + description=None, + author='Andrey Zvonov', + date='December 14, 2020', + status='-', + approved_by='-', + approved_date='-', + approved_version='-', + version=None, + group=None, + type=None, + link=None, + uid=None, + parent=None, + children=None, + headings=( + Heading(name='Revision History', level=1, num='1'), + Heading(name='Introduction', level=1, num='2'), + Heading(name='Terminology', level=1, num='3'), + Heading(name='Requirements', level=1, num='4'), + Heading(name='Generic', level=2, num='4.1'), + Heading(name='RQ.SRS-016.Kerberos', level=3, num='4.1.1'), + Heading(name='Configuration', level=2, num='4.2'), + Heading(name='RQ.SRS-016.Kerberos.Configuration.MultipleAuthMethods', level=3, num='4.2.1'), + Heading(name='RQ.SRS-016.Kerberos.Configuration.KerberosNotEnabled', level=3, num='4.2.2'), + Heading(name='RQ.SRS-016.Kerberos.Configuration.MultipleKerberosSections', level=3, num='4.2.3'), + Heading(name='RQ.SRS-016.Kerberos.Configuration.WrongUserRealm', level=3, num='4.2.4'), + Heading(name='RQ.SRS-016.Kerberos.Configuration.PrincipalAndRealmSpecified', level=3, num='4.2.5'), + Heading(name='RQ.SRS-016.Kerberos.Configuration.MultiplePrincipalSections', level=3, num='4.2.6'), + Heading(name='RQ.SRS-016.Kerberos.Configuration.MultipleRealmSections', level=3, num='4.2.7'), + Heading(name='Valid User', level=2, num='4.3'), + Heading(name='RQ.SRS-016.Kerberos.ValidUser.XMLConfiguredUser', level=3, num='4.3.1'), + Heading(name='RQ.SRS-016.Kerberos.ValidUser.RBACConfiguredUser', level=3, num='4.3.2'), + Heading(name='RQ.SRS-016.Kerberos.ValidUser.KerberosNotConfigured', level=3, num='4.3.3'), + Heading(name='Invalid User', level=2, num='4.4'), + Heading(name='RQ.SRS-016.Kerberos.InvalidUser', level=3, num='4.4.1'), + Heading(name='RQ.SRS-016.Kerberos.InvalidUser.UserDeleted', level=3, num='4.4.2'), + Heading(name='Kerberos Not Available', level=2, num='4.5'), + Heading(name='RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidServerTicket', level=3, num='4.5.1'), + Heading(name='RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidClientTicket', level=3, num='4.5.2'), + Heading(name='RQ.SRS-016.Kerberos.KerberosNotAvailable.ValidTickets', level=3, num='4.5.3'), + Heading(name='Kerberos Restarted', level=2, num='4.6'), + Heading(name='RQ.SRS-016.Kerberos.KerberosServerRestarted', level=3, num='4.6.1'), + Heading(name='Performance', level=2, num='4.7'), + Heading(name='RQ.SRS-016.Kerberos.Performance', level=3, num='4.7.1'), + Heading(name='Parallel Requests processing', level=2, num='4.8'), + Heading(name='RQ.SRS-016.Kerberos.Parallel', level=3, num='4.8.1'), + Heading(name='RQ.SRS-016.Kerberos.Parallel.ValidRequests.KerberosAndNonKerberos', level=3, num='4.8.2'), + Heading(name='RQ.SRS-016.Kerberos.Parallel.ValidRequests.SameCredentials', level=3, num='4.8.3'), + Heading(name='RQ.SRS-016.Kerberos.Parallel.ValidRequests.DifferentCredentials', level=3, num='4.8.4'), + Heading(name='RQ.SRS-016.Kerberos.Parallel.ValidInvalid', level=3, num='4.8.5'), + Heading(name='RQ.SRS-016.Kerberos.Parallel.Deletion', level=3, num='4.8.6'), + Heading(name='References', level=1, num='5'), + ), + requirements=( + RQ_SRS_016_Kerberos, + RQ_SRS_016_Kerberos_Configuration_MultipleAuthMethods, + RQ_SRS_016_Kerberos_Configuration_KerberosNotEnabled, + RQ_SRS_016_Kerberos_Configuration_MultipleKerberosSections, + RQ_SRS_016_Kerberos_Configuration_WrongUserRealm, + RQ_SRS_016_Kerberos_Configuration_PrincipalAndRealmSpecified, + RQ_SRS_016_Kerberos_Configuration_MultiplePrincipalSections, + RQ_SRS_016_Kerberos_Configuration_MultipleRealmSections, + RQ_SRS_016_Kerberos_ValidUser_XMLConfiguredUser, + RQ_SRS_016_Kerberos_ValidUser_RBACConfiguredUser, + RQ_SRS_016_Kerberos_ValidUser_KerberosNotConfigured, + RQ_SRS_016_Kerberos_InvalidUser, + RQ_SRS_016_Kerberos_InvalidUser_UserDeleted, + RQ_SRS_016_Kerberos_KerberosNotAvailable_InvalidServerTicket, + RQ_SRS_016_Kerberos_KerberosNotAvailable_InvalidClientTicket, + RQ_SRS_016_Kerberos_KerberosNotAvailable_ValidTickets, + RQ_SRS_016_Kerberos_KerberosServerRestarted, + RQ_SRS_016_Kerberos_Performance, + RQ_SRS_016_Kerberos_Parallel, + RQ_SRS_016_Kerberos_Parallel_ValidRequests_KerberosAndNonKerberos, + RQ_SRS_016_Kerberos_Parallel_ValidRequests_SameCredentials, + RQ_SRS_016_Kerberos_Parallel_ValidRequests_DifferentCredentials, + RQ_SRS_016_Kerberos_Parallel_ValidInvalid, + RQ_SRS_016_Kerberos_Parallel_Deletion, + ), + content=''' +# QA-SRS016 ClickHouse Kerberos Authentication +# Software Requirements Specification + +(c) 2020 Altinity LTD. All Rights Reserved. + +**Document status:** Confidential + +**Author:** Andrey Zvonov + +**Date:** December 14, 2020 + +## Approval + +**Status:** - + +**Version:** - + +**Approved by:** - + +**Date:** - + + +## Table of Contents + +* 1 [Revision History](#revision-history) +* 2 [Introduction](#introduction) +* 3 [Terminology](#terminology) +* 4 [Requirements](#requirements) + * 4.1 [Generic](#generic) + * 4.1.1 [RQ.SRS-016.Kerberos](#rqsrs-016kerberos) + * 4.2 [Configuration](#configuration) + * 4.2.1 [RQ.SRS-016.Kerberos.Configuration.MultipleAuthMethods](#rqsrs-016kerberosconfigurationmultipleauthmethods) + * 4.2.2 [RQ.SRS-016.Kerberos.Configuration.KerberosNotEnabled](#rqsrs-016kerberosconfigurationkerberosnotenabled) + * 4.2.3 [RQ.SRS-016.Kerberos.Configuration.MultipleKerberosSections](#rqsrs-016kerberosconfigurationmultiplekerberossections) + * 4.2.4 [RQ.SRS-016.Kerberos.Configuration.WrongUserRealm](#rqsrs-016kerberosconfigurationwronguserrealm) + * 4.2.5 [RQ.SRS-016.Kerberos.Configuration.PrincipalAndRealmSpecified](#rqsrs-016kerberosconfigurationprincipalandrealmspecified) + * 4.2.6 [RQ.SRS-016.Kerberos.Configuration.MultiplePrincipalSections](#rqsrs-016kerberosconfigurationmultipleprincipalsections) + * 4.2.7 [RQ.SRS-016.Kerberos.Configuration.MultipleRealmSections](#rqsrs-016kerberosconfigurationmultiplerealmsections) + * 4.3 [Valid User](#valid-user) + * 4.3.1 [RQ.SRS-016.Kerberos.ValidUser.XMLConfiguredUser](#rqsrs-016kerberosvaliduserxmlconfigureduser) + * 4.3.2 [RQ.SRS-016.Kerberos.ValidUser.RBACConfiguredUser](#rqsrs-016kerberosvaliduserrbacconfigureduser) + * 4.3.3 [RQ.SRS-016.Kerberos.ValidUser.KerberosNotConfigured](#rqsrs-016kerberosvaliduserkerberosnotconfigured) + * 4.4 [Invalid User](#invalid-user) + * 4.4.1 [RQ.SRS-016.Kerberos.InvalidUser](#rqsrs-016kerberosinvaliduser) + * 4.4.2 [RQ.SRS-016.Kerberos.InvalidUser.UserDeleted](#rqsrs-016kerberosinvaliduseruserdeleted) + * 4.5 [Kerberos Not Available](#kerberos-not-available) + * 4.5.1 [RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidServerTicket](#rqsrs-016kerberoskerberosnotavailableinvalidserverticket) + * 4.5.2 [RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidClientTicket](#rqsrs-016kerberoskerberosnotavailableinvalidclientticket) + * 4.5.3 [RQ.SRS-016.Kerberos.KerberosNotAvailable.ValidTickets](#rqsrs-016kerberoskerberosnotavailablevalidtickets) + * 4.6 [Kerberos Restarted](#kerberos-restarted) + * 4.6.1 [RQ.SRS-016.Kerberos.KerberosServerRestarted](#rqsrs-016kerberoskerberosserverrestarted) + * 4.7 [Performance](#performance) + * 4.7.1 [RQ.SRS-016.Kerberos.Performance](#rqsrs-016kerberosperformance) + * 4.8 [Parallel Requests processing](#parallel-requests-processing) + * 4.8.1 [RQ.SRS-016.Kerberos.Parallel](#rqsrs-016kerberosparallel) + * 4.8.2 [RQ.SRS-016.Kerberos.Parallel.ValidRequests.KerberosAndNonKerberos](#rqsrs-016kerberosparallelvalidrequestskerberosandnonkerberos) + * 4.8.3 [RQ.SRS-016.Kerberos.Parallel.ValidRequests.SameCredentials](#rqsrs-016kerberosparallelvalidrequestssamecredentials) + * 4.8.4 [RQ.SRS-016.Kerberos.Parallel.ValidRequests.DifferentCredentials](#rqsrs-016kerberosparallelvalidrequestsdifferentcredentials) + * 4.8.5 [RQ.SRS-016.Kerberos.Parallel.ValidInvalid](#rqsrs-016kerberosparallelvalidinvalid) + * 4.8.6 [RQ.SRS-016.Kerberos.Parallel.Deletion](#rqsrs-016kerberosparalleldeletion) +* 5 [References](#references) + +## Revision History + +This document is stored in an electronic form using [Git] source control management software +hosted in a [GitLab Repository]. +All the updates are tracked using the [Git]'s [Revision History]. + +## Introduction + +This document specifies the behavior for authenticating existing users using [Kerberos] authentication protocol. +Existing [ClickHouse] users, that are properly configured, have an ability to authenticate using [Kerberos]. Kerberos authentication is only supported for HTTP requests, and users configured to authenticate via Kerberos cannot be authenticated by any other means of authentication. + +In order to use Kerberos authentication, Kerberos needs to be properly configured in the environment: Kerberos server must be present and user's and server's credentials must be set up. Configuring the Kerberos environment is outside the scope of this document. + +## Terminology + +* **Principal** - + A unique identity that uses [Kerberos]. + +* **Realm** - + A logical group of resources and identities that use [Kerberos]. + +* **Ticket** - + An encrypted block of data that authenticates principal. + +* **Credentials** - + A Kerberos ticket and a session key. + +* **Kerberized request** - + A HTTP query to ClickHouse server, which uses GSS [SPNEGO] and [Kerberos] to authenticate client. + +* **Unkerberized request** - + A HTTP query to ClickHouse server, which uses any other mean of authentication than GSS [SPNEGO] or [Kerberos]. + +For a more detailed descriprion, visit [Kerberos terminology]. + +## Requirements + +### Generic + +#### RQ.SRS-016.Kerberos +version: 1.0 + +[ClickHouse] SHALL support user authentication using [Kerberos] server. + +### Configuration + +#### RQ.SRS-016.Kerberos.Configuration.MultipleAuthMethods +version: 1.0 + +[ClickHouse] SHALL generate an exception and TERMINATE in case some user in `users.xml` has a `` section specified alongside with any other authentication method's section, e.g. `ldap`, `password`. + +#### RQ.SRS-016.Kerberos.Configuration.KerberosNotEnabled +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication in case user is properly configured for using Kerberos, but Kerberos itself is not enabled in `config.xml`. For example: + +```xml + + + + +``` +```xml + + + + HTTP/clickhouse.example.com@EXAMPLE.COM + + +``` +```xml + + + + EXAMPLE.COM + + +``` + +#### RQ.SRS-016.Kerberos.Configuration.MultipleKerberosSections +version: 1.0 + +[ClickHouse] SHALL disable [Kerberos] and reject [Kerberos] authentication in case multiple `kerberos` sections are present in `config.xml`. + +#### RQ.SRS-016.Kerberos.Configuration.WrongUserRealm +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if user's realm specified in `users.xml` doesn't match the realm of the principal trying to authenticate. + +#### RQ.SRS-016.Kerberos.Configuration.PrincipalAndRealmSpecified +version: 1.0 + +[ClickHouse] SHALL generate an exception and disable [Kerberos] in case both `realm` and `principal` sections are defined in `config.xml`. + +#### RQ.SRS-016.Kerberos.Configuration.MultiplePrincipalSections +version: 1.0 + +[ClickHouse] SHALL generate an exception and disable [Kerberos] in case multiple `principal` sections are specified inside `kerberos` section in `config.xml`. + +#### RQ.SRS-016.Kerberos.Configuration.MultipleRealmSections +version: 1.0 + +[ClickHouse] SHALL generate an exception and disable [Kerberos] in case multiple `realm` sections are specified inside `kerberos` section in `config.xml`. + +### Valid User + +#### RQ.SRS-016.Kerberos.ValidUser.XMLConfiguredUser +version: 1.0 + +[ClickHouse] SHALL accept [Kerberos] authentication for a user that is configured in `users.xml` and has [Kerberos] enabled, i.e.: + +```xml + + + + + + + + EXAMPLE.COM + + + + +``` + +#### RQ.SRS-016.Kerberos.ValidUser.RBACConfiguredUser +version: 1.0 + +[ClickHouse] SHALL accept [Kerberos] authentication if user is configured to authenticate via [Kerberos] using SQL queries + +```sql +CREATE USER my_user IDENTIFIED WITH kerberos REALM 'EXAMPLE.COM' +``` + +or + +```sql +CREATE USER my_user IDENTIFIED WITH kerberos +``` + +#### RQ.SRS-016.Kerberos.ValidUser.KerberosNotConfigured +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if username is valid but [ClickHouse] user is not configured to be authenticated using [Kerberos]. + +### Invalid User + +#### RQ.SRS-016.Kerberos.InvalidUser +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if name of the principal attempting to authenticate does not translate to a valid [ClickHouse] username configured in `users.xml` or via SQL workflow. + +#### RQ.SRS-016.Kerberos.InvalidUser.UserDeleted +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if [ClickHouse] user was removed from the database using an SQL query. + +### Kerberos Not Available + +#### RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidServerTicket +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if [ClickHouse] user is configured to be authenticated using [Kerberos] and [Kerberos] server is unavailable, but [ClickHouse] doesn't have a valid Kerberos ticket or the ticket is expired. + +#### RQ.SRS-016.Kerberos.KerberosNotAvailable.InvalidClientTicket +version: 1.0 + +[ClickHouse] SHALL reject [Kerberos] authentication if [ClickHouse] user is configured to to be authenticated using [Kerberos] and [Kerberos] server is unavailable, but the client doesn't have a valid Kerberos ticket or the ticket is expired. + +#### RQ.SRS-016.Kerberos.KerberosNotAvailable.ValidTickets +version: 1.0 + +[ClickHouse] SHALL accept [Kerberos] authentication if no [Kerberos] server is reachable, but [ClickHouse] is configured to use valid credentials and [ClickHouse] has already processed some valid kerberized request (so it was granted a ticket), and the client has a valid ticket as well. + +### Kerberos Restarted + +#### RQ.SRS-016.Kerberos.KerberosServerRestarted +version: 1.0 + +[ClickHouse] SHALL accept [Kerberos] authentication if [Kerberos] server was restarted. + +### Performance + +#### RQ.SRS-016.Kerberos.Performance +version: 1.0 + +[ClickHouse]'s performance for [Kerberos] authentication SHALL be comparable to regular authentication. + +### Parallel Requests processing + +#### RQ.SRS-016.Kerberos.Parallel +version: 1.0 + +[ClickHouse] SHALL support parallel authentication using [Kerberos]. + +#### RQ.SRS-016.Kerberos.Parallel.ValidRequests.KerberosAndNonKerberos +version: 1.0 + +[ClickHouse] SHALL support processing of simultaneous kerberized (for users configured to authenticate via [Kerberos]) and non-kerberized (for users configured to authenticate with any other means) requests. + +#### RQ.SRS-016.Kerberos.Parallel.ValidRequests.SameCredentials +version: 1.0 + +[ClickHouse] SHALL support processing of simultaneously sent [Kerberos] requests under the same credentials. + +#### RQ.SRS-016.Kerberos.Parallel.ValidRequests.DifferentCredentials +version: 1.0 + +[ClickHouse] SHALL support processing of simultaneously sent [Kerberos] requests under different credentials. + +#### RQ.SRS-016.Kerberos.Parallel.ValidInvalid +version: 1.0 + +[ClickHouse] SHALL support parallel authentication of users using [Kerberos] server, some of which are valid and some invalid. Valid users' authentication should not be affected by invalid users' attempts. + +#### RQ.SRS-016.Kerberos.Parallel.Deletion +version: 1.0 + +[ClickHouse] SHALL not crash when two or more [Kerberos] users are simultaneously deleting one another. + +## References + +* **ClickHouse:** https://clickhouse.tech +* **Gitlab Repository:** https://gitlab.com/altinity-qa/documents/qa-srs016-clickhouse-kerberos-authentication/-/blob/master/QA_SRS016_ClickHouse_Kerberos_Authentication.md +* **Revision History:** https://gitlab.com/altinity-qa/documents/qa-srs016-clickhouse-kerberos-authentication/-/commits/master/QA_SRS016_ClickHouse_Kerberos_Authentication.md +* **Git:** https://git-scm.com/ +* **Kerberos terminology:** https://web.mit.edu/kerberos/kfw-4.1/kfw-4.1/kfw-4.1-help/html/kerberos_terminology.htm + +[Kerberos]: https://en.wikipedia.org/wiki/Kerberos_(protocol) +[SPNEGO]: https://en.wikipedia.org/wiki/SPNEGO +[ClickHouse]: https://clickhouse.tech +[GitLab]: https://gitlab.com +[GitLab Repository]: https://gitlab.com/altinity-qa/documents/qa-srs016-clickhouse-kerberos-authentication/-/blob/master/QA_SRS016_ClickHouse_Kerberos_Authentication.md +[Revision History]: https://gitlab.com/altinity-qa/documents/qa-srs016-clickhouse-kerberos-authentication/-/commits/master/QA_SRS016_ClickHouse_Kerberos_Authentication.md +[Git]: https://git-scm.com/ +[Kerberos terminology]: https://web.mit.edu/kerberos/kfw-4.1/kfw-4.1/kfw-4.1-help/html/kerberos_terminology.htm +''') diff --git a/tests/testflows/kerberos/tests/common.py b/tests/testflows/kerberos/tests/common.py new file mode 100644 index 00000000000..e768a78cad5 --- /dev/null +++ b/tests/testflows/kerberos/tests/common.py @@ -0,0 +1,225 @@ +from testflows.core import * +from testflows.asserts import error +from contextlib import contextmanager +import xml.etree.ElementTree as xmltree + +import time +import uuid + + +def getuid(): + return str(uuid.uuid1()).replace('-', '_') + + +def xml_append(root, tag, text=Null): + element = xmltree.Element(tag) + if text: + element.text = text + root.append(element) + + +def xml_write(data, filename): + strdata = xmltree.tostring(data) + with open(filename, "wb") as f: + f.write(strdata) + + +def xml_parse_file(filename): + return xmltree.parse(filename).getroot() + + +def create_default_config(filename): + contents = "" + if "kerberos_users.xml" in filename: + contents = "EXAMPLE.COM" \ + "" + elif "kerberos.xml" in filename: + contents = "EXAMPLE.COM" + + with open(filename, "w") as f: + f.write(contents) + + +def test_select_query(node, krb_auth=True, req="SELECT currentUser()"): + """ Helper forming a HTTP query to ClickHouse server + """ + if krb_auth: + return f"echo '{req}' | curl --negotiate -u : 'http://{node.name}:8123/' --data-binary @-" + else: + return f"echo '{req}' | curl 'http://{node.name}:8123/' --data-binary @-" + + +@TestStep(Given) +def kinit_no_keytab(self, node, principal="kerberos_user", lifetime_option="-l 10:00"): + """ Helper for obtaining Kerberos ticket for client + """ + try: + node.cmd("echo pwd | kinit admin/admin") + node.cmd(f"kadmin -w pwd -q \"add_principal -pw pwd {principal}\"") + node.cmd(f"echo pwd | kinit {lifetime_option} {principal}") + yield + finally: + node.cmd("kdestroy") + + +@TestStep(Given) +def create_server_principal(self, node): + """ Helper for obtaining Kerberos ticket for server + """ + try: + node.cmd("echo pwd | kinit admin/admin") + node.cmd(f"kadmin -w pwd -q \"add_principal -randkey HTTP/docker-compose_{node.name}_1.docker-compose_default\"") + node.cmd(f"kadmin -w pwd -q \"ktadd -k /etc/krb5.keytab HTTP/docker-compose_{node.name}_1.docker-compose_default\"") + yield + finally: + node.cmd("kdestroy") + node.cmd("rm /etc/krb5.keytab") + + +@TestStep(Given) +def save_file_state(self, node, filename): + """ Save current file and then restore it, restarting the node + """ + try: + with When("I save file state"): + with open(filename, 'r') as f: + a = f.read() + yield + finally: + with Finally("I restore initial state"): + with open(filename, 'w') as f: + f.write(a) + node.restart() + + +@TestStep(Given) +def temp_erase(self, node, filename=None): + """ Temporary erasing config file and restarting the node + """ + if filename is None: + filename = f"kerberos/configs/{node.name}/config.d/kerberos.xml" + with When("I save file state"): + with open(filename, 'r') as f: + a = f.read() + try: + with Then("I overwrite file to be dummy"): + with open(filename, 'w') as f: + f.write("\n") + node.restart() + yield + finally: + with Finally("I restore initial file state"): + with open(filename, 'w') as f: + f.write(a) + node.restart() + + +def restart(node, config_path, safe=False, timeout=60): + """Restart ClickHouse server and wait for config to be reloaded. + """ + + filename = '/etc/clickhouse-server/config.xml' if 'config.d' in config_path else '/etc/clickhouse-server/users.xml' + with When("I restart ClickHouse server node"): + with node.cluster.shell(node.name) as bash: + bash.expect(bash.prompt) + + with By("closing terminal to the node to be restarted"): + bash.close() + + with And("getting current log size"): + logsize = \ + node.command("stat --format=%s /var/log/clickhouse-server/clickhouse-server.log").output.split(" ")[0].strip() + + with And("restarting ClickHouse server"): + node.restart(safe=safe) + + with Then("tailing the log file from using previous log size as the offset"): + bash.prompt = bash.__class__.prompt + bash.open() + bash.send(f"tail -c +{logsize} -f /var/log/clickhouse-server/clickhouse-server.log") + + with And("waiting for config reload message in the log file"): + bash.expect( + f"ConfigReloader: Loaded config '{filename}', performed update on configuration", + timeout=timeout) + + +@TestStep +def check_wrong_config(self, node, client, config_path, modify_file, log_error="", output="", + tail=120, timeout=60, healthy_on_restart=True): + """Check that ClickHouse errors when trying to load invalid configuration file. + """ + preprocessed_name = "config.xml" if "config.d" in config_path else "users.xml" + + full_config_path = "/etc/clickhouse-server/config.d/kerberos.xml" if "config.d" in config_path else "/etc/clickhouse-server/users.d/kerberos-users.xml" + + uid = getuid() + + try: + with Given("I save config file to restore it later"): + with open(config_path, 'r') as f: + initial_contents = f.read() + + with And("I prepare the error log by writing empty lines into it"): + node.command("echo -e \"%s\" > /var/log/clickhouse-server/clickhouse-server.err.log" % ("-\\n" * tail)) + + with When("I modify xml file"): + root = xml_parse_file(config_path) + root = modify_file(root) + root.append(xmltree.fromstring(f"{uid}")) + config_contents = xmltree.tostring(root, encoding='utf8', method='xml').decode('utf-8') + command = f"cat < {full_config_path}\n{config_contents}\nHEREDOC" + node.command(command, steps=False, exitcode=0) + # time.sleep(1) + + with Then(f"{preprocessed_name} should be updated", description=f"timeout {timeout}"): + started = time.time() + command = f"cat /var/lib/clickhouse/preprocessed_configs/{preprocessed_name} | grep {uid} > /dev/null" + while time.time() - started < timeout: + exitcode = node.command(command, steps=False).exitcode + if exitcode == 0: + break + time.sleep(1) + assert exitcode == 0, error() + + with When("I restart ClickHouse to apply the config changes"): + if output: + node.restart(safe=False, wait_healthy=True) + else: + node.restart(safe=False, wait_healthy=False) + + if output != "": + with Then(f"check {output} is in output"): + time.sleep(5) + started = time.time() + while time.time() - started < timeout: + kinit_no_keytab(node=client) + create_server_principal(node=node) + r = client.cmd(test_select_query(node=node), no_checks=True) + if output in r.output: + assert True, error() + break + time.sleep(1) + else: + assert False, error() + + finally: + with Finally("I restore original config"): + with By("restoring the (correct) config file"): + with open(config_path, 'w') as f: + f.write(initial_contents) + with And("restarting the node"): + node.restart(safe=False) + + if log_error != "": + with Then("error log should contain the expected error message"): + started = time.time() + command = f"tail -n {tail} /var/log/clickhouse-server/clickhouse-server.err.log | grep \"{log_error}\"" + while time.time() - started < timeout: + exitcode = node.command(command, steps=False).exitcode + if exitcode == 0: + break + time.sleep(1) + assert exitcode == 0, error() + + diff --git a/tests/testflows/kerberos/tests/config.py b/tests/testflows/kerberos/tests/config.py new file mode 100644 index 00000000000..3f4bf15deb5 --- /dev/null +++ b/tests/testflows/kerberos/tests/config.py @@ -0,0 +1,163 @@ +from testflows.core import * +from kerberos.tests.common import * +from kerberos.requirements.requirements import * + +import time +import datetime +import itertools + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Configuration_KerberosNotEnabled("1.0") +) +def kerberos_not_enabled(self): + """ClickHouse SHALL reject Kerberos authentication if user is properly configured for Kerberos, + but Kerberos itself is not enabled in config.xml. + """ + ch_nodes = self.context.ch_nodes + config_path = f"kerberos/configs/{ch_nodes[0].name}/config.d/kerberos.xml" + + def modify_file(root): + return xmltree.fromstring("") + + check_wrong_config(node=ch_nodes[0], client=ch_nodes[2], config_path=config_path, modify_file=modify_file, + output="Kerberos is not enabled") + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Configuration_MultipleKerberosSections("1.0") +) +def multiple_kerberos(self): + """ClickHouse SHALL disable Kerberos authentication if more than one kerberos sections specified in config.xml. + """ + ch_nodes = self.context.ch_nodes + config_path = f"kerberos/configs/{ch_nodes[0].name}/config.d/kerberos.xml" + + def modify_file(root): + second_section = "EXAM.COM" + root.append(xmltree.fromstring(second_section)) + return root + + check_wrong_config(node=ch_nodes[0], client=ch_nodes[2], config_path=config_path, modify_file=modify_file, + log_error="Multiple kerberos sections are not allowed", healthy_on_restart=False) + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Configuration_WrongUserRealm("1.0") +) +def wrong_user_realm(self): + """ClickHouse SHALL reject Kerberos authentication if user's realm specified in users.xml + doesn't match the realm of the principal trying to authenticate. + """ + + ch_nodes = self.context.ch_nodes + config_path = f"kerberos/configs/{ch_nodes[0].name}/users.d/kerberos-users.xml" + + def modify_file(root): + krb = root.find('users').find('kerberos_user') + krb.find('kerberos').find('realm').text = "OTHER.COM" + return root + + check_wrong_config(node=ch_nodes[0], client=ch_nodes[2], config_path=config_path, modify_file=modify_file, + output="Authentication failed") + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Configuration_MultipleAuthMethods("1.0") +) +def multiple_auth_methods(self): + """ClickHouse SHALL reject Kerberos authentication if other + auth method is specified for user alongside with Kerberos. + """ + ch_nodes = self.context.ch_nodes + config_path = f"kerberos/configs/{ch_nodes[0].name}/users.d/kerberos-users.xml" + + def modify_file(root): + krb = root.find('users').find('kerberos_user') + xml_append(krb, 'password', 'qwerty') + return root + + check_wrong_config(node=ch_nodes[0], client=ch_nodes[2], config_path=config_path, modify_file=modify_file, + log_error="More than one field of", healthy_on_restart=False) + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Configuration_PrincipalAndRealmSpecified("1.0") +) +def principal_and_realm_specified(self): + """ClickHouse SHALL drop an exception if both realm and principal fields are specified in config.xml. + """ + ch_nodes = self.context.ch_nodes + config_path = f"kerberos/configs/{ch_nodes[0].name}/config.d/kerberos.xml" + + def modify_file(root): + krb = root.find('kerberos') + xml_append(krb, 'principal', 'HTTP/srv1@EXAMPLE.COM') + return root + + check_wrong_config(node=ch_nodes[0], client=ch_nodes[2], config_path=config_path, modify_file=modify_file, + log_error="Realm and principal name cannot be specified simultaneously", + output="Kerberos is not enabled") + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Configuration_MultipleRealmSections("1.0") +) +def multiple_realm(self): + """ClickHouse SHALL throw an exception and disable Kerberos if more than one realm is specified in config.xml. + """ + ch_nodes = self.context.ch_nodes + config_path = f"kerberos/configs/{ch_nodes[0].name}/config.d/kerberos.xml" + + def modify_file(root): + krb = root.find('kerberos') + xml_append(krb, 'realm', 'EXAM.COM') + return root + + check_wrong_config(node=ch_nodes[0], client=ch_nodes[2], config_path=config_path, modify_file=modify_file, + log_error="Multiple realm sections are not allowed") + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Configuration_MultiplePrincipalSections("1.0") +) +def multiple_principal(self): + """ClickHouse SHALL throw an exception and disable Kerberos if more than one principal is specified in config.xml. + """ + ch_nodes = self.context.ch_nodes + config_path = f"kerberos/configs/{ch_nodes[0].name}/config.d/kerberos.xml" + + def modify_file(root): + krb = root.find('kerberos') + krb.remove(krb.find('realm')) + xml_append(krb, 'principal', 'HTTP/s1@EXAMPLE.COM') + xml_append(krb, 'principal', 'HTTP/s2@EXAMPLE.COM') + return root + + check_wrong_config(node=ch_nodes[0], client=ch_nodes[2], config_path=config_path, modify_file=modify_file, + log_error="Multiple principal sections are not allowed") + + + + + + + +@TestFeature +def config(self): + """Perform ClickHouse Kerberos authentication testing for incorrect configuration files + """ + + self.context.ch_nodes = [self.context.cluster.node(f"clickhouse{i}") for i in range(1, 4)] + self.context.krb_server = self.context.cluster.node("kerberos") + self.context.clients = [self.context.cluster.node(f"krb-client{i}") for i in range(1, 6)] + + for scenario in loads(current_module(), Scenario, Suite): + Scenario(run=scenario, flags=TE) diff --git a/tests/testflows/kerberos/tests/generic.py b/tests/testflows/kerberos/tests/generic.py new file mode 100644 index 00000000000..3276fd5ec5f --- /dev/null +++ b/tests/testflows/kerberos/tests/generic.py @@ -0,0 +1,332 @@ +from testflows.core import * +from kerberos.tests.common import * +from kerberos.requirements.requirements import * + +import time +import datetime +import itertools + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_ValidUser_XMLConfiguredUser("1.0") +) +def xml_configured_user(self): + """ClickHouse SHALL accept Kerberos authentication for valid XML-configured user + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for client"): + kinit_no_keytab(node=ch_nodes[2]) + + with And("kinit for server"): + create_server_principal(node=ch_nodes[0]) + + with When("I attempt to authenticate"): + r = ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])) + + with Then(f"I expect 'kerberos_user'"): + assert r.output == "kerberos_user", error() + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_ValidUser_RBACConfiguredUser("1.0") +) +def rbac_configured_user(self): + """ClickHouse SHALL accept Kerberos authentication for valid RBAC-configured user + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for client"): + kinit_no_keytab(node=ch_nodes[2], principal="krb_rbac") + + with And("kinit for server"): + create_server_principal(node=ch_nodes[0]) + + with When("I create a RBAC user"): + ch_nodes[0].query("CREATE USER krb_rbac IDENTIFIED WITH kerberos REALM 'EXAMPLE.COM'") + + with When("I attempt to authenticate"): + r = ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])) + + with Then("I restore server original state"): + ch_nodes[0].query("DROP USER krb_rbac") + + with Finally("I expect 'krb_rbac'"): + assert r.output == "krb_rbac", error() + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_KerberosNotAvailable_InvalidServerTicket("1.0") +) +def invalid_server_ticket(self): + """ClickHouse SHALL reject Kerberos authentication no Kerberos server is reachable + and CH-server has no valid ticket (or the existing ticket is outdated). + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for client"): + kinit_no_keytab(node=ch_nodes[2]) + + with And("setting up server principal"): + create_server_principal(node=ch_nodes[0]) + + with And("I kill kerberos-server"): + self.context.krb_server.stop() + + with When("I attempt to authenticate as kerberos_user"): + r = ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])) + + with Then("I start kerberos server again"): + self.context.krb_server.start() + ch_nodes[2].cmd("kdestroy") + while True: + kinit_no_keytab(node=ch_nodes[2]) + if ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])).output == "kerberos_user": + break + ch_nodes[2].cmd("kdestroy") + + with And("I expect the user to be default"): + assert r.output == "default", error() + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_KerberosNotAvailable_InvalidClientTicket("1.0") +) +def invalid_client_ticket(self): + """ClickHouse SHALL reject Kerberos authentication no Kerberos server is reachable + and client has no valid ticket (or the existing ticket is outdated). + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for client"): + kinit_no_keytab(node=ch_nodes[2], lifetime_option="-l 00:00:05") + + with And("setting up server principal"): + create_server_principal(node=ch_nodes[0]) + + with And("I kill kerberos-server"): + self.context.krb_server.stop() + + with And("I wait until client ticket is expired"): + time.sleep(10) + + with When("I attempt to authenticate as kerberos_user"): + r = ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])) + + with Then("I expect the user to be default"): + assert r.output == "default", error() + + with Finally("I start kerberos server again"): + self.context.krb_server.start() + ch_nodes[2].cmd("kdestroy") + while True: + kinit_no_keytab(node=ch_nodes[2]) + if ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])).output == "kerberos_user": + break + ch_nodes[2].cmd("kdestroy") + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_KerberosNotAvailable_ValidTickets("1.0") +) +def kerberos_unreachable_valid_tickets(self): + """ClickHouse SHALL accept Kerberos authentication if no Kerberos server is reachable + but both CH-server and client have valid tickets. + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for client"): + kinit_no_keytab(node=ch_nodes[2]) + + with And("setting up server principal"): + create_server_principal(node=ch_nodes[0]) + + with And("make sure server obtained ticket"): + ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])) + + with And("I kill kerberos-server"): + self.context.krb_server.stop() + + with When("I attempt to authenticate as kerberos_user"): + r = ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])) + + with Then("I expect the user to be default"): + assert r.output == "kerberos_user", error() + + with Finally("I start kerberos server again"): + self.context.krb_server.start() + ch_nodes[2].cmd("kdestroy") + while True: + kinit_no_keytab(node=ch_nodes[2]) + if ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])).output == "kerberos_user": + break + ch_nodes[2].cmd("kdestroy") + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_ValidUser_KerberosNotConfigured("1.0") +) +def kerberos_not_configured(self): + """ClickHouse SHALL reject Kerberos authentication if user is not a kerberos-auth user. + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for client"): + kinit_no_keytab(node=ch_nodes[2], principal="unkerberized") + + with And('Kinit for server'): + create_server_principal(node=ch_nodes[0]) + + with By("I add non-Kerberos user to ClickHouse"): + ch_nodes[0].query("CREATE USER unkerberized IDENTIFIED WITH plaintext_password BY 'qwerty'") + + with When("I attempt to authenticate"): + r = ch_nodes[2].cmd(test_select_query(node=ch_nodes[0]), no_checks=True) + + with Then("I expect authentication failure"): + assert "Authentication failed" in r.output, error() + + with Finally("I drop the user"): + ch_nodes[0].query("DROP USER unkerberized") + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_KerberosServerRestarted("1.0") +) +def kerberos_server_restarted(self): + """ClickHouse SHALL accept Kerberos authentication if Kerberos server was restarted. + """ + ch_nodes = self.context.ch_nodes + krb_server = self.context.krb_server + + with Given("I obtain keytab for user"): + kinit_no_keytab(node=ch_nodes[2]) + with And("I create server principal"): + create_server_principal(node=ch_nodes[0]) + with And("I obtain server ticket"): + ch_nodes[2].cmd(test_select_query(node=ch_nodes[0]), no_checks=True) + with By("I dump, restart and restore kerberos server"): + krb_server.cmd("kdb5_util dump dump.dmp", shell_command="/bin/sh") + krb_server.restart() + krb_server.cmd("kdb5_util load dump.dmp", shell_command="/bin/sh") + + with When("I attempt to authenticate"): + r = ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])) + + with And("I wait for kerberos to be healthy"): + ch_nodes[2].cmd("kdestroy") + while True: + kinit_no_keytab(node=ch_nodes[2]) + if ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])).output == "kerberos_user": + break + + with Then(f"I expect kerberos_user"): + assert r.output == "kerberos_user", error() + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_InvalidUser("1.0") +) +def invalid_user(self): + """ClickHouse SHALL reject Kerberos authentication for invalid principal + """ + ch_nodes = self.context.ch_nodes + + with Given("I obtain keytab for invalid user"): + kinit_no_keytab(node=ch_nodes[2], principal="invalid") + + with And("I create server principal"): + create_server_principal(node=ch_nodes[0]) + + with When("I attempt to authenticate"): + r = ch_nodes[2].cmd(test_select_query(node=ch_nodes[0]), no_checks=True) + + with Then(f"I expect default"): + assert "Authentication failed: password is incorrect or there is no user with such name" in r.output, error() + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_InvalidUser_UserDeleted("1.0") +) +def user_deleted(self): + """ClickHouse SHALL reject Kerberos authentication if Kerberos user was deleted prior to query. + """ + ch_nodes = self.context.ch_nodes + + with Given("I obtain keytab for a user"): + kinit_no_keytab(node=ch_nodes[2], principal="krb_rbac") + + with And("I create server principal"): + create_server_principal(node=ch_nodes[0]) + + with And("I create and then delete kerberized user"): + ch_nodes[0].query("CREATE USER krb_rbac IDENTIFIED WITH kerberos REALM 'EXAMPLE.COM'") + ch_nodes[0].query("DROP USER krb_rbac") + + with When("I attempt to authenticate"): + r = ch_nodes[2].cmd(test_select_query(node=ch_nodes[0]), no_checks=True) + + with Then(f"I expect error"): + assert "Authentication failed: password is incorrect or there is no user with such name" in r.output, error() + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Performance("1.0") +) +def authentication_performance(self): + """ClickHouse's performance for Kerberos authentication SHALL shall be comparable to regular authentication. + """ + ch_nodes = self.context.ch_nodes + + with Given("I obtain keytab for a user"): + kinit_no_keytab(node=ch_nodes[2]) + + with And("I create server principal"): + create_server_principal(node=ch_nodes[0]) + + with And("I create a password-identified user"): + ch_nodes[0].query("CREATE USER pwd_user IDENTIFIED WITH plaintext_password BY 'pwd'") + + with When("I measure kerberos auth time"): + start_time_krb = time.time() + for i in range(100): + ch_nodes[2].cmd(test_select_query(node=ch_nodes[0])) + krb_time = (time.time() - start_time_krb) / 100 + + with And("I measure password auth time"): + start_time_usual = time.time() + for i in range(100): + ch_nodes[2].cmd(f"echo 'SELECT 1' | curl 'http://pwd_user:pwd@clickhouse1:8123/' -d @-") + usual_time = (time.time() - start_time_usual) / 100 + + with Then("measuring the performance compared to password auth"): + metric("percentage_improvement", units="%", value=100*(krb_time - usual_time)/usual_time) + + with Finally("I drop pwd_user"): + ch_nodes[0].query("DROP USER pwd_user") + + + + + +@TestFeature +def generic(self): + """Perform ClickHouse Kerberos authentication testing + """ + + self.context.ch_nodes = [self.context.cluster.node(f"clickhouse{i}") for i in range(1, 4)] + self.context.krb_server = self.context.cluster.node("kerberos") + self.context.clients = [self.context.cluster.node(f"krb-client{i}") for i in range(1, 6)] + + for scenario in loads(current_module(), Scenario, Suite): + Scenario(run=scenario, flags=TE) diff --git a/tests/testflows/kerberos/tests/parallel.py b/tests/testflows/kerberos/tests/parallel.py new file mode 100644 index 00000000000..694245e524c --- /dev/null +++ b/tests/testflows/kerberos/tests/parallel.py @@ -0,0 +1,204 @@ +from testflows.core import * +from kerberos.tests.common import * +from kerberos.requirements.requirements import * +from multiprocessing.dummy import Pool + +import time +import datetime +import itertools + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Parallel_ValidRequests_SameCredentials("1.0") +) +def valid_requests_same_credentials(self): + """ClickHouse should be able to process parallel requests sent under the same credentials. + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for clients"): + kinit_no_keytab(node=ch_nodes[1]) + kinit_no_keytab(node=ch_nodes[2]) + + with And('create server principal'): + create_server_principal(node=ch_nodes[0]) + + def helper(cmd): + return cmd(test_select_query(node=ch_nodes[0])) + + for i in range(15): + pool = Pool(2) + tasks = [] + with When("I try simultaneous authentication"): + tasks.append(pool.apply_async(helper, (ch_nodes[1].cmd, ))) + tasks.append(pool.apply_async(helper, (ch_nodes[2].cmd, ))) + tasks[0].wait(timeout=200) + tasks[1].wait(timeout=200) + + with Then(f"I expect requests to success"): + assert tasks[0].get(timeout=300).output == "kerberos_user", error() + assert tasks[1].get(timeout=300).output == "kerberos_user", error() + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Parallel_ValidRequests_DifferentCredentials("1.0") +) +def valid_requests_different_credentials(self): + """ClickHouse should be able to process parallel requests by different users. + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for clients"): + kinit_no_keytab(node=ch_nodes[1], principal="krb1") + kinit_no_keytab(node=ch_nodes[2], principal="krb2") + + with And("create server principal"): + create_server_principal(node=ch_nodes[0]) + + def helper(cmd): + return cmd(test_select_query(node=ch_nodes[0])) + + for i in range(15): + pool = Pool(2) + tasks = [] + + with And("add 2 kerberos users via RBAC"): + ch_nodes[0].query("CREATE USER krb1 IDENTIFIED WITH kerberos REALM 'EXAMPLE.COM'") + ch_nodes[0].query("CREATE USER krb2 IDENTIFIED WITH kerberos REALM 'EXAMPLE.COM'") + + with When("I try simultaneous authentication for valid and invalid"): + tasks.append(pool.apply_async(helper, (ch_nodes[1].cmd, ))) + tasks.append(pool.apply_async(helper, (ch_nodes[2].cmd, ))) + tasks[0].wait(timeout=200) + tasks[1].wait(timeout=200) + + with Then(f"I expect have auth failure"): + assert tasks[1].get(timeout=300).output == "krb2", error() + assert tasks[0].get(timeout=300).output == "krb1", error() + + with Finally("I make sure both users are removed"): + ch_nodes[0].query("DROP USER krb1", no_checks=True) + ch_nodes[0].query("DROP USER krb2", no_checks=True) + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Parallel_ValidInvalid("1.0") +) +def valid_invalid(self): + """Valid users' Kerberos authentication should not be affected by invalid users' attempts. + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for clients"): + kinit_no_keytab(node=ch_nodes[2]) + kinit_no_keytab(node=ch_nodes[1], principal="invalid_user") + + with And('create server principal'): + create_server_principal(node=ch_nodes[0]) + + def helper(cmd): + return cmd(test_select_query(node=ch_nodes[0]), no_checks=True) + + for i in range(15): + pool = Pool(2) + tasks = [] + with When("I try simultaneous authentication for valid and invalid"): + tasks.append(pool.apply_async(helper, (ch_nodes[1].cmd, ))) # invalid + tasks.append(pool.apply_async(helper, (ch_nodes[2].cmd, ))) # valid + + with Then(f"I expect have auth failure"): + assert tasks[1].get(timeout=300).output == "kerberos_user", error() + assert tasks[0].get(timeout=300).output != "kerberos_user", error() + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Parallel_Deletion("1.0") +) +def deletion(self): + """ClickHouse SHALL NOT crash when 2 Kerberos users are simultaneously deleting one another. + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for clients"): + kinit_no_keytab(node=ch_nodes[1], principal="krb1") + kinit_no_keytab(node=ch_nodes[2], principal="krb2") + + with And("create server principal"): + create_server_principal(node=ch_nodes[0]) + + def helper(cmd, todel): + return cmd(test_select_query(node=ch_nodes[0], req=f"DROP USER {todel}"), no_checks=True) + + for i in range(15): + pool = Pool(2) + tasks = [] + + with And("add 2 kerberos users via RBAC"): + ch_nodes[0].query("CREATE USER krb1 IDENTIFIED WITH kerberos REALM 'EXAMPLE.COM'") + ch_nodes[0].query("CREATE USER krb2 IDENTIFIED WITH kerberos REALM 'EXAMPLE.COM'") + ch_nodes[0].query("GRANT ACCESS MANAGEMENT ON *.* TO krb1") + ch_nodes[0].query("GRANT ACCESS MANAGEMENT ON *.* TO krb2") + + + with When("I try simultaneous authentication for valid and invalid"): + tasks.append(pool.apply_async(helper, (ch_nodes[1].cmd, "krb2"))) + tasks.append(pool.apply_async(helper, (ch_nodes[2].cmd, "krb1"))) + tasks[0].wait(timeout=200) + tasks[1].wait(timeout=200) + + with Then(f"I check CH is alive"): + assert ch_nodes[0].query("SELECT 1").output == "1", error() + + with Finally("I make sure both users are removed"): + ch_nodes[0].query("DROP USER krb1", no_checks=True) + ch_nodes[0].query("DROP USER krb2", no_checks=True) + + +@TestScenario +@Requirements( + RQ_SRS_016_Kerberos_Parallel_ValidRequests_KerberosAndNonKerberos("1.0") +) +def kerberos_and_nonkerberos(self): + """ClickHouse SHALL support processing of simultaneous kerberized and non-kerberized requests. + """ + ch_nodes = self.context.ch_nodes + + with Given("kinit for clients"): + kinit_no_keytab(node=ch_nodes[2]) + + with And('create server principal'): + create_server_principal(node=ch_nodes[0]) + + def helper(cmd, krb_auth): + return cmd(test_select_query(node=ch_nodes[0], krb_auth=krb_auth), no_checks=True) + + for i in range(15): + pool = Pool(2) + tasks = [] + with When("I try simultaneous authentication for valid and invalid"): + tasks.append(pool.apply_async(helper, (ch_nodes[1].cmd, False))) # non-kerberos + tasks.append(pool.apply_async(helper, (ch_nodes[2].cmd, True))) # kerberos + + with Then(f"I expect have auth failure"): + assert tasks[1].get(timeout=300).output == "kerberos_user", error() + assert tasks[0].get(timeout=300).output == "default", error() + + +@TestFeature +@Requirements( + RQ_SRS_016_Kerberos_Parallel("1.0") +) +def parallel(self): + """Perform ClickHouse Kerberos authentication testing for incorrect configuration files + """ + + self.context.ch_nodes = [self.context.cluster.node(f"clickhouse{i}") for i in range(1, 4)] + self.context.krb_server = self.context.cluster.node("kerberos") + self.context.clients = [self.context.cluster.node(f"krb-client{i}") for i in range(1, 6)] + + for scenario in loads(current_module(), Scenario, Suite): + Scenario(run=scenario, flags=TE) diff --git a/tests/testflows/ldap/authentication/configs/clickhouse/config.xml b/tests/testflows/ldap/authentication/configs/clickhouse/config.xml index e28a0c8e255..3db8338b865 100644 --- a/tests/testflows/ldap/authentication/configs/clickhouse/config.xml +++ b/tests/testflows/ldap/authentication/configs/clickhouse/config.xml @@ -412,7 +412,7 @@ 86400 - 60 + 7200 diff --git a/tests/testflows/ldap/authentication/docker-compose/docker-compose.yml b/tests/testflows/ldap/authentication/docker-compose/docker-compose.yml index c8ff683df58..36e25ef766e 100644 --- a/tests/testflows/ldap/authentication/docker-compose/docker-compose.yml +++ b/tests/testflows/ldap/authentication/docker-compose/docker-compose.yml @@ -135,7 +135,7 @@ services: zookeeper: condition: service_healthy - # dummy service which does nothing, but allows to postpone + # dummy service which does nothing, but allows to postpone # 'docker-compose up -d' till all dependecies will go healthy all_services_ready: image: hello-world diff --git a/tests/testflows/ldap/authentication/docker-compose/openldap-service.yml b/tests/testflows/ldap/authentication/docker-compose/openldap-service.yml index 139907c513c..e489637b8c9 100644 --- a/tests/testflows/ldap/authentication/docker-compose/openldap-service.yml +++ b/tests/testflows/ldap/authentication/docker-compose/openldap-service.yml @@ -28,7 +28,7 @@ services: environment: PHPLDAPADMIN_HTTPS=false: ports: - - "8080:80" + - "8080:80" healthcheck: test: echo 1 interval: 10s @@ -37,4 +37,3 @@ services: start_period: 300s security_opt: - label:disable - diff --git a/tests/testflows/ldap/authentication/docker-compose/zookeeper-service.yml b/tests/testflows/ldap/authentication/docker-compose/zookeeper-service.yml index 6691a2df31c..ca732a48dbd 100644 --- a/tests/testflows/ldap/authentication/docker-compose/zookeeper-service.yml +++ b/tests/testflows/ldap/authentication/docker-compose/zookeeper-service.yml @@ -2,7 +2,7 @@ version: '2.3' services: zookeeper: - image: zookeeper:3.4.12 + image: zookeeper:3.6.2 expose: - "2181" environment: diff --git a/tests/testflows/ldap/authentication/requirements/requirements.md b/tests/testflows/ldap/authentication/requirements/requirements.md index 27ce8c921a0..e27a0ca14f7 100644 --- a/tests/testflows/ldap/authentication/requirements/requirements.md +++ b/tests/testflows/ldap/authentication/requirements/requirements.md @@ -468,7 +468,7 @@ version: 1.0 the following RBAC command ```sql -CREATE USER name IDENTIFIED WITH ldap_server BY 'server_name' +CREATE USER name IDENTIFIED WITH ldap SERVER 'server_name' ``` #### RQ.SRS-007.LDAP.Configuration.User.Syntax diff --git a/tests/testflows/ldap/authentication/requirements/requirements.py b/tests/testflows/ldap/authentication/requirements/requirements.py index 25b943d18c2..2437711dd22 100644 --- a/tests/testflows/ldap/authentication/requirements/requirements.py +++ b/tests/testflows/ldap/authentication/requirements/requirements.py @@ -903,7 +903,7 @@ RQ_SRS_007_LDAP_Configuration_User_RBAC = Requirement( 'the following RBAC command\n' '\n' '```sql\n' - "CREATE USER name IDENTIFIED WITH ldap_server BY 'server_name'\n" + "CREATE USER name IDENTIFIED WITH ldap SERVER 'server_name'\n" '```\n' '\n' ), @@ -1841,7 +1841,7 @@ version: 1.0 the following RBAC command ```sql -CREATE USER name IDENTIFIED WITH ldap_server BY 'server_name' +CREATE USER name IDENTIFIED WITH ldap SERVER 'server_name' ``` #### RQ.SRS-007.LDAP.Configuration.User.Syntax diff --git a/tests/testflows/ldap/authentication/tests/authentications.py b/tests/testflows/ldap/authentication/tests/authentications.py index b54cc880bbc..909cc61cdbb 100644 --- a/tests/testflows/ldap/authentication/tests/authentications.py +++ b/tests/testflows/ldap/authentication/tests/authentications.py @@ -747,10 +747,7 @@ def verification_cooldown_performance(self, server, rbac=False, iterations=5000) no_vcd_time = repeat_requests(server=server, iterations=iterations, vcd_value="0", rbac=rbac) metric("login_with_vcd_value_0", units="seconds", value=no_vcd_time) - with Then("The performance with verification cooldown parameter set is better than the performance with no verification cooldown parameter."): - assert no_vcd_time > vcd_time, error() - - with And("Log the performance improvement as a percentage."): + with Then("Log the performance improvement as a percentage"): metric("percentage_improvement", units="%", value=100*(no_vcd_time - vcd_time)/vcd_time) @TestOutline diff --git a/tests/testflows/ldap/authentication/tests/common.py b/tests/testflows/ldap/authentication/tests/common.py index 7f9f16e827c..6b6ce0413a4 100644 --- a/tests/testflows/ldap/authentication/tests/common.py +++ b/tests/testflows/ldap/authentication/tests/common.py @@ -248,7 +248,7 @@ def add_users_identified_with_ldap(*users): try: with Given("I create users"): for user in users: - node.query(f"CREATE USER '{user['username']}' IDENTIFIED WITH ldap_server BY '{user['server']}'") + node.query(f"CREATE USER '{user['username']}' IDENTIFIED WITH ldap SERVER '{user['server']}'") yield finally: with Finally("I remove users"): diff --git a/tests/testflows/ldap/external_user_directory/docker-compose/docker-compose.yml b/tests/testflows/ldap/external_user_directory/docker-compose/docker-compose.yml index c8ff683df58..36e25ef766e 100644 --- a/tests/testflows/ldap/external_user_directory/docker-compose/docker-compose.yml +++ b/tests/testflows/ldap/external_user_directory/docker-compose/docker-compose.yml @@ -135,7 +135,7 @@ services: zookeeper: condition: service_healthy - # dummy service which does nothing, but allows to postpone + # dummy service which does nothing, but allows to postpone # 'docker-compose up -d' till all dependecies will go healthy all_services_ready: image: hello-world diff --git a/tests/testflows/ldap/external_user_directory/docker-compose/openldap-service.yml b/tests/testflows/ldap/external_user_directory/docker-compose/openldap-service.yml index 139907c513c..e489637b8c9 100644 --- a/tests/testflows/ldap/external_user_directory/docker-compose/openldap-service.yml +++ b/tests/testflows/ldap/external_user_directory/docker-compose/openldap-service.yml @@ -28,7 +28,7 @@ services: environment: PHPLDAPADMIN_HTTPS=false: ports: - - "8080:80" + - "8080:80" healthcheck: test: echo 1 interval: 10s @@ -37,4 +37,3 @@ services: start_period: 300s security_opt: - label:disable - diff --git a/tests/testflows/ldap/external_user_directory/docker-compose/zookeeper-service.yml b/tests/testflows/ldap/external_user_directory/docker-compose/zookeeper-service.yml index 6691a2df31c..ca732a48dbd 100644 --- a/tests/testflows/ldap/external_user_directory/docker-compose/zookeeper-service.yml +++ b/tests/testflows/ldap/external_user_directory/docker-compose/zookeeper-service.yml @@ -2,7 +2,7 @@ version: '2.3' services: zookeeper: - image: zookeeper:3.4.12 + image: zookeeper:3.6.2 expose: - "2181" environment: diff --git a/tests/testflows/ldap/role_mapping/docker-compose/docker-compose.yml b/tests/testflows/ldap/role_mapping/docker-compose/docker-compose.yml index c8ff683df58..36e25ef766e 100644 --- a/tests/testflows/ldap/role_mapping/docker-compose/docker-compose.yml +++ b/tests/testflows/ldap/role_mapping/docker-compose/docker-compose.yml @@ -135,7 +135,7 @@ services: zookeeper: condition: service_healthy - # dummy service which does nothing, but allows to postpone + # dummy service which does nothing, but allows to postpone # 'docker-compose up -d' till all dependecies will go healthy all_services_ready: image: hello-world diff --git a/tests/testflows/ldap/role_mapping/docker-compose/openldap-service.yml b/tests/testflows/ldap/role_mapping/docker-compose/openldap-service.yml index 139907c513c..e489637b8c9 100644 --- a/tests/testflows/ldap/role_mapping/docker-compose/openldap-service.yml +++ b/tests/testflows/ldap/role_mapping/docker-compose/openldap-service.yml @@ -28,7 +28,7 @@ services: environment: PHPLDAPADMIN_HTTPS=false: ports: - - "8080:80" + - "8080:80" healthcheck: test: echo 1 interval: 10s @@ -37,4 +37,3 @@ services: start_period: 300s security_opt: - label:disable - diff --git a/tests/testflows/ldap/role_mapping/docker-compose/zookeeper-service.yml b/tests/testflows/ldap/role_mapping/docker-compose/zookeeper-service.yml index 6691a2df31c..ca732a48dbd 100644 --- a/tests/testflows/ldap/role_mapping/docker-compose/zookeeper-service.yml +++ b/tests/testflows/ldap/role_mapping/docker-compose/zookeeper-service.yml @@ -2,7 +2,7 @@ version: '2.3' services: zookeeper: - image: zookeeper:3.4.12 + image: zookeeper:3.6.2 expose: - "2181" environment: diff --git a/tests/testflows/rbac/configs/clickhouse/config.xml b/tests/testflows/rbac/configs/clickhouse/config.xml index 4ec12232539..265bcd1882a 100644 --- a/tests/testflows/rbac/configs/clickhouse/config.xml +++ b/tests/testflows/rbac/configs/clickhouse/config.xml @@ -418,7 +418,7 @@ 86400 - 60 + 7200 diff --git a/tests/testflows/rbac/docker-compose/clickhouse-service.yml b/tests/testflows/rbac/docker-compose/clickhouse-service.yml index d5f981ca8b7..2d79443dcbb 100755 --- a/tests/testflows/rbac/docker-compose/clickhouse-service.yml +++ b/tests/testflows/rbac/docker-compose/clickhouse-service.yml @@ -20,7 +20,7 @@ services: test: clickhouse client --query='select 1' interval: 10s timeout: 10s - retries: 10 + retries: 3 start_period: 300s cap_add: - SYS_PTRACE diff --git a/tests/testflows/rbac/docker-compose/docker-compose.yml b/tests/testflows/rbac/docker-compose/docker-compose.yml index a3f5144c9ed..29f2ef52470 100755 --- a/tests/testflows/rbac/docker-compose/docker-compose.yml +++ b/tests/testflows/rbac/docker-compose/docker-compose.yml @@ -57,4 +57,4 @@ services: clickhouse3: condition: service_healthy zookeeper: - condition: service_healthy \ No newline at end of file + condition: service_healthy diff --git a/tests/testflows/rbac/helper/common.py b/tests/testflows/rbac/helper/common.py index 47e38560714..c140e01f34f 100755 --- a/tests/testflows/rbac/helper/common.py +++ b/tests/testflows/rbac/helper/common.py @@ -2,6 +2,7 @@ import uuid from contextlib import contextmanager from multiprocessing.dummy import Pool +from multiprocessing import TimeoutError as PoolTaskTimeoutError from testflows.core.name import basename, parentname from testflows._core.testtype import TestSubType @@ -30,6 +31,9 @@ def instrument_clickhouse_server_log(self, node=None, clickhouse_server_log="/va yield finally: + if self.context.cluster.terminating is True: + return + with Finally("adding test name end message to the clickhouse-server.log", flags=TE): node.command(f"echo -e \"\\n-- end: {current().name} --\\n\" >> {clickhouse_server_log}") @@ -38,14 +42,20 @@ def instrument_clickhouse_server_log(self, node=None, clickhouse_server_log="/va with Then("dumping clickhouse-server.log for this test"): node.command(f"tail -c +{logsize} {clickhouse_server_log}") -def join(tasks): +def join(tasks, polling_timeout=5): """Join all parallel tests. """ exc = None while tasks: try: - tasks[0].get() - tasks.pop(0) + try: + tasks[0].get(timeout=polling_timeout) + tasks.pop(0) + + except PoolTaskTimeoutError as e: + task = tasks.pop(0) + tasks.append(task) + continue except KeyboardInterrupt as e: current().context.cluster.terminating = True @@ -133,6 +143,23 @@ def role(node, role): for role in roles: with Finally("I drop the role"): node.query(f"DROP ROLE IF EXISTS {role}") + +@TestStep(Given) +def row_policy(self, name, table, node=None): + """Create a row policy with a given name on a given table. + """ + if node is None: + node = self.context.node + + try: + with Given(f"I create row policy {name}"): + node.query(f"CREATE ROW POLICY {name} ON {table}") + yield + + finally: + with Finally(f"I delete row policy {name}"): + node.query(f"DROP ROW POLICY IF EXISTS {name} ON {table}") + tables = { "table0" : 1 << 0, "table1" : 1 << 1, diff --git a/tests/testflows/rbac/regression.py b/tests/testflows/rbac/regression.py index e89be3bab20..a07cb8da805 100755 --- a/tests/testflows/rbac/regression.py +++ b/tests/testflows/rbac/regression.py @@ -27,6 +27,8 @@ issue_17655 = "https://github.com/ClickHouse/ClickHouse/issues/17655" issue_17766 = "https://github.com/ClickHouse/ClickHouse/issues/17766" issue_18110 = "https://github.com/ClickHouse/ClickHouse/issues/18110" issue_18206 = "https://github.com/ClickHouse/ClickHouse/issues/18206" +issue_21083 = "https://github.com/ClickHouse/ClickHouse/issues/21083" +issue_21084 = "https://github.com/ClickHouse/ClickHouse/issues/21084" xfails = { "syntax/show create quota/I show create quota current": @@ -131,6 +133,10 @@ xfails = { [(Fail, issue_18206)], "privileges/system replication queues/:/:/:/:/SYSTEM:": [(Fail, issue_18206)], + "privileges/: row policy/nested live:": + [(Fail, issue_21083)], + "privileges/: row policy/nested mat:": + [(Fail, issue_21084)], } xflags = { @@ -160,9 +166,9 @@ def regression(self, local, clickhouse_binary_path, stress=None, parallel=None): if parallel is not None: self.context.parallel = parallel - Feature(run=load("rbac.tests.syntax.feature", "feature"), flags=TE) - Feature(run=load("rbac.tests.privileges.feature", "feature"), flags=TE) - Feature(run=load("rbac.tests.views.feature", "feature"), flags=TE) + Feature(run=load("rbac.tests.syntax.feature", "feature")) + Feature(run=load("rbac.tests.privileges.feature", "feature")) + Feature(run=load("rbac.tests.views.feature", "feature")) if main(): regression() diff --git a/tests/testflows/rbac/requirements/requirements.md b/tests/testflows/rbac/requirements/requirements.md index ae6a038c15e..163417e1617 100644 --- a/tests/testflows/rbac/requirements/requirements.md +++ b/tests/testflows/rbac/requirements/requirements.md @@ -9,556 +9,588 @@ * 5 [Requirements](#requirements) * 5.1 [Generic](#generic) * 5.1.1 [RQ.SRS-006.RBAC](#rqsrs-006rbac) - * 5.1.2 [Login](#login) - * 5.1.2.1 [RQ.SRS-006.RBAC.Login](#rqsrs-006rbaclogin) - * 5.1.2.2 [RQ.SRS-006.RBAC.Login.DefaultUser](#rqsrs-006rbaclogindefaultuser) - * 5.1.3 [User](#user) - * 5.1.3.1 [RQ.SRS-006.RBAC.User](#rqsrs-006rbacuser) - * 5.1.3.2 [RQ.SRS-006.RBAC.User.Roles](#rqsrs-006rbacuserroles) - * 5.1.3.3 [RQ.SRS-006.RBAC.User.Privileges](#rqsrs-006rbacuserprivileges) - * 5.1.3.4 [RQ.SRS-006.RBAC.User.Variables](#rqsrs-006rbacuservariables) - * 5.1.3.5 [RQ.SRS-006.RBAC.User.Variables.Constraints](#rqsrs-006rbacuservariablesconstraints) - * 5.1.3.6 [RQ.SRS-006.RBAC.User.SettingsProfile](#rqsrs-006rbacusersettingsprofile) - * 5.1.3.7 [RQ.SRS-006.RBAC.User.Quotas](#rqsrs-006rbacuserquotas) - * 5.1.3.8 [RQ.SRS-006.RBAC.User.RowPolicies](#rqsrs-006rbacuserrowpolicies) - * 5.1.3.9 [RQ.SRS-006.RBAC.User.AccountLock](#rqsrs-006rbacuseraccountlock) - * 5.1.3.10 [RQ.SRS-006.RBAC.User.AccountLock.DenyAccess](#rqsrs-006rbacuseraccountlockdenyaccess) - * 5.1.3.11 [RQ.SRS-006.RBAC.User.DefaultRole](#rqsrs-006rbacuserdefaultrole) - * 5.1.3.12 [RQ.SRS-006.RBAC.User.RoleSelection](#rqsrs-006rbacuserroleselection) - * 5.1.3.13 [RQ.SRS-006.RBAC.User.ShowCreate](#rqsrs-006rbacusershowcreate) - * 5.1.3.14 [RQ.SRS-006.RBAC.User.ShowPrivileges](#rqsrs-006rbacusershowprivileges) - * 5.1.4 [Role](#role) - * 5.1.4.1 [RQ.SRS-006.RBAC.Role](#rqsrs-006rbacrole) - * 5.1.4.2 [RQ.SRS-006.RBAC.Role.Privileges](#rqsrs-006rbacroleprivileges) - * 5.1.4.3 [RQ.SRS-006.RBAC.Role.Variables](#rqsrs-006rbacrolevariables) - * 5.1.4.4 [RQ.SRS-006.RBAC.Role.SettingsProfile](#rqsrs-006rbacrolesettingsprofile) - * 5.1.4.5 [RQ.SRS-006.RBAC.Role.Quotas](#rqsrs-006rbacrolequotas) - * 5.1.4.6 [RQ.SRS-006.RBAC.Role.RowPolicies](#rqsrs-006rbacrolerowpolicies) - * 5.1.5 [Partial Revokes](#partial-revokes) - * 5.1.5.1 [RQ.SRS-006.RBAC.PartialRevokes](#rqsrs-006rbacpartialrevokes) - * 5.1.6 [Settings Profile](#settings-profile) - * 5.1.6.1 [RQ.SRS-006.RBAC.SettingsProfile](#rqsrs-006rbacsettingsprofile) - * 5.1.6.2 [RQ.SRS-006.RBAC.SettingsProfile.Constraints](#rqsrs-006rbacsettingsprofileconstraints) - * 5.1.6.3 [RQ.SRS-006.RBAC.SettingsProfile.ShowCreate](#rqsrs-006rbacsettingsprofileshowcreate) - * 5.1.7 [Quotas](#quotas) - * 5.1.7.1 [RQ.SRS-006.RBAC.Quotas](#rqsrs-006rbacquotas) - * 5.1.7.2 [RQ.SRS-006.RBAC.Quotas.Keyed](#rqsrs-006rbacquotaskeyed) - * 5.1.7.3 [RQ.SRS-006.RBAC.Quotas.Queries](#rqsrs-006rbacquotasqueries) - * 5.1.7.4 [RQ.SRS-006.RBAC.Quotas.Errors](#rqsrs-006rbacquotaserrors) - * 5.1.7.5 [RQ.SRS-006.RBAC.Quotas.ResultRows](#rqsrs-006rbacquotasresultrows) - * 5.1.7.6 [RQ.SRS-006.RBAC.Quotas.ReadRows](#rqsrs-006rbacquotasreadrows) - * 5.1.7.7 [RQ.SRS-006.RBAC.Quotas.ResultBytes](#rqsrs-006rbacquotasresultbytes) - * 5.1.7.8 [RQ.SRS-006.RBAC.Quotas.ReadBytes](#rqsrs-006rbacquotasreadbytes) - * 5.1.7.9 [RQ.SRS-006.RBAC.Quotas.ExecutionTime](#rqsrs-006rbacquotasexecutiontime) - * 5.1.7.10 [RQ.SRS-006.RBAC.Quotas.ShowCreate](#rqsrs-006rbacquotasshowcreate) - * 5.1.8 [Row Policy](#row-policy) - * 5.1.8.1 [RQ.SRS-006.RBAC.RowPolicy](#rqsrs-006rbacrowpolicy) - * 5.1.8.2 [RQ.SRS-006.RBAC.RowPolicy.Condition](#rqsrs-006rbacrowpolicycondition) - * 5.1.8.3 [RQ.SRS-006.RBAC.RowPolicy.ShowCreate](#rqsrs-006rbacrowpolicyshowcreate) - * 5.2 [Specific](#specific) - * 5.2.8.1 [RQ.SRS-006.RBAC.User.Use.DefaultRole](#rqsrs-006rbacuserusedefaultrole) - * 5.2.8.2 [RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole](#rqsrs-006rbacuseruseallroleswhennodefaultrole) - * 5.2.8.3 [RQ.SRS-006.RBAC.User.Create](#rqsrs-006rbacusercreate) - * 5.2.8.4 [RQ.SRS-006.RBAC.User.Create.IfNotExists](#rqsrs-006rbacusercreateifnotexists) - * 5.2.8.5 [RQ.SRS-006.RBAC.User.Create.Replace](#rqsrs-006rbacusercreatereplace) - * 5.2.8.6 [RQ.SRS-006.RBAC.User.Create.Password.NoPassword](#rqsrs-006rbacusercreatepasswordnopassword) - * 5.2.8.7 [RQ.SRS-006.RBAC.User.Create.Password.NoPassword.Login](#rqsrs-006rbacusercreatepasswordnopasswordlogin) - * 5.2.8.8 [RQ.SRS-006.RBAC.User.Create.Password.PlainText](#rqsrs-006rbacusercreatepasswordplaintext) - * 5.2.8.9 [RQ.SRS-006.RBAC.User.Create.Password.PlainText.Login](#rqsrs-006rbacusercreatepasswordplaintextlogin) - * 5.2.8.10 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Password](#rqsrs-006rbacusercreatepasswordsha256password) - * 5.2.8.11 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Password.Login](#rqsrs-006rbacusercreatepasswordsha256passwordlogin) - * 5.2.8.12 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash](#rqsrs-006rbacusercreatepasswordsha256hash) - * 5.2.8.13 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash.Login](#rqsrs-006rbacusercreatepasswordsha256hashlogin) - * 5.2.8.14 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password](#rqsrs-006rbacusercreatepassworddoublesha1password) - * 5.2.8.15 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password.Login](#rqsrs-006rbacusercreatepassworddoublesha1passwordlogin) - * 5.2.8.16 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash](#rqsrs-006rbacusercreatepassworddoublesha1hash) - * 5.2.8.17 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash.Login](#rqsrs-006rbacusercreatepassworddoublesha1hashlogin) - * 5.2.8.18 [RQ.SRS-006.RBAC.User.Create.Host.Name](#rqsrs-006rbacusercreatehostname) - * 5.2.8.19 [RQ.SRS-006.RBAC.User.Create.Host.Regexp](#rqsrs-006rbacusercreatehostregexp) - * 5.2.8.20 [RQ.SRS-006.RBAC.User.Create.Host.IP](#rqsrs-006rbacusercreatehostip) - * 5.2.8.21 [RQ.SRS-006.RBAC.User.Create.Host.Any](#rqsrs-006rbacusercreatehostany) - * 5.2.8.22 [RQ.SRS-006.RBAC.User.Create.Host.None](#rqsrs-006rbacusercreatehostnone) - * 5.2.8.23 [RQ.SRS-006.RBAC.User.Create.Host.Local](#rqsrs-006rbacusercreatehostlocal) - * 5.2.8.24 [RQ.SRS-006.RBAC.User.Create.Host.Like](#rqsrs-006rbacusercreatehostlike) - * 5.2.8.25 [RQ.SRS-006.RBAC.User.Create.Host.Default](#rqsrs-006rbacusercreatehostdefault) - * 5.2.8.26 [RQ.SRS-006.RBAC.User.Create.DefaultRole](#rqsrs-006rbacusercreatedefaultrole) - * 5.2.8.27 [RQ.SRS-006.RBAC.User.Create.DefaultRole.None](#rqsrs-006rbacusercreatedefaultrolenone) - * 5.2.8.28 [RQ.SRS-006.RBAC.User.Create.DefaultRole.All](#rqsrs-006rbacusercreatedefaultroleall) - * 5.2.8.29 [RQ.SRS-006.RBAC.User.Create.Settings](#rqsrs-006rbacusercreatesettings) - * 5.2.8.30 [RQ.SRS-006.RBAC.User.Create.OnCluster](#rqsrs-006rbacusercreateoncluster) - * 5.2.8.31 [RQ.SRS-006.RBAC.User.Create.Syntax](#rqsrs-006rbacusercreatesyntax) - * 5.2.8.32 [RQ.SRS-006.RBAC.User.Alter](#rqsrs-006rbacuseralter) - * 5.2.8.33 [RQ.SRS-006.RBAC.User.Alter.OrderOfEvaluation](#rqsrs-006rbacuseralterorderofevaluation) - * 5.2.8.34 [RQ.SRS-006.RBAC.User.Alter.IfExists](#rqsrs-006rbacuseralterifexists) - * 5.2.8.35 [RQ.SRS-006.RBAC.User.Alter.Cluster](#rqsrs-006rbacuseraltercluster) - * 5.2.8.36 [RQ.SRS-006.RBAC.User.Alter.Rename](#rqsrs-006rbacuseralterrename) - * 5.2.8.37 [RQ.SRS-006.RBAC.User.Alter.Password.PlainText](#rqsrs-006rbacuseralterpasswordplaintext) - * 5.2.8.38 [RQ.SRS-006.RBAC.User.Alter.Password.Sha256Password](#rqsrs-006rbacuseralterpasswordsha256password) - * 5.2.8.39 [RQ.SRS-006.RBAC.User.Alter.Password.DoubleSha1Password](#rqsrs-006rbacuseralterpassworddoublesha1password) - * 5.2.8.40 [RQ.SRS-006.RBAC.User.Alter.Host.AddDrop](#rqsrs-006rbacuseralterhostadddrop) - * 5.2.8.41 [RQ.SRS-006.RBAC.User.Alter.Host.Local](#rqsrs-006rbacuseralterhostlocal) - * 5.2.8.42 [RQ.SRS-006.RBAC.User.Alter.Host.Name](#rqsrs-006rbacuseralterhostname) - * 5.2.8.43 [RQ.SRS-006.RBAC.User.Alter.Host.Regexp](#rqsrs-006rbacuseralterhostregexp) - * 5.2.8.44 [RQ.SRS-006.RBAC.User.Alter.Host.IP](#rqsrs-006rbacuseralterhostip) - * 5.2.8.45 [RQ.SRS-006.RBAC.User.Alter.Host.Like](#rqsrs-006rbacuseralterhostlike) - * 5.2.8.46 [RQ.SRS-006.RBAC.User.Alter.Host.Any](#rqsrs-006rbacuseralterhostany) - * 5.2.8.47 [RQ.SRS-006.RBAC.User.Alter.Host.None](#rqsrs-006rbacuseralterhostnone) - * 5.2.8.48 [RQ.SRS-006.RBAC.User.Alter.DefaultRole](#rqsrs-006rbacuseralterdefaultrole) - * 5.2.8.49 [RQ.SRS-006.RBAC.User.Alter.DefaultRole.All](#rqsrs-006rbacuseralterdefaultroleall) - * 5.2.8.50 [RQ.SRS-006.RBAC.User.Alter.DefaultRole.AllExcept](#rqsrs-006rbacuseralterdefaultroleallexcept) - * 5.2.8.51 [RQ.SRS-006.RBAC.User.Alter.Settings](#rqsrs-006rbacuseraltersettings) - * 5.2.8.52 [RQ.SRS-006.RBAC.User.Alter.Settings.Min](#rqsrs-006rbacuseraltersettingsmin) - * 5.2.8.53 [RQ.SRS-006.RBAC.User.Alter.Settings.Max](#rqsrs-006rbacuseraltersettingsmax) - * 5.2.8.54 [RQ.SRS-006.RBAC.User.Alter.Settings.Profile](#rqsrs-006rbacuseraltersettingsprofile) - * 5.2.8.55 [RQ.SRS-006.RBAC.User.Alter.Syntax](#rqsrs-006rbacuseraltersyntax) - * 5.2.8.56 [RQ.SRS-006.RBAC.SetDefaultRole](#rqsrs-006rbacsetdefaultrole) - * 5.2.8.57 [RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser](#rqsrs-006rbacsetdefaultrolecurrentuser) - * 5.2.8.58 [RQ.SRS-006.RBAC.SetDefaultRole.All](#rqsrs-006rbacsetdefaultroleall) - * 5.2.8.59 [RQ.SRS-006.RBAC.SetDefaultRole.AllExcept](#rqsrs-006rbacsetdefaultroleallexcept) - * 5.2.8.60 [RQ.SRS-006.RBAC.SetDefaultRole.None](#rqsrs-006rbacsetdefaultrolenone) - * 5.2.8.61 [RQ.SRS-006.RBAC.SetDefaultRole.Syntax](#rqsrs-006rbacsetdefaultrolesyntax) - * 5.2.8.62 [RQ.SRS-006.RBAC.SetRole](#rqsrs-006rbacsetrole) - * 5.2.8.63 [RQ.SRS-006.RBAC.SetRole.Default](#rqsrs-006rbacsetroledefault) - * 5.2.8.64 [RQ.SRS-006.RBAC.SetRole.None](#rqsrs-006rbacsetrolenone) - * 5.2.8.65 [RQ.SRS-006.RBAC.SetRole.All](#rqsrs-006rbacsetroleall) - * 5.2.8.66 [RQ.SRS-006.RBAC.SetRole.AllExcept](#rqsrs-006rbacsetroleallexcept) - * 5.2.8.67 [RQ.SRS-006.RBAC.SetRole.Syntax](#rqsrs-006rbacsetrolesyntax) - * 5.2.8.68 [RQ.SRS-006.RBAC.User.ShowCreateUser](#rqsrs-006rbacusershowcreateuser) - * 5.2.8.69 [RQ.SRS-006.RBAC.User.ShowCreateUser.For](#rqsrs-006rbacusershowcreateuserfor) - * 5.2.8.70 [RQ.SRS-006.RBAC.User.ShowCreateUser.Syntax](#rqsrs-006rbacusershowcreateusersyntax) - * 5.2.8.71 [RQ.SRS-006.RBAC.User.Drop](#rqsrs-006rbacuserdrop) - * 5.2.8.72 [RQ.SRS-006.RBAC.User.Drop.IfExists](#rqsrs-006rbacuserdropifexists) - * 5.2.8.73 [RQ.SRS-006.RBAC.User.Drop.OnCluster](#rqsrs-006rbacuserdroponcluster) - * 5.2.8.74 [RQ.SRS-006.RBAC.User.Drop.Syntax](#rqsrs-006rbacuserdropsyntax) - * 5.2.8.75 [RQ.SRS-006.RBAC.Role.Create](#rqsrs-006rbacrolecreate) - * 5.2.8.76 [RQ.SRS-006.RBAC.Role.Create.IfNotExists](#rqsrs-006rbacrolecreateifnotexists) - * 5.2.8.77 [RQ.SRS-006.RBAC.Role.Create.Replace](#rqsrs-006rbacrolecreatereplace) - * 5.2.8.78 [RQ.SRS-006.RBAC.Role.Create.Settings](#rqsrs-006rbacrolecreatesettings) - * 5.2.8.79 [RQ.SRS-006.RBAC.Role.Create.Syntax](#rqsrs-006rbacrolecreatesyntax) - * 5.2.8.80 [RQ.SRS-006.RBAC.Role.Alter](#rqsrs-006rbacrolealter) - * 5.2.8.81 [RQ.SRS-006.RBAC.Role.Alter.IfExists](#rqsrs-006rbacrolealterifexists) - * 5.2.8.82 [RQ.SRS-006.RBAC.Role.Alter.Cluster](#rqsrs-006rbacrolealtercluster) - * 5.2.8.83 [RQ.SRS-006.RBAC.Role.Alter.Rename](#rqsrs-006rbacrolealterrename) - * 5.2.8.84 [RQ.SRS-006.RBAC.Role.Alter.Settings](#rqsrs-006rbacrolealtersettings) - * 5.2.8.85 [RQ.SRS-006.RBAC.Role.Alter.Syntax](#rqsrs-006rbacrolealtersyntax) - * 5.2.8.86 [RQ.SRS-006.RBAC.Role.Drop](#rqsrs-006rbacroledrop) - * 5.2.8.87 [RQ.SRS-006.RBAC.Role.Drop.IfExists](#rqsrs-006rbacroledropifexists) - * 5.2.8.88 [RQ.SRS-006.RBAC.Role.Drop.Cluster](#rqsrs-006rbacroledropcluster) - * 5.2.8.89 [RQ.SRS-006.RBAC.Role.Drop.Syntax](#rqsrs-006rbacroledropsyntax) - * 5.2.8.90 [RQ.SRS-006.RBAC.Role.ShowCreate](#rqsrs-006rbacroleshowcreate) - * 5.2.8.91 [RQ.SRS-006.RBAC.Role.ShowCreate.Syntax](#rqsrs-006rbacroleshowcreatesyntax) - * 5.2.8.92 [RQ.SRS-006.RBAC.Grant.Privilege.To](#rqsrs-006rbacgrantprivilegeto) - * 5.2.8.93 [RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser](#rqsrs-006rbacgrantprivilegetocurrentuser) - * 5.2.8.94 [RQ.SRS-006.RBAC.Grant.Privilege.Select](#rqsrs-006rbacgrantprivilegeselect) - * 5.2.8.95 [RQ.SRS-006.RBAC.Grant.Privilege.Insert](#rqsrs-006rbacgrantprivilegeinsert) - * 5.2.8.96 [RQ.SRS-006.RBAC.Grant.Privilege.Alter](#rqsrs-006rbacgrantprivilegealter) - * 5.2.8.97 [RQ.SRS-006.RBAC.Grant.Privilege.Create](#rqsrs-006rbacgrantprivilegecreate) - * 5.2.8.98 [RQ.SRS-006.RBAC.Grant.Privilege.Drop](#rqsrs-006rbacgrantprivilegedrop) - * 5.2.8.99 [RQ.SRS-006.RBAC.Grant.Privilege.Truncate](#rqsrs-006rbacgrantprivilegetruncate) - * 5.2.8.100 [RQ.SRS-006.RBAC.Grant.Privilege.Optimize](#rqsrs-006rbacgrantprivilegeoptimize) - * 5.2.8.101 [RQ.SRS-006.RBAC.Grant.Privilege.Show](#rqsrs-006rbacgrantprivilegeshow) - * 5.2.8.102 [RQ.SRS-006.RBAC.Grant.Privilege.KillQuery](#rqsrs-006rbacgrantprivilegekillquery) - * 5.2.8.103 [RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement](#rqsrs-006rbacgrantprivilegeaccessmanagement) - * 5.2.8.104 [RQ.SRS-006.RBAC.Grant.Privilege.System](#rqsrs-006rbacgrantprivilegesystem) - * 5.2.8.105 [RQ.SRS-006.RBAC.Grant.Privilege.Introspection](#rqsrs-006rbacgrantprivilegeintrospection) - * 5.2.8.106 [RQ.SRS-006.RBAC.Grant.Privilege.Sources](#rqsrs-006rbacgrantprivilegesources) - * 5.2.8.107 [RQ.SRS-006.RBAC.Grant.Privilege.DictGet](#rqsrs-006rbacgrantprivilegedictget) - * 5.2.8.108 [RQ.SRS-006.RBAC.Grant.Privilege.None](#rqsrs-006rbacgrantprivilegenone) - * 5.2.8.109 [RQ.SRS-006.RBAC.Grant.Privilege.All](#rqsrs-006rbacgrantprivilegeall) - * 5.2.8.110 [RQ.SRS-006.RBAC.Grant.Privilege.GrantOption](#rqsrs-006rbacgrantprivilegegrantoption) - * 5.2.8.111 [RQ.SRS-006.RBAC.Grant.Privilege.On](#rqsrs-006rbacgrantprivilegeon) - * 5.2.8.112 [RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns](#rqsrs-006rbacgrantprivilegeprivilegecolumns) - * 5.2.8.113 [RQ.SRS-006.RBAC.Grant.Privilege.OnCluster](#rqsrs-006rbacgrantprivilegeoncluster) - * 5.2.8.114 [RQ.SRS-006.RBAC.Grant.Privilege.Syntax](#rqsrs-006rbacgrantprivilegesyntax) - * 5.2.8.115 [RQ.SRS-006.RBAC.Revoke.Privilege.Cluster](#rqsrs-006rbacrevokeprivilegecluster) - * 5.2.8.116 [RQ.SRS-006.RBAC.Revoke.Privilege.Any](#rqsrs-006rbacrevokeprivilegeany) - * 5.2.8.117 [RQ.SRS-006.RBAC.Revoke.Privilege.Select](#rqsrs-006rbacrevokeprivilegeselect) - * 5.2.8.118 [RQ.SRS-006.RBAC.Revoke.Privilege.Insert](#rqsrs-006rbacrevokeprivilegeinsert) - * 5.2.8.119 [RQ.SRS-006.RBAC.Revoke.Privilege.Alter](#rqsrs-006rbacrevokeprivilegealter) - * 5.2.8.120 [RQ.SRS-006.RBAC.Revoke.Privilege.Create](#rqsrs-006rbacrevokeprivilegecreate) - * 5.2.8.121 [RQ.SRS-006.RBAC.Revoke.Privilege.Drop](#rqsrs-006rbacrevokeprivilegedrop) - * 5.2.8.122 [RQ.SRS-006.RBAC.Revoke.Privilege.Truncate](#rqsrs-006rbacrevokeprivilegetruncate) - * 5.2.8.123 [RQ.SRS-006.RBAC.Revoke.Privilege.Optimize](#rqsrs-006rbacrevokeprivilegeoptimize) - * 5.2.8.124 [RQ.SRS-006.RBAC.Revoke.Privilege.Show](#rqsrs-006rbacrevokeprivilegeshow) - * 5.2.8.125 [RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery](#rqsrs-006rbacrevokeprivilegekillquery) - * 5.2.8.126 [RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement](#rqsrs-006rbacrevokeprivilegeaccessmanagement) - * 5.2.8.127 [RQ.SRS-006.RBAC.Revoke.Privilege.System](#rqsrs-006rbacrevokeprivilegesystem) - * 5.2.8.128 [RQ.SRS-006.RBAC.Revoke.Privilege.Introspection](#rqsrs-006rbacrevokeprivilegeintrospection) - * 5.2.8.129 [RQ.SRS-006.RBAC.Revoke.Privilege.Sources](#rqsrs-006rbacrevokeprivilegesources) - * 5.2.8.130 [RQ.SRS-006.RBAC.Revoke.Privilege.DictGet](#rqsrs-006rbacrevokeprivilegedictget) - * 5.2.8.131 [RQ.SRS-006.RBAC.Revoke.Privilege.PrivelegeColumns](#rqsrs-006rbacrevokeprivilegeprivelegecolumns) - * 5.2.8.132 [RQ.SRS-006.RBAC.Revoke.Privilege.Multiple](#rqsrs-006rbacrevokeprivilegemultiple) - * 5.2.8.133 [RQ.SRS-006.RBAC.Revoke.Privilege.All](#rqsrs-006rbacrevokeprivilegeall) - * 5.2.8.134 [RQ.SRS-006.RBAC.Revoke.Privilege.None](#rqsrs-006rbacrevokeprivilegenone) - * 5.2.8.135 [RQ.SRS-006.RBAC.Revoke.Privilege.On](#rqsrs-006rbacrevokeprivilegeon) - * 5.2.8.136 [RQ.SRS-006.RBAC.Revoke.Privilege.From](#rqsrs-006rbacrevokeprivilegefrom) - * 5.2.8.137 [RQ.SRS-006.RBAC.Revoke.Privilege.Syntax](#rqsrs-006rbacrevokeprivilegesyntax) - * 5.2.8.138 [RQ.SRS-006.RBAC.PartialRevoke.Syntax](#rqsrs-006rbacpartialrevokesyntax) - * 5.2.8.139 [RQ.SRS-006.RBAC.Grant.Role](#rqsrs-006rbacgrantrole) - * 5.2.8.140 [RQ.SRS-006.RBAC.Grant.Role.CurrentUser](#rqsrs-006rbacgrantrolecurrentuser) - * 5.2.8.141 [RQ.SRS-006.RBAC.Grant.Role.AdminOption](#rqsrs-006rbacgrantroleadminoption) - * 5.2.8.142 [RQ.SRS-006.RBAC.Grant.Role.OnCluster](#rqsrs-006rbacgrantroleoncluster) - * 5.2.8.143 [RQ.SRS-006.RBAC.Grant.Role.Syntax](#rqsrs-006rbacgrantrolesyntax) - * 5.2.8.144 [RQ.SRS-006.RBAC.Revoke.Role](#rqsrs-006rbacrevokerole) - * 5.2.8.145 [RQ.SRS-006.RBAC.Revoke.Role.Keywords](#rqsrs-006rbacrevokerolekeywords) - * 5.2.8.146 [RQ.SRS-006.RBAC.Revoke.Role.Cluster](#rqsrs-006rbacrevokerolecluster) - * 5.2.8.147 [RQ.SRS-006.RBAC.Revoke.AdminOption](#rqsrs-006rbacrevokeadminoption) - * 5.2.8.148 [RQ.SRS-006.RBAC.Revoke.Role.Syntax](#rqsrs-006rbacrevokerolesyntax) - * 5.2.8.149 [RQ.SRS-006.RBAC.Show.Grants](#rqsrs-006rbacshowgrants) - * 5.2.8.150 [RQ.SRS-006.RBAC.Show.Grants.For](#rqsrs-006rbacshowgrantsfor) - * 5.2.8.151 [RQ.SRS-006.RBAC.Show.Grants.Syntax](#rqsrs-006rbacshowgrantssyntax) - * 5.2.8.152 [RQ.SRS-006.RBAC.SettingsProfile.Create](#rqsrs-006rbacsettingsprofilecreate) - * 5.2.8.153 [RQ.SRS-006.RBAC.SettingsProfile.Create.IfNotExists](#rqsrs-006rbacsettingsprofilecreateifnotexists) - * 5.2.8.154 [RQ.SRS-006.RBAC.SettingsProfile.Create.Replace](#rqsrs-006rbacsettingsprofilecreatereplace) - * 5.2.8.155 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables](#rqsrs-006rbacsettingsprofilecreatevariables) - * 5.2.8.156 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Value](#rqsrs-006rbacsettingsprofilecreatevariablesvalue) - * 5.2.8.157 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Constraints](#rqsrs-006rbacsettingsprofilecreatevariablesconstraints) - * 5.2.8.158 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment](#rqsrs-006rbacsettingsprofilecreateassignment) - * 5.2.8.159 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.None](#rqsrs-006rbacsettingsprofilecreateassignmentnone) - * 5.2.8.160 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.All](#rqsrs-006rbacsettingsprofilecreateassignmentall) - * 5.2.8.161 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.AllExcept](#rqsrs-006rbacsettingsprofilecreateassignmentallexcept) - * 5.2.8.162 [RQ.SRS-006.RBAC.SettingsProfile.Create.Inherit](#rqsrs-006rbacsettingsprofilecreateinherit) - * 5.2.8.163 [RQ.SRS-006.RBAC.SettingsProfile.Create.OnCluster](#rqsrs-006rbacsettingsprofilecreateoncluster) - * 5.2.8.164 [RQ.SRS-006.RBAC.SettingsProfile.Create.Syntax](#rqsrs-006rbacsettingsprofilecreatesyntax) - * 5.2.8.165 [RQ.SRS-006.RBAC.SettingsProfile.Alter](#rqsrs-006rbacsettingsprofilealter) - * 5.2.8.166 [RQ.SRS-006.RBAC.SettingsProfile.Alter.IfExists](#rqsrs-006rbacsettingsprofilealterifexists) - * 5.2.8.167 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Rename](#rqsrs-006rbacsettingsprofilealterrename) - * 5.2.8.168 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables](#rqsrs-006rbacsettingsprofilealtervariables) - * 5.2.8.169 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Value](#rqsrs-006rbacsettingsprofilealtervariablesvalue) - * 5.2.8.170 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Constraints](#rqsrs-006rbacsettingsprofilealtervariablesconstraints) - * 5.2.8.171 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment](#rqsrs-006rbacsettingsprofilealterassignment) - * 5.2.8.172 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.None](#rqsrs-006rbacsettingsprofilealterassignmentnone) - * 5.2.8.173 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.All](#rqsrs-006rbacsettingsprofilealterassignmentall) - * 5.2.8.174 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.AllExcept](#rqsrs-006rbacsettingsprofilealterassignmentallexcept) - * 5.2.8.175 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.Inherit](#rqsrs-006rbacsettingsprofilealterassignmentinherit) - * 5.2.8.176 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.OnCluster](#rqsrs-006rbacsettingsprofilealterassignmentoncluster) - * 5.2.8.177 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Syntax](#rqsrs-006rbacsettingsprofilealtersyntax) - * 5.2.8.178 [RQ.SRS-006.RBAC.SettingsProfile.Drop](#rqsrs-006rbacsettingsprofiledrop) - * 5.2.8.179 [RQ.SRS-006.RBAC.SettingsProfile.Drop.IfExists](#rqsrs-006rbacsettingsprofiledropifexists) - * 5.2.8.180 [RQ.SRS-006.RBAC.SettingsProfile.Drop.OnCluster](#rqsrs-006rbacsettingsprofiledroponcluster) - * 5.2.8.181 [RQ.SRS-006.RBAC.SettingsProfile.Drop.Syntax](#rqsrs-006rbacsettingsprofiledropsyntax) - * 5.2.8.182 [RQ.SRS-006.RBAC.SettingsProfile.ShowCreateSettingsProfile](#rqsrs-006rbacsettingsprofileshowcreatesettingsprofile) - * 5.2.8.183 [RQ.SRS-006.RBAC.Quota.Create](#rqsrs-006rbacquotacreate) - * 5.2.8.184 [RQ.SRS-006.RBAC.Quota.Create.IfNotExists](#rqsrs-006rbacquotacreateifnotexists) - * 5.2.8.185 [RQ.SRS-006.RBAC.Quota.Create.Replace](#rqsrs-006rbacquotacreatereplace) - * 5.2.8.186 [RQ.SRS-006.RBAC.Quota.Create.Cluster](#rqsrs-006rbacquotacreatecluster) - * 5.2.8.187 [RQ.SRS-006.RBAC.Quota.Create.Interval](#rqsrs-006rbacquotacreateinterval) - * 5.2.8.188 [RQ.SRS-006.RBAC.Quota.Create.Interval.Randomized](#rqsrs-006rbacquotacreateintervalrandomized) - * 5.2.8.189 [RQ.SRS-006.RBAC.Quota.Create.Queries](#rqsrs-006rbacquotacreatequeries) - * 5.2.8.190 [RQ.SRS-006.RBAC.Quota.Create.Errors](#rqsrs-006rbacquotacreateerrors) - * 5.2.8.191 [RQ.SRS-006.RBAC.Quota.Create.ResultRows](#rqsrs-006rbacquotacreateresultrows) - * 5.2.8.192 [RQ.SRS-006.RBAC.Quota.Create.ReadRows](#rqsrs-006rbacquotacreatereadrows) - * 5.2.8.193 [RQ.SRS-006.RBAC.Quota.Create.ResultBytes](#rqsrs-006rbacquotacreateresultbytes) - * 5.2.8.194 [RQ.SRS-006.RBAC.Quota.Create.ReadBytes](#rqsrs-006rbacquotacreatereadbytes) - * 5.2.8.195 [RQ.SRS-006.RBAC.Quota.Create.ExecutionTime](#rqsrs-006rbacquotacreateexecutiontime) - * 5.2.8.196 [RQ.SRS-006.RBAC.Quota.Create.NoLimits](#rqsrs-006rbacquotacreatenolimits) - * 5.2.8.197 [RQ.SRS-006.RBAC.Quota.Create.TrackingOnly](#rqsrs-006rbacquotacreatetrackingonly) - * 5.2.8.198 [RQ.SRS-006.RBAC.Quota.Create.KeyedBy](#rqsrs-006rbacquotacreatekeyedby) - * 5.2.8.199 [RQ.SRS-006.RBAC.Quota.Create.KeyedByOptions](#rqsrs-006rbacquotacreatekeyedbyoptions) - * 5.2.8.200 [RQ.SRS-006.RBAC.Quota.Create.Assignment](#rqsrs-006rbacquotacreateassignment) - * 5.2.8.201 [RQ.SRS-006.RBAC.Quota.Create.Assignment.None](#rqsrs-006rbacquotacreateassignmentnone) - * 5.2.8.202 [RQ.SRS-006.RBAC.Quota.Create.Assignment.All](#rqsrs-006rbacquotacreateassignmentall) - * 5.2.8.203 [RQ.SRS-006.RBAC.Quota.Create.Assignment.Except](#rqsrs-006rbacquotacreateassignmentexcept) - * 5.2.8.204 [RQ.SRS-006.RBAC.Quota.Create.Syntax](#rqsrs-006rbacquotacreatesyntax) - * 5.2.8.205 [RQ.SRS-006.RBAC.Quota.Alter](#rqsrs-006rbacquotaalter) - * 5.2.8.206 [RQ.SRS-006.RBAC.Quota.Alter.IfExists](#rqsrs-006rbacquotaalterifexists) - * 5.2.8.207 [RQ.SRS-006.RBAC.Quota.Alter.Rename](#rqsrs-006rbacquotaalterrename) - * 5.2.8.208 [RQ.SRS-006.RBAC.Quota.Alter.Cluster](#rqsrs-006rbacquotaaltercluster) - * 5.2.8.209 [RQ.SRS-006.RBAC.Quota.Alter.Interval](#rqsrs-006rbacquotaalterinterval) - * 5.2.8.210 [RQ.SRS-006.RBAC.Quota.Alter.Interval.Randomized](#rqsrs-006rbacquotaalterintervalrandomized) - * 5.2.8.211 [RQ.SRS-006.RBAC.Quota.Alter.Queries](#rqsrs-006rbacquotaalterqueries) - * 5.2.8.212 [RQ.SRS-006.RBAC.Quota.Alter.Errors](#rqsrs-006rbacquotaaltererrors) - * 5.2.8.213 [RQ.SRS-006.RBAC.Quota.Alter.ResultRows](#rqsrs-006rbacquotaalterresultrows) - * 5.2.8.214 [RQ.SRS-006.RBAC.Quota.Alter.ReadRows](#rqsrs-006rbacquotaalterreadrows) - * 5.2.8.215 [RQ.SRS-006.RBAC.Quota.ALter.ResultBytes](#rqsrs-006rbacquotaalterresultbytes) - * 5.2.8.216 [RQ.SRS-006.RBAC.Quota.Alter.ReadBytes](#rqsrs-006rbacquotaalterreadbytes) - * 5.2.8.217 [RQ.SRS-006.RBAC.Quota.Alter.ExecutionTime](#rqsrs-006rbacquotaalterexecutiontime) - * 5.2.8.218 [RQ.SRS-006.RBAC.Quota.Alter.NoLimits](#rqsrs-006rbacquotaalternolimits) - * 5.2.8.219 [RQ.SRS-006.RBAC.Quota.Alter.TrackingOnly](#rqsrs-006rbacquotaaltertrackingonly) - * 5.2.8.220 [RQ.SRS-006.RBAC.Quota.Alter.KeyedBy](#rqsrs-006rbacquotaalterkeyedby) - * 5.2.8.221 [RQ.SRS-006.RBAC.Quota.Alter.KeyedByOptions](#rqsrs-006rbacquotaalterkeyedbyoptions) - * 5.2.8.222 [RQ.SRS-006.RBAC.Quota.Alter.Assignment](#rqsrs-006rbacquotaalterassignment) - * 5.2.8.223 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.None](#rqsrs-006rbacquotaalterassignmentnone) - * 5.2.8.224 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.All](#rqsrs-006rbacquotaalterassignmentall) - * 5.2.8.225 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.Except](#rqsrs-006rbacquotaalterassignmentexcept) - * 5.2.8.226 [RQ.SRS-006.RBAC.Quota.Alter.Syntax](#rqsrs-006rbacquotaaltersyntax) - * 5.2.8.227 [RQ.SRS-006.RBAC.Quota.Drop](#rqsrs-006rbacquotadrop) - * 5.2.8.228 [RQ.SRS-006.RBAC.Quota.Drop.IfExists](#rqsrs-006rbacquotadropifexists) - * 5.2.8.229 [RQ.SRS-006.RBAC.Quota.Drop.Cluster](#rqsrs-006rbacquotadropcluster) - * 5.2.8.230 [RQ.SRS-006.RBAC.Quota.Drop.Syntax](#rqsrs-006rbacquotadropsyntax) - * 5.2.8.231 [RQ.SRS-006.RBAC.Quota.ShowQuotas](#rqsrs-006rbacquotashowquotas) - * 5.2.8.232 [RQ.SRS-006.RBAC.Quota.ShowQuotas.IntoOutfile](#rqsrs-006rbacquotashowquotasintooutfile) - * 5.2.8.233 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Format](#rqsrs-006rbacquotashowquotasformat) - * 5.2.8.234 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Settings](#rqsrs-006rbacquotashowquotassettings) - * 5.2.8.235 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Syntax](#rqsrs-006rbacquotashowquotassyntax) - * 5.2.8.236 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Name](#rqsrs-006rbacquotashowcreatequotaname) - * 5.2.8.237 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Current](#rqsrs-006rbacquotashowcreatequotacurrent) - * 5.2.8.238 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Syntax](#rqsrs-006rbacquotashowcreatequotasyntax) - * 5.2.8.239 [RQ.SRS-006.RBAC.RowPolicy.Create](#rqsrs-006rbacrowpolicycreate) - * 5.2.8.240 [RQ.SRS-006.RBAC.RowPolicy.Create.IfNotExists](#rqsrs-006rbacrowpolicycreateifnotexists) - * 5.2.8.241 [RQ.SRS-006.RBAC.RowPolicy.Create.Replace](#rqsrs-006rbacrowpolicycreatereplace) - * 5.2.8.242 [RQ.SRS-006.RBAC.RowPolicy.Create.OnCluster](#rqsrs-006rbacrowpolicycreateoncluster) - * 5.2.8.243 [RQ.SRS-006.RBAC.RowPolicy.Create.On](#rqsrs-006rbacrowpolicycreateon) - * 5.2.8.244 [RQ.SRS-006.RBAC.RowPolicy.Create.Access](#rqsrs-006rbacrowpolicycreateaccess) - * 5.2.8.245 [RQ.SRS-006.RBAC.RowPolicy.Create.Access.Permissive](#rqsrs-006rbacrowpolicycreateaccesspermissive) - * 5.2.8.246 [RQ.SRS-006.RBAC.RowPolicy.Create.Access.Restrictive](#rqsrs-006rbacrowpolicycreateaccessrestrictive) - * 5.2.8.247 [RQ.SRS-006.RBAC.RowPolicy.Create.ForSelect](#rqsrs-006rbacrowpolicycreateforselect) - * 5.2.8.248 [RQ.SRS-006.RBAC.RowPolicy.Create.Condition](#rqsrs-006rbacrowpolicycreatecondition) - * 5.2.8.249 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment](#rqsrs-006rbacrowpolicycreateassignment) - * 5.2.8.250 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.None](#rqsrs-006rbacrowpolicycreateassignmentnone) - * 5.2.8.251 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.All](#rqsrs-006rbacrowpolicycreateassignmentall) - * 5.2.8.252 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.AllExcept](#rqsrs-006rbacrowpolicycreateassignmentallexcept) - * 5.2.8.253 [RQ.SRS-006.RBAC.RowPolicy.Create.Syntax](#rqsrs-006rbacrowpolicycreatesyntax) - * 5.2.8.254 [RQ.SRS-006.RBAC.RowPolicy.Alter](#rqsrs-006rbacrowpolicyalter) - * 5.2.8.255 [RQ.SRS-006.RBAC.RowPolicy.Alter.IfExists](#rqsrs-006rbacrowpolicyalterifexists) - * 5.2.8.256 [RQ.SRS-006.RBAC.RowPolicy.Alter.ForSelect](#rqsrs-006rbacrowpolicyalterforselect) - * 5.2.8.257 [RQ.SRS-006.RBAC.RowPolicy.Alter.OnCluster](#rqsrs-006rbacrowpolicyalteroncluster) - * 5.2.8.258 [RQ.SRS-006.RBAC.RowPolicy.Alter.On](#rqsrs-006rbacrowpolicyalteron) - * 5.2.8.259 [RQ.SRS-006.RBAC.RowPolicy.Alter.Rename](#rqsrs-006rbacrowpolicyalterrename) - * 5.2.8.260 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access](#rqsrs-006rbacrowpolicyalteraccess) - * 5.2.8.261 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Permissive](#rqsrs-006rbacrowpolicyalteraccesspermissive) - * 5.2.8.262 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Restrictive](#rqsrs-006rbacrowpolicyalteraccessrestrictive) - * 5.2.8.263 [RQ.SRS-006.RBAC.RowPolicy.Alter.Condition](#rqsrs-006rbacrowpolicyaltercondition) - * 5.2.8.264 [RQ.SRS-006.RBAC.RowPolicy.Alter.Condition.None](#rqsrs-006rbacrowpolicyalterconditionnone) - * 5.2.8.265 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment](#rqsrs-006rbacrowpolicyalterassignment) - * 5.2.8.266 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.None](#rqsrs-006rbacrowpolicyalterassignmentnone) - * 5.2.8.267 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.All](#rqsrs-006rbacrowpolicyalterassignmentall) - * 5.2.8.268 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.AllExcept](#rqsrs-006rbacrowpolicyalterassignmentallexcept) - * 5.2.8.269 [RQ.SRS-006.RBAC.RowPolicy.Alter.Syntax](#rqsrs-006rbacrowpolicyaltersyntax) - * 5.2.8.270 [RQ.SRS-006.RBAC.RowPolicy.Drop](#rqsrs-006rbacrowpolicydrop) - * 5.2.8.271 [RQ.SRS-006.RBAC.RowPolicy.Drop.IfExists](#rqsrs-006rbacrowpolicydropifexists) - * 5.2.8.272 [RQ.SRS-006.RBAC.RowPolicy.Drop.On](#rqsrs-006rbacrowpolicydropon) - * 5.2.8.273 [RQ.SRS-006.RBAC.RowPolicy.Drop.OnCluster](#rqsrs-006rbacrowpolicydroponcluster) - * 5.2.8.274 [RQ.SRS-006.RBAC.RowPolicy.Drop.Syntax](#rqsrs-006rbacrowpolicydropsyntax) - * 5.2.8.275 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy](#rqsrs-006rbacrowpolicyshowcreaterowpolicy) - * 5.2.8.276 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.On](#rqsrs-006rbacrowpolicyshowcreaterowpolicyon) - * 5.2.8.277 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.Syntax](#rqsrs-006rbacrowpolicyshowcreaterowpolicysyntax) - * 5.2.8.278 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies](#rqsrs-006rbacrowpolicyshowrowpolicies) - * 5.2.8.279 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.On](#rqsrs-006rbacrowpolicyshowrowpolicieson) - * 5.2.8.280 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.Syntax](#rqsrs-006rbacrowpolicyshowrowpoliciessyntax) - * 5.2.9 [Table Privileges](#table-privileges) - * 5.2.9.1 [RQ.SRS-006.RBAC.Table.PublicTables](#rqsrs-006rbactablepublictables) - * 5.2.9.2 [RQ.SRS-006.RBAC.Table.SensitiveTables](#rqsrs-006rbactablesensitivetables) - * 5.2.10 [Distributed Tables](#distributed-tables) - * 5.2.10.1 [RQ.SRS-006.RBAC.DistributedTable.Create](#rqsrs-006rbacdistributedtablecreate) - * 5.2.10.2 [RQ.SRS-006.RBAC.DistributedTable.Select](#rqsrs-006rbacdistributedtableselect) - * 5.2.10.3 [RQ.SRS-006.RBAC.DistributedTable.Insert](#rqsrs-006rbacdistributedtableinsert) - * 5.2.10.4 [RQ.SRS-006.RBAC.DistributedTable.SpecialTables](#rqsrs-006rbacdistributedtablespecialtables) - * 5.2.10.5 [RQ.SRS-006.RBAC.DistributedTable.LocalUser](#rqsrs-006rbacdistributedtablelocaluser) - * 5.2.10.6 [RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges](#rqsrs-006rbacdistributedtablesameuserdifferentnodesdifferentprivileges) - * 5.2.11 [Views](#views) - * 5.2.11.1 [View](#view) - * 5.2.11.1.1 [RQ.SRS-006.RBAC.View](#rqsrs-006rbacview) - * 5.2.11.1.2 [RQ.SRS-006.RBAC.View.Create](#rqsrs-006rbacviewcreate) - * 5.2.11.1.3 [RQ.SRS-006.RBAC.View.Select](#rqsrs-006rbacviewselect) - * 5.2.11.1.4 [RQ.SRS-006.RBAC.View.Drop](#rqsrs-006rbacviewdrop) - * 5.2.11.2 [Materialized View](#materialized-view) - * 5.2.11.2.1 [RQ.SRS-006.RBAC.MaterializedView](#rqsrs-006rbacmaterializedview) - * 5.2.11.2.2 [RQ.SRS-006.RBAC.MaterializedView.Create](#rqsrs-006rbacmaterializedviewcreate) - * 5.2.11.2.3 [RQ.SRS-006.RBAC.MaterializedView.Select](#rqsrs-006rbacmaterializedviewselect) - * 5.2.11.2.4 [RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable](#rqsrs-006rbacmaterializedviewselecttargettable) - * 5.2.11.2.5 [RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable](#rqsrs-006rbacmaterializedviewselectsourcetable) - * 5.2.11.2.6 [RQ.SRS-006.RBAC.MaterializedView.Drop](#rqsrs-006rbacmaterializedviewdrop) - * 5.2.11.2.7 [RQ.SRS-006.RBAC.MaterializedView.ModifyQuery](#rqsrs-006rbacmaterializedviewmodifyquery) - * 5.2.11.2.8 [RQ.SRS-006.RBAC.MaterializedView.Insert](#rqsrs-006rbacmaterializedviewinsert) - * 5.2.11.2.9 [RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable](#rqsrs-006rbacmaterializedviewinsertsourcetable) - * 5.2.11.2.10 [RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable](#rqsrs-006rbacmaterializedviewinserttargettable) - * 5.2.11.3 [Live View](#live-view) - * 5.2.11.3.1 [RQ.SRS-006.RBAC.LiveView](#rqsrs-006rbacliveview) - * 5.2.11.3.2 [RQ.SRS-006.RBAC.LiveView.Create](#rqsrs-006rbacliveviewcreate) - * 5.2.11.3.3 [RQ.SRS-006.RBAC.LiveView.Select](#rqsrs-006rbacliveviewselect) - * 5.2.11.3.4 [RQ.SRS-006.RBAC.LiveView.Drop](#rqsrs-006rbacliveviewdrop) - * 5.2.11.3.5 [RQ.SRS-006.RBAC.LiveView.Refresh](#rqsrs-006rbacliveviewrefresh) - * 5.2.12 [Select](#select) - * 5.2.12.1 [RQ.SRS-006.RBAC.Select](#rqsrs-006rbacselect) - * 5.2.12.2 [RQ.SRS-006.RBAC.Select.Column](#rqsrs-006rbacselectcolumn) - * 5.2.12.3 [RQ.SRS-006.RBAC.Select.Cluster](#rqsrs-006rbacselectcluster) - * 5.2.12.4 [RQ.SRS-006.RBAC.Select.TableEngines](#rqsrs-006rbacselecttableengines) - * 5.2.13 [Insert](#insert) - * 5.2.13.1 [RQ.SRS-006.RBAC.Insert](#rqsrs-006rbacinsert) - * 5.2.13.2 [RQ.SRS-006.RBAC.Insert.Column](#rqsrs-006rbacinsertcolumn) - * 5.2.13.3 [RQ.SRS-006.RBAC.Insert.Cluster](#rqsrs-006rbacinsertcluster) - * 5.2.13.4 [RQ.SRS-006.RBAC.Insert.TableEngines](#rqsrs-006rbacinserttableengines) - * 5.2.14 [Alter](#alter) - * 5.2.14.1 [Alter Column](#alter-column) - * 5.2.14.1.1 [RQ.SRS-006.RBAC.Privileges.AlterColumn](#rqsrs-006rbacprivilegesaltercolumn) - * 5.2.14.1.2 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant](#rqsrs-006rbacprivilegesaltercolumngrant) - * 5.2.14.1.3 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke](#rqsrs-006rbacprivilegesaltercolumnrevoke) - * 5.2.14.1.4 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Column](#rqsrs-006rbacprivilegesaltercolumncolumn) - * 5.2.14.1.5 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster](#rqsrs-006rbacprivilegesaltercolumncluster) - * 5.2.14.1.6 [RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines](#rqsrs-006rbacprivilegesaltercolumntableengines) - * 5.2.14.2 [Alter Index](#alter-index) - * 5.2.14.2.1 [RQ.SRS-006.RBAC.Privileges.AlterIndex](#rqsrs-006rbacprivilegesalterindex) - * 5.2.14.2.2 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant](#rqsrs-006rbacprivilegesalterindexgrant) - * 5.2.14.2.3 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke](#rqsrs-006rbacprivilegesalterindexrevoke) - * 5.2.14.2.4 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster](#rqsrs-006rbacprivilegesalterindexcluster) - * 5.2.14.2.5 [RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines](#rqsrs-006rbacprivilegesalterindextableengines) - * 5.2.14.3 [Alter Constraint](#alter-constraint) - * 5.2.14.3.1 [RQ.SRS-006.RBAC.Privileges.AlterConstraint](#rqsrs-006rbacprivilegesalterconstraint) - * 5.2.14.3.2 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant](#rqsrs-006rbacprivilegesalterconstraintgrant) - * 5.2.14.3.3 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke](#rqsrs-006rbacprivilegesalterconstraintrevoke) - * 5.2.14.3.4 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster](#rqsrs-006rbacprivilegesalterconstraintcluster) - * 5.2.14.3.5 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines](#rqsrs-006rbacprivilegesalterconstrainttableengines) - * 5.2.14.4 [Alter TTL](#alter-ttl) - * 5.2.14.4.1 [RQ.SRS-006.RBAC.Privileges.AlterTTL](#rqsrs-006rbacprivilegesalterttl) - * 5.2.14.4.2 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant](#rqsrs-006rbacprivilegesalterttlgrant) - * 5.2.14.4.3 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke](#rqsrs-006rbacprivilegesalterttlrevoke) - * 5.2.14.4.4 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster](#rqsrs-006rbacprivilegesalterttlcluster) - * 5.2.14.4.5 [RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines](#rqsrs-006rbacprivilegesalterttltableengines) - * 5.2.14.5 [Alter Settings](#alter-settings) - * 5.2.14.5.1 [RQ.SRS-006.RBAC.Privileges.AlterSettings](#rqsrs-006rbacprivilegesaltersettings) - * 5.2.14.5.2 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant](#rqsrs-006rbacprivilegesaltersettingsgrant) - * 5.2.14.5.3 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke](#rqsrs-006rbacprivilegesaltersettingsrevoke) - * 5.2.14.5.4 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster](#rqsrs-006rbacprivilegesaltersettingscluster) - * 5.2.14.5.5 [RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines](#rqsrs-006rbacprivilegesaltersettingstableengines) - * 5.2.14.6 [Alter Update](#alter-update) - * 5.2.14.6.1 [RQ.SRS-006.RBAC.Privileges.AlterUpdate](#rqsrs-006rbacprivilegesalterupdate) - * 5.2.14.6.2 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant](#rqsrs-006rbacprivilegesalterupdategrant) - * 5.2.14.6.3 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke](#rqsrs-006rbacprivilegesalterupdaterevoke) - * 5.2.14.6.4 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines](#rqsrs-006rbacprivilegesalterupdatetableengines) - * 5.2.14.7 [Alter Delete](#alter-delete) - * 5.2.14.7.1 [RQ.SRS-006.RBAC.Privileges.AlterDelete](#rqsrs-006rbacprivilegesalterdelete) - * 5.2.14.7.2 [RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant](#rqsrs-006rbacprivilegesalterdeletegrant) - * 5.2.14.7.3 [RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke](#rqsrs-006rbacprivilegesalterdeleterevoke) - * 5.2.14.7.4 [RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines](#rqsrs-006rbacprivilegesalterdeletetableengines) - * 5.2.14.8 [Alter Freeze Partition](#alter-freeze-partition) - * 5.2.14.8.1 [RQ.SRS-006.RBAC.Privileges.AlterFreeze](#rqsrs-006rbacprivilegesalterfreeze) - * 5.2.14.8.2 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant](#rqsrs-006rbacprivilegesalterfreezegrant) - * 5.2.14.8.3 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke](#rqsrs-006rbacprivilegesalterfreezerevoke) - * 5.2.14.8.4 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines](#rqsrs-006rbacprivilegesalterfreezetableengines) - * 5.2.14.9 [Alter Fetch Partition](#alter-fetch-partition) - * 5.2.14.9.1 [RQ.SRS-006.RBAC.Privileges.AlterFetch](#rqsrs-006rbacprivilegesalterfetch) - * 5.2.14.9.2 [RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant](#rqsrs-006rbacprivilegesalterfetchgrant) - * 5.2.14.9.3 [RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke](#rqsrs-006rbacprivilegesalterfetchrevoke) - * 5.2.14.9.4 [RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines](#rqsrs-006rbacprivilegesalterfetchtableengines) - * 5.2.14.10 [Alter Move Partition](#alter-move-partition) - * 5.2.14.10.1 [RQ.SRS-006.RBAC.Privileges.AlterMove](#rqsrs-006rbacprivilegesaltermove) - * 5.2.14.10.2 [RQ.SRS-006.RBAC.Privileges.AlterMove.Grant](#rqsrs-006rbacprivilegesaltermovegrant) - * 5.2.14.10.3 [RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke](#rqsrs-006rbacprivilegesaltermoverevoke) - * 5.2.14.10.4 [RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines](#rqsrs-006rbacprivilegesaltermovetableengines) - * 5.2.15 [RQ.SRS-006.RBAC.Privileges.CreateTable](#rqsrs-006rbacprivilegescreatetable) - * 5.2.16 [RQ.SRS-006.RBAC.Privileges.CreateDatabase](#rqsrs-006rbacprivilegescreatedatabase) - * 5.2.17 [RQ.SRS-006.RBAC.Privileges.CreateDictionary](#rqsrs-006rbacprivilegescreatedictionary) - * 5.2.18 [RQ.SRS-006.RBAC.Privileges.CreateTemporaryTable](#rqsrs-006rbacprivilegescreatetemporarytable) - * 5.2.19 [RQ.SRS-006.RBAC.Privileges.AttachDatabase](#rqsrs-006rbacprivilegesattachdatabase) - * 5.2.20 [RQ.SRS-006.RBAC.Privileges.AttachDictionary](#rqsrs-006rbacprivilegesattachdictionary) - * 5.2.21 [RQ.SRS-006.RBAC.Privileges.AttachTemporaryTable](#rqsrs-006rbacprivilegesattachtemporarytable) - * 5.2.22 [RQ.SRS-006.RBAC.Privileges.AttachTable](#rqsrs-006rbacprivilegesattachtable) - * 5.2.23 [RQ.SRS-006.RBAC.Privileges.DropTable](#rqsrs-006rbacprivilegesdroptable) - * 5.2.24 [RQ.SRS-006.RBAC.Privileges.DropDatabase](#rqsrs-006rbacprivilegesdropdatabase) - * 5.2.25 [RQ.SRS-006.RBAC.Privileges.DropDictionary](#rqsrs-006rbacprivilegesdropdictionary) - * 5.2.26 [RQ.SRS-006.RBAC.Privileges.DetachTable](#rqsrs-006rbacprivilegesdetachtable) - * 5.2.27 [RQ.SRS-006.RBAC.Privileges.DetachView](#rqsrs-006rbacprivilegesdetachview) - * 5.2.28 [RQ.SRS-006.RBAC.Privileges.DetachDatabase](#rqsrs-006rbacprivilegesdetachdatabase) - * 5.2.29 [RQ.SRS-006.RBAC.Privileges.DetachDictionary](#rqsrs-006rbacprivilegesdetachdictionary) - * 5.2.30 [RQ.SRS-006.RBAC.Privileges.Truncate](#rqsrs-006rbacprivilegestruncate) - * 5.2.31 [RQ.SRS-006.RBAC.Privileges.Optimize](#rqsrs-006rbacprivilegesoptimize) - * 5.2.32 [RQ.SRS-006.RBAC.Privileges.KillQuery](#rqsrs-006rbacprivilegeskillquery) - * 5.2.33 [Kill Mutation](#kill-mutation) - * 5.2.33.1 [RQ.SRS-006.RBAC.Privileges.KillMutation](#rqsrs-006rbacprivilegeskillmutation) - * 5.2.33.2 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate](#rqsrs-006rbacprivilegeskillmutationalterupdate) - * 5.2.33.3 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete](#rqsrs-006rbacprivilegeskillmutationalterdelete) - * 5.2.33.4 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn](#rqsrs-006rbacprivilegeskillmutationalterdropcolumn) - * 5.2.34 [Show](#show) - * 5.2.34.1 [RQ.SRS-006.RBAC.ShowTables.Privilege](#rqsrs-006rbacshowtablesprivilege) - * 5.2.34.2 [RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege](#rqsrs-006rbacshowtablesrequiredprivilege) - * 5.2.34.3 [RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege](#rqsrs-006rbacexiststablerequiredprivilege) - * 5.2.34.4 [RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege](#rqsrs-006rbacchecktablerequiredprivilege) - * 5.2.34.5 [RQ.SRS-006.RBAC.ShowDatabases.Privilege](#rqsrs-006rbacshowdatabasesprivilege) - * 5.2.34.6 [RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege](#rqsrs-006rbacshowdatabasesrequiredprivilege) - * 5.2.34.7 [RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege](#rqsrs-006rbacshowcreatedatabaserequiredprivilege) - * 5.2.34.8 [RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege](#rqsrs-006rbacusedatabaserequiredprivilege) - * 5.2.34.9 [RQ.SRS-006.RBAC.ShowColumns.Privilege](#rqsrs-006rbacshowcolumnsprivilege) - * 5.2.34.10 [RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege](#rqsrs-006rbacshowcreatetablerequiredprivilege) - * 5.2.34.11 [RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege](#rqsrs-006rbacdescribetablerequiredprivilege) - * 5.2.34.12 [RQ.SRS-006.RBAC.ShowDictionaries.Privilege](#rqsrs-006rbacshowdictionariesprivilege) - * 5.2.34.13 [RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege](#rqsrs-006rbacshowdictionariesrequiredprivilege) - * 5.2.34.14 [RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege](#rqsrs-006rbacshowcreatedictionaryrequiredprivilege) - * 5.2.34.15 [RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege](#rqsrs-006rbacexistsdictionaryrequiredprivilege) - * 5.2.35 [Access Management](#access-management) - * 5.2.35.1 [RQ.SRS-006.RBAC.Privileges.CreateUser](#rqsrs-006rbacprivilegescreateuser) - * 5.2.35.2 [RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole](#rqsrs-006rbacprivilegescreateuserdefaultrole) - * 5.2.35.3 [RQ.SRS-006.RBAC.Privileges.AlterUser](#rqsrs-006rbacprivilegesalteruser) - * 5.2.35.4 [RQ.SRS-006.RBAC.Privileges.DropUser](#rqsrs-006rbacprivilegesdropuser) - * 5.2.35.5 [RQ.SRS-006.RBAC.Privileges.CreateRole](#rqsrs-006rbacprivilegescreaterole) - * 5.2.35.6 [RQ.SRS-006.RBAC.Privileges.AlterRole](#rqsrs-006rbacprivilegesalterrole) - * 5.2.35.7 [RQ.SRS-006.RBAC.Privileges.DropRole](#rqsrs-006rbacprivilegesdroprole) - * 5.2.35.8 [RQ.SRS-006.RBAC.Privileges.CreateRowPolicy](#rqsrs-006rbacprivilegescreaterowpolicy) - * 5.2.35.9 [RQ.SRS-006.RBAC.Privileges.AlterRowPolicy](#rqsrs-006rbacprivilegesalterrowpolicy) - * 5.2.35.10 [RQ.SRS-006.RBAC.Privileges.DropRowPolicy](#rqsrs-006rbacprivilegesdroprowpolicy) - * 5.2.35.11 [RQ.SRS-006.RBAC.Privileges.CreateQuota](#rqsrs-006rbacprivilegescreatequota) - * 5.2.35.12 [RQ.SRS-006.RBAC.Privileges.AlterQuota](#rqsrs-006rbacprivilegesalterquota) - * 5.2.35.13 [RQ.SRS-006.RBAC.Privileges.DropQuota](#rqsrs-006rbacprivilegesdropquota) - * 5.2.35.14 [RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile](#rqsrs-006rbacprivilegescreatesettingsprofile) - * 5.2.35.15 [RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile](#rqsrs-006rbacprivilegesaltersettingsprofile) - * 5.2.35.16 [RQ.SRS-006.RBAC.Privileges.DropSettingsProfile](#rqsrs-006rbacprivilegesdropsettingsprofile) - * 5.2.35.17 [RQ.SRS-006.RBAC.Privileges.RoleAdmin](#rqsrs-006rbacprivilegesroleadmin) - * 5.2.35.18 [Show Access](#show-access) - * 5.2.35.18.1 [RQ.SRS-006.RBAC.ShowUsers.Privilege](#rqsrs-006rbacshowusersprivilege) - * 5.2.35.18.2 [RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege](#rqsrs-006rbacshowusersrequiredprivilege) - * 5.2.35.18.3 [RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege](#rqsrs-006rbacshowcreateuserrequiredprivilege) - * 5.2.35.18.4 [RQ.SRS-006.RBAC.ShowRoles.Privilege](#rqsrs-006rbacshowrolesprivilege) - * 5.2.35.18.5 [RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege](#rqsrs-006rbacshowrolesrequiredprivilege) - * 5.2.35.18.6 [RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege](#rqsrs-006rbacshowcreaterolerequiredprivilege) - * 5.2.35.18.7 [RQ.SRS-006.RBAC.ShowRowPolicies.Privilege](#rqsrs-006rbacshowrowpoliciesprivilege) - * 5.2.35.18.8 [RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege](#rqsrs-006rbacshowrowpoliciesrequiredprivilege) - * 5.2.35.18.9 [RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege](#rqsrs-006rbacshowcreaterowpolicyrequiredprivilege) - * 5.2.35.18.10 [RQ.SRS-006.RBAC.ShowQuotas.Privilege](#rqsrs-006rbacshowquotasprivilege) - * 5.2.35.18.11 [RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege](#rqsrs-006rbacshowquotasrequiredprivilege) - * 5.2.35.18.12 [RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege](#rqsrs-006rbacshowcreatequotarequiredprivilege) - * 5.2.35.18.13 [RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege](#rqsrs-006rbacshowsettingsprofilesprivilege) - * 5.2.35.18.14 [RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege](#rqsrs-006rbacshowsettingsprofilesrequiredprivilege) - * 5.2.35.18.15 [RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege](#rqsrs-006rbacshowcreatesettingsprofilerequiredprivilege) - * 5.2.36 [dictGet](#dictget) - * 5.2.36.1 [RQ.SRS-006.RBAC.dictGet.Privilege](#rqsrs-006rbacdictgetprivilege) - * 5.2.36.2 [RQ.SRS-006.RBAC.dictGet.RequiredPrivilege](#rqsrs-006rbacdictgetrequiredprivilege) - * 5.2.36.3 [RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege](#rqsrs-006rbacdictgettyperequiredprivilege) - * 5.2.36.4 [RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege](#rqsrs-006rbacdictgetordefaultrequiredprivilege) - * 5.2.36.5 [RQ.SRS-006.RBAC.dictHas.RequiredPrivilege](#rqsrs-006rbacdicthasrequiredprivilege) - * 5.2.36.6 [RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege](#rqsrs-006rbacdictgethierarchyrequiredprivilege) - * 5.2.36.7 [RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege](#rqsrs-006rbacdictisinrequiredprivilege) - * 5.2.37 [Introspection](#introspection) - * 5.2.37.1 [RQ.SRS-006.RBAC.Privileges.Introspection](#rqsrs-006rbacprivilegesintrospection) - * 5.2.37.2 [RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine](#rqsrs-006rbacprivilegesintrospectionaddresstoline) - * 5.2.37.3 [RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol](#rqsrs-006rbacprivilegesintrospectionaddresstosymbol) - * 5.2.37.4 [RQ.SRS-006.RBAC.Privileges.Introspection.demangle](#rqsrs-006rbacprivilegesintrospectiondemangle) - * 5.2.38 [System](#system) - * 5.2.38.1 [RQ.SRS-006.RBAC.Privileges.System.Shutdown](#rqsrs-006rbacprivilegessystemshutdown) - * 5.2.38.2 [RQ.SRS-006.RBAC.Privileges.System.DropCache](#rqsrs-006rbacprivilegessystemdropcache) - * 5.2.38.3 [RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS](#rqsrs-006rbacprivilegessystemdropcachedns) - * 5.2.38.4 [RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark](#rqsrs-006rbacprivilegessystemdropcachemark) - * 5.2.38.5 [RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed](#rqsrs-006rbacprivilegessystemdropcacheuncompressed) - * 5.2.38.6 [RQ.SRS-006.RBAC.Privileges.System.Reload](#rqsrs-006rbacprivilegessystemreload) - * 5.2.38.7 [RQ.SRS-006.RBAC.Privileges.System.Reload.Config](#rqsrs-006rbacprivilegessystemreloadconfig) - * 5.2.38.8 [RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary](#rqsrs-006rbacprivilegessystemreloaddictionary) - * 5.2.38.9 [RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries](#rqsrs-006rbacprivilegessystemreloaddictionaries) - * 5.2.38.10 [RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries](#rqsrs-006rbacprivilegessystemreloadembeddeddictionaries) - * 5.2.38.11 [RQ.SRS-006.RBAC.Privileges.System.Merges](#rqsrs-006rbacprivilegessystemmerges) - * 5.2.38.12 [RQ.SRS-006.RBAC.Privileges.System.TTLMerges](#rqsrs-006rbacprivilegessystemttlmerges) - * 5.2.38.13 [RQ.SRS-006.RBAC.Privileges.System.Fetches](#rqsrs-006rbacprivilegessystemfetches) - * 5.2.38.14 [RQ.SRS-006.RBAC.Privileges.System.Moves](#rqsrs-006rbacprivilegessystemmoves) - * 5.2.38.15 [RQ.SRS-006.RBAC.Privileges.System.Sends](#rqsrs-006rbacprivilegessystemsends) - * 5.2.38.16 [RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed](#rqsrs-006rbacprivilegessystemsendsdistributed) - * 5.2.38.17 [RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated](#rqsrs-006rbacprivilegessystemsendsreplicated) - * 5.2.38.18 [RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues](#rqsrs-006rbacprivilegessystemreplicationqueues) - * 5.2.38.19 [RQ.SRS-006.RBAC.Privileges.System.SyncReplica](#rqsrs-006rbacprivilegessystemsyncreplica) - * 5.2.38.20 [RQ.SRS-006.RBAC.Privileges.System.RestartReplica](#rqsrs-006rbacprivilegessystemrestartreplica) - * 5.2.38.21 [RQ.SRS-006.RBAC.Privileges.System.Flush](#rqsrs-006rbacprivilegessystemflush) - * 5.2.38.22 [RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed](#rqsrs-006rbacprivilegessystemflushdistributed) - * 5.2.38.23 [RQ.SRS-006.RBAC.Privileges.System.Flush.Logs](#rqsrs-006rbacprivilegessystemflushlogs) - * 5.2.39 [Sources](#sources) - * 5.2.39.1 [RQ.SRS-006.RBAC.Privileges.Sources](#rqsrs-006rbacprivilegessources) - * 5.2.39.2 [RQ.SRS-006.RBAC.Privileges.Sources.File](#rqsrs-006rbacprivilegessourcesfile) - * 5.2.39.3 [RQ.SRS-006.RBAC.Privileges.Sources.URL](#rqsrs-006rbacprivilegessourcesurl) - * 5.2.39.4 [RQ.SRS-006.RBAC.Privileges.Sources.Remote](#rqsrs-006rbacprivilegessourcesremote) - * 5.2.39.5 [RQ.SRS-006.RBAC.Privileges.Sources.MySQL](#rqsrs-006rbacprivilegessourcesmysql) - * 5.2.39.6 [RQ.SRS-006.RBAC.Privileges.Sources.ODBC](#rqsrs-006rbacprivilegessourcesodbc) - * 5.2.39.7 [RQ.SRS-006.RBAC.Privileges.Sources.JDBC](#rqsrs-006rbacprivilegessourcesjdbc) - * 5.2.39.8 [RQ.SRS-006.RBAC.Privileges.Sources.HDFS](#rqsrs-006rbacprivilegessourceshdfs) - * 5.2.39.9 [RQ.SRS-006.RBAC.Privileges.Sources.S3](#rqsrs-006rbacprivilegessourcess3) - * 5.2.40 [RQ.SRS-006.RBAC.Privileges.GrantOption](#rqsrs-006rbacprivilegesgrantoption) - * 5.2.41 [RQ.SRS-006.RBAC.Privileges.All](#rqsrs-006rbacprivilegesall) - * 5.2.42 [RQ.SRS-006.RBAC.Privileges.AdminOption](#rqsrs-006rbacprivilegesadminoption) + * 5.2 [Login](#login) + * 5.2.1 [RQ.SRS-006.RBAC.Login](#rqsrs-006rbaclogin) + * 5.2.2 [RQ.SRS-006.RBAC.Login.DefaultUser](#rqsrs-006rbaclogindefaultuser) + * 5.3 [User](#user) + * 5.3.1 [RQ.SRS-006.RBAC.User](#rqsrs-006rbacuser) + * 5.3.2 [RQ.SRS-006.RBAC.User.Roles](#rqsrs-006rbacuserroles) + * 5.3.3 [RQ.SRS-006.RBAC.User.Privileges](#rqsrs-006rbacuserprivileges) + * 5.3.4 [RQ.SRS-006.RBAC.User.Variables](#rqsrs-006rbacuservariables) + * 5.3.5 [RQ.SRS-006.RBAC.User.Variables.Constraints](#rqsrs-006rbacuservariablesconstraints) + * 5.3.6 [RQ.SRS-006.RBAC.User.SettingsProfile](#rqsrs-006rbacusersettingsprofile) + * 5.3.7 [RQ.SRS-006.RBAC.User.Quotas](#rqsrs-006rbacuserquotas) + * 5.3.8 [RQ.SRS-006.RBAC.User.RowPolicies](#rqsrs-006rbacuserrowpolicies) + * 5.3.9 [RQ.SRS-006.RBAC.User.DefaultRole](#rqsrs-006rbacuserdefaultrole) + * 5.3.10 [RQ.SRS-006.RBAC.User.RoleSelection](#rqsrs-006rbacuserroleselection) + * 5.3.11 [RQ.SRS-006.RBAC.User.ShowCreate](#rqsrs-006rbacusershowcreate) + * 5.3.12 [RQ.SRS-006.RBAC.User.ShowPrivileges](#rqsrs-006rbacusershowprivileges) + * 5.3.13 [RQ.SRS-006.RBAC.User.Use.DefaultRole](#rqsrs-006rbacuserusedefaultrole) + * 5.3.14 [RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole](#rqsrs-006rbacuseruseallroleswhennodefaultrole) + * 5.3.15 [Create User](#create-user) + * 5.3.15.1 [RQ.SRS-006.RBAC.User.Create](#rqsrs-006rbacusercreate) + * 5.3.15.2 [RQ.SRS-006.RBAC.User.Create.IfNotExists](#rqsrs-006rbacusercreateifnotexists) + * 5.3.15.3 [RQ.SRS-006.RBAC.User.Create.Replace](#rqsrs-006rbacusercreatereplace) + * 5.3.15.4 [RQ.SRS-006.RBAC.User.Create.Password.NoPassword](#rqsrs-006rbacusercreatepasswordnopassword) + * 5.3.15.5 [RQ.SRS-006.RBAC.User.Create.Password.NoPassword.Login](#rqsrs-006rbacusercreatepasswordnopasswordlogin) + * 5.3.15.6 [RQ.SRS-006.RBAC.User.Create.Password.PlainText](#rqsrs-006rbacusercreatepasswordplaintext) + * 5.3.15.7 [RQ.SRS-006.RBAC.User.Create.Password.PlainText.Login](#rqsrs-006rbacusercreatepasswordplaintextlogin) + * 5.3.15.8 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Password](#rqsrs-006rbacusercreatepasswordsha256password) + * 5.3.15.9 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Password.Login](#rqsrs-006rbacusercreatepasswordsha256passwordlogin) + * 5.3.15.10 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash](#rqsrs-006rbacusercreatepasswordsha256hash) + * 5.3.15.11 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash.Login](#rqsrs-006rbacusercreatepasswordsha256hashlogin) + * 5.3.15.12 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password](#rqsrs-006rbacusercreatepassworddoublesha1password) + * 5.3.15.13 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password.Login](#rqsrs-006rbacusercreatepassworddoublesha1passwordlogin) + * 5.3.15.14 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash](#rqsrs-006rbacusercreatepassworddoublesha1hash) + * 5.3.15.15 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash.Login](#rqsrs-006rbacusercreatepassworddoublesha1hashlogin) + * 5.3.15.16 [RQ.SRS-006.RBAC.User.Create.Host.Name](#rqsrs-006rbacusercreatehostname) + * 5.3.15.17 [RQ.SRS-006.RBAC.User.Create.Host.Regexp](#rqsrs-006rbacusercreatehostregexp) + * 5.3.15.18 [RQ.SRS-006.RBAC.User.Create.Host.IP](#rqsrs-006rbacusercreatehostip) + * 5.3.15.19 [RQ.SRS-006.RBAC.User.Create.Host.Any](#rqsrs-006rbacusercreatehostany) + * 5.3.15.20 [RQ.SRS-006.RBAC.User.Create.Host.None](#rqsrs-006rbacusercreatehostnone) + * 5.3.15.21 [RQ.SRS-006.RBAC.User.Create.Host.Local](#rqsrs-006rbacusercreatehostlocal) + * 5.3.15.22 [RQ.SRS-006.RBAC.User.Create.Host.Like](#rqsrs-006rbacusercreatehostlike) + * 5.3.15.23 [RQ.SRS-006.RBAC.User.Create.Host.Default](#rqsrs-006rbacusercreatehostdefault) + * 5.3.15.24 [RQ.SRS-006.RBAC.User.Create.DefaultRole](#rqsrs-006rbacusercreatedefaultrole) + * 5.3.15.25 [RQ.SRS-006.RBAC.User.Create.DefaultRole.None](#rqsrs-006rbacusercreatedefaultrolenone) + * 5.3.15.26 [RQ.SRS-006.RBAC.User.Create.DefaultRole.All](#rqsrs-006rbacusercreatedefaultroleall) + * 5.3.15.27 [RQ.SRS-006.RBAC.User.Create.Settings](#rqsrs-006rbacusercreatesettings) + * 5.3.15.28 [RQ.SRS-006.RBAC.User.Create.OnCluster](#rqsrs-006rbacusercreateoncluster) + * 5.3.15.29 [RQ.SRS-006.RBAC.User.Create.Syntax](#rqsrs-006rbacusercreatesyntax) + * 5.3.16 [Alter User](#alter-user) + * 5.3.16.1 [RQ.SRS-006.RBAC.User.Alter](#rqsrs-006rbacuseralter) + * 5.3.16.2 [RQ.SRS-006.RBAC.User.Alter.OrderOfEvaluation](#rqsrs-006rbacuseralterorderofevaluation) + * 5.3.16.3 [RQ.SRS-006.RBAC.User.Alter.IfExists](#rqsrs-006rbacuseralterifexists) + * 5.3.16.4 [RQ.SRS-006.RBAC.User.Alter.Cluster](#rqsrs-006rbacuseraltercluster) + * 5.3.16.5 [RQ.SRS-006.RBAC.User.Alter.Rename](#rqsrs-006rbacuseralterrename) + * 5.3.16.6 [RQ.SRS-006.RBAC.User.Alter.Password.PlainText](#rqsrs-006rbacuseralterpasswordplaintext) + * 5.3.16.7 [RQ.SRS-006.RBAC.User.Alter.Password.Sha256Password](#rqsrs-006rbacuseralterpasswordsha256password) + * 5.3.16.8 [RQ.SRS-006.RBAC.User.Alter.Password.DoubleSha1Password](#rqsrs-006rbacuseralterpassworddoublesha1password) + * 5.3.16.9 [RQ.SRS-006.RBAC.User.Alter.Host.AddDrop](#rqsrs-006rbacuseralterhostadddrop) + * 5.3.16.10 [RQ.SRS-006.RBAC.User.Alter.Host.Local](#rqsrs-006rbacuseralterhostlocal) + * 5.3.16.11 [RQ.SRS-006.RBAC.User.Alter.Host.Name](#rqsrs-006rbacuseralterhostname) + * 5.3.16.12 [RQ.SRS-006.RBAC.User.Alter.Host.Regexp](#rqsrs-006rbacuseralterhostregexp) + * 5.3.16.13 [RQ.SRS-006.RBAC.User.Alter.Host.IP](#rqsrs-006rbacuseralterhostip) + * 5.3.16.14 [RQ.SRS-006.RBAC.User.Alter.Host.Like](#rqsrs-006rbacuseralterhostlike) + * 5.3.16.15 [RQ.SRS-006.RBAC.User.Alter.Host.Any](#rqsrs-006rbacuseralterhostany) + * 5.3.16.16 [RQ.SRS-006.RBAC.User.Alter.Host.None](#rqsrs-006rbacuseralterhostnone) + * 5.3.16.17 [RQ.SRS-006.RBAC.User.Alter.DefaultRole](#rqsrs-006rbacuseralterdefaultrole) + * 5.3.16.18 [RQ.SRS-006.RBAC.User.Alter.DefaultRole.All](#rqsrs-006rbacuseralterdefaultroleall) + * 5.3.16.19 [RQ.SRS-006.RBAC.User.Alter.DefaultRole.AllExcept](#rqsrs-006rbacuseralterdefaultroleallexcept) + * 5.3.16.20 [RQ.SRS-006.RBAC.User.Alter.Settings](#rqsrs-006rbacuseraltersettings) + * 5.3.16.21 [RQ.SRS-006.RBAC.User.Alter.Settings.Min](#rqsrs-006rbacuseraltersettingsmin) + * 5.3.16.22 [RQ.SRS-006.RBAC.User.Alter.Settings.Max](#rqsrs-006rbacuseraltersettingsmax) + * 5.3.16.23 [RQ.SRS-006.RBAC.User.Alter.Settings.Profile](#rqsrs-006rbacuseraltersettingsprofile) + * 5.3.16.24 [RQ.SRS-006.RBAC.User.Alter.Syntax](#rqsrs-006rbacuseraltersyntax) + * 5.3.17 [Show Create User](#show-create-user) + * 5.3.17.1 [RQ.SRS-006.RBAC.User.ShowCreateUser](#rqsrs-006rbacusershowcreateuser) + * 5.3.17.2 [RQ.SRS-006.RBAC.User.ShowCreateUser.For](#rqsrs-006rbacusershowcreateuserfor) + * 5.3.17.3 [RQ.SRS-006.RBAC.User.ShowCreateUser.Syntax](#rqsrs-006rbacusershowcreateusersyntax) + * 5.3.18 [Drop User](#drop-user) + * 5.3.18.1 [RQ.SRS-006.RBAC.User.Drop](#rqsrs-006rbacuserdrop) + * 5.3.18.2 [RQ.SRS-006.RBAC.User.Drop.IfExists](#rqsrs-006rbacuserdropifexists) + * 5.3.18.3 [RQ.SRS-006.RBAC.User.Drop.OnCluster](#rqsrs-006rbacuserdroponcluster) + * 5.3.18.4 [RQ.SRS-006.RBAC.User.Drop.Syntax](#rqsrs-006rbacuserdropsyntax) + * 5.4 [Role](#role) + * 5.4.1 [RQ.SRS-006.RBAC.Role](#rqsrs-006rbacrole) + * 5.4.2 [RQ.SRS-006.RBAC.Role.Privileges](#rqsrs-006rbacroleprivileges) + * 5.4.3 [RQ.SRS-006.RBAC.Role.Variables](#rqsrs-006rbacrolevariables) + * 5.4.4 [RQ.SRS-006.RBAC.Role.SettingsProfile](#rqsrs-006rbacrolesettingsprofile) + * 5.4.5 [RQ.SRS-006.RBAC.Role.Quotas](#rqsrs-006rbacrolequotas) + * 5.4.6 [RQ.SRS-006.RBAC.Role.RowPolicies](#rqsrs-006rbacrolerowpolicies) + * 5.4.7 [Create Role](#create-role) + * 5.4.7.1 [RQ.SRS-006.RBAC.Role.Create](#rqsrs-006rbacrolecreate) + * 5.4.7.2 [RQ.SRS-006.RBAC.Role.Create.IfNotExists](#rqsrs-006rbacrolecreateifnotexists) + * 5.4.7.3 [RQ.SRS-006.RBAC.Role.Create.Replace](#rqsrs-006rbacrolecreatereplace) + * 5.4.7.4 [RQ.SRS-006.RBAC.Role.Create.Settings](#rqsrs-006rbacrolecreatesettings) + * 5.4.7.5 [RQ.SRS-006.RBAC.Role.Create.Syntax](#rqsrs-006rbacrolecreatesyntax) + * 5.4.8 [Alter Role](#alter-role) + * 5.4.8.1 [RQ.SRS-006.RBAC.Role.Alter](#rqsrs-006rbacrolealter) + * 5.4.8.2 [RQ.SRS-006.RBAC.Role.Alter.IfExists](#rqsrs-006rbacrolealterifexists) + * 5.4.8.3 [RQ.SRS-006.RBAC.Role.Alter.Cluster](#rqsrs-006rbacrolealtercluster) + * 5.4.8.4 [RQ.SRS-006.RBAC.Role.Alter.Rename](#rqsrs-006rbacrolealterrename) + * 5.4.8.5 [RQ.SRS-006.RBAC.Role.Alter.Settings](#rqsrs-006rbacrolealtersettings) + * 5.4.8.6 [RQ.SRS-006.RBAC.Role.Alter.Syntax](#rqsrs-006rbacrolealtersyntax) + * 5.4.9 [Drop Role](#drop-role) + * 5.4.9.1 [RQ.SRS-006.RBAC.Role.Drop](#rqsrs-006rbacroledrop) + * 5.4.9.2 [RQ.SRS-006.RBAC.Role.Drop.IfExists](#rqsrs-006rbacroledropifexists) + * 5.4.9.3 [RQ.SRS-006.RBAC.Role.Drop.Cluster](#rqsrs-006rbacroledropcluster) + * 5.4.9.4 [RQ.SRS-006.RBAC.Role.Drop.Syntax](#rqsrs-006rbacroledropsyntax) + * 5.4.10 [Show Create Role](#show-create-role) + * 5.4.10.1 [RQ.SRS-006.RBAC.Role.ShowCreate](#rqsrs-006rbacroleshowcreate) + * 5.4.10.2 [RQ.SRS-006.RBAC.Role.ShowCreate.Syntax](#rqsrs-006rbacroleshowcreatesyntax) + * 5.5 [Partial Revokes](#partial-revokes) + * 5.5.1 [RQ.SRS-006.RBAC.PartialRevokes](#rqsrs-006rbacpartialrevokes) + * 5.5.2 [RQ.SRS-006.RBAC.PartialRevoke.Syntax](#rqsrs-006rbacpartialrevokesyntax) + * 5.6 [Settings Profile](#settings-profile) + * 5.6.1 [RQ.SRS-006.RBAC.SettingsProfile](#rqsrs-006rbacsettingsprofile) + * 5.6.2 [RQ.SRS-006.RBAC.SettingsProfile.Constraints](#rqsrs-006rbacsettingsprofileconstraints) + * 5.6.3 [Create Settings Profile](#create-settings-profile) + * 5.6.3.1 [RQ.SRS-006.RBAC.SettingsProfile.Create](#rqsrs-006rbacsettingsprofilecreate) + * 5.6.3.2 [RQ.SRS-006.RBAC.SettingsProfile.Create.IfNotExists](#rqsrs-006rbacsettingsprofilecreateifnotexists) + * 5.6.3.3 [RQ.SRS-006.RBAC.SettingsProfile.Create.Replace](#rqsrs-006rbacsettingsprofilecreatereplace) + * 5.6.3.4 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables](#rqsrs-006rbacsettingsprofilecreatevariables) + * 5.6.3.5 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Value](#rqsrs-006rbacsettingsprofilecreatevariablesvalue) + * 5.6.3.6 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Constraints](#rqsrs-006rbacsettingsprofilecreatevariablesconstraints) + * 5.6.3.7 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment](#rqsrs-006rbacsettingsprofilecreateassignment) + * 5.6.3.8 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.None](#rqsrs-006rbacsettingsprofilecreateassignmentnone) + * 5.6.3.9 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.All](#rqsrs-006rbacsettingsprofilecreateassignmentall) + * 5.6.3.10 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.AllExcept](#rqsrs-006rbacsettingsprofilecreateassignmentallexcept) + * 5.6.3.11 [RQ.SRS-006.RBAC.SettingsProfile.Create.Inherit](#rqsrs-006rbacsettingsprofilecreateinherit) + * 5.6.3.12 [RQ.SRS-006.RBAC.SettingsProfile.Create.OnCluster](#rqsrs-006rbacsettingsprofilecreateoncluster) + * 5.6.3.13 [RQ.SRS-006.RBAC.SettingsProfile.Create.Syntax](#rqsrs-006rbacsettingsprofilecreatesyntax) + * 5.6.4 [Alter Settings Profile](#alter-settings-profile) + * 5.6.4.1 [RQ.SRS-006.RBAC.SettingsProfile.Alter](#rqsrs-006rbacsettingsprofilealter) + * 5.6.4.2 [RQ.SRS-006.RBAC.SettingsProfile.Alter.IfExists](#rqsrs-006rbacsettingsprofilealterifexists) + * 5.6.4.3 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Rename](#rqsrs-006rbacsettingsprofilealterrename) + * 5.6.4.4 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables](#rqsrs-006rbacsettingsprofilealtervariables) + * 5.6.4.5 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Value](#rqsrs-006rbacsettingsprofilealtervariablesvalue) + * 5.6.4.6 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Constraints](#rqsrs-006rbacsettingsprofilealtervariablesconstraints) + * 5.6.4.7 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment](#rqsrs-006rbacsettingsprofilealterassignment) + * 5.6.4.8 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.None](#rqsrs-006rbacsettingsprofilealterassignmentnone) + * 5.6.4.9 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.All](#rqsrs-006rbacsettingsprofilealterassignmentall) + * 5.6.4.10 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.AllExcept](#rqsrs-006rbacsettingsprofilealterassignmentallexcept) + * 5.6.4.11 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.Inherit](#rqsrs-006rbacsettingsprofilealterassignmentinherit) + * 5.6.4.12 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.OnCluster](#rqsrs-006rbacsettingsprofilealterassignmentoncluster) + * 5.6.4.13 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Syntax](#rqsrs-006rbacsettingsprofilealtersyntax) + * 5.6.5 [Drop Settings Profile](#drop-settings-profile) + * 5.6.5.1 [RQ.SRS-006.RBAC.SettingsProfile.Drop](#rqsrs-006rbacsettingsprofiledrop) + * 5.6.5.2 [RQ.SRS-006.RBAC.SettingsProfile.Drop.IfExists](#rqsrs-006rbacsettingsprofiledropifexists) + * 5.6.5.3 [RQ.SRS-006.RBAC.SettingsProfile.Drop.OnCluster](#rqsrs-006rbacsettingsprofiledroponcluster) + * 5.6.5.4 [RQ.SRS-006.RBAC.SettingsProfile.Drop.Syntax](#rqsrs-006rbacsettingsprofiledropsyntax) + * 5.6.6 [Show Create Settings Profile](#show-create-settings-profile) + * 5.6.6.1 [RQ.SRS-006.RBAC.SettingsProfile.ShowCreateSettingsProfile](#rqsrs-006rbacsettingsprofileshowcreatesettingsprofile) + * 5.7 [Quotas](#quotas) + * 5.7.1 [RQ.SRS-006.RBAC.Quotas](#rqsrs-006rbacquotas) + * 5.7.2 [RQ.SRS-006.RBAC.Quotas.Keyed](#rqsrs-006rbacquotaskeyed) + * 5.7.3 [RQ.SRS-006.RBAC.Quotas.Queries](#rqsrs-006rbacquotasqueries) + * 5.7.4 [RQ.SRS-006.RBAC.Quotas.Errors](#rqsrs-006rbacquotaserrors) + * 5.7.5 [RQ.SRS-006.RBAC.Quotas.ResultRows](#rqsrs-006rbacquotasresultrows) + * 5.7.6 [RQ.SRS-006.RBAC.Quotas.ReadRows](#rqsrs-006rbacquotasreadrows) + * 5.7.7 [RQ.SRS-006.RBAC.Quotas.ResultBytes](#rqsrs-006rbacquotasresultbytes) + * 5.7.8 [RQ.SRS-006.RBAC.Quotas.ReadBytes](#rqsrs-006rbacquotasreadbytes) + * 5.7.9 [RQ.SRS-006.RBAC.Quotas.ExecutionTime](#rqsrs-006rbacquotasexecutiontime) + * 5.7.10 [Create Quotas](#create-quotas) + * 5.7.10.1 [RQ.SRS-006.RBAC.Quota.Create](#rqsrs-006rbacquotacreate) + * 5.7.10.2 [RQ.SRS-006.RBAC.Quota.Create.IfNotExists](#rqsrs-006rbacquotacreateifnotexists) + * 5.7.10.3 [RQ.SRS-006.RBAC.Quota.Create.Replace](#rqsrs-006rbacquotacreatereplace) + * 5.7.10.4 [RQ.SRS-006.RBAC.Quota.Create.Cluster](#rqsrs-006rbacquotacreatecluster) + * 5.7.10.5 [RQ.SRS-006.RBAC.Quota.Create.Interval](#rqsrs-006rbacquotacreateinterval) + * 5.7.10.6 [RQ.SRS-006.RBAC.Quota.Create.Interval.Randomized](#rqsrs-006rbacquotacreateintervalrandomized) + * 5.7.10.7 [RQ.SRS-006.RBAC.Quota.Create.Queries](#rqsrs-006rbacquotacreatequeries) + * 5.7.10.8 [RQ.SRS-006.RBAC.Quota.Create.Errors](#rqsrs-006rbacquotacreateerrors) + * 5.7.10.9 [RQ.SRS-006.RBAC.Quota.Create.ResultRows](#rqsrs-006rbacquotacreateresultrows) + * 5.7.10.10 [RQ.SRS-006.RBAC.Quota.Create.ReadRows](#rqsrs-006rbacquotacreatereadrows) + * 5.7.10.11 [RQ.SRS-006.RBAC.Quota.Create.ResultBytes](#rqsrs-006rbacquotacreateresultbytes) + * 5.7.10.12 [RQ.SRS-006.RBAC.Quota.Create.ReadBytes](#rqsrs-006rbacquotacreatereadbytes) + * 5.7.10.13 [RQ.SRS-006.RBAC.Quota.Create.ExecutionTime](#rqsrs-006rbacquotacreateexecutiontime) + * 5.7.10.14 [RQ.SRS-006.RBAC.Quota.Create.NoLimits](#rqsrs-006rbacquotacreatenolimits) + * 5.7.10.15 [RQ.SRS-006.RBAC.Quota.Create.TrackingOnly](#rqsrs-006rbacquotacreatetrackingonly) + * 5.7.10.16 [RQ.SRS-006.RBAC.Quota.Create.KeyedBy](#rqsrs-006rbacquotacreatekeyedby) + * 5.7.10.17 [RQ.SRS-006.RBAC.Quota.Create.KeyedByOptions](#rqsrs-006rbacquotacreatekeyedbyoptions) + * 5.7.10.18 [RQ.SRS-006.RBAC.Quota.Create.Assignment](#rqsrs-006rbacquotacreateassignment) + * 5.7.10.19 [RQ.SRS-006.RBAC.Quota.Create.Assignment.None](#rqsrs-006rbacquotacreateassignmentnone) + * 5.7.10.20 [RQ.SRS-006.RBAC.Quota.Create.Assignment.All](#rqsrs-006rbacquotacreateassignmentall) + * 5.7.10.21 [RQ.SRS-006.RBAC.Quota.Create.Assignment.Except](#rqsrs-006rbacquotacreateassignmentexcept) + * 5.7.10.22 [RQ.SRS-006.RBAC.Quota.Create.Syntax](#rqsrs-006rbacquotacreatesyntax) + * 5.7.11 [Alter Quota](#alter-quota) + * 5.7.11.1 [RQ.SRS-006.RBAC.Quota.Alter](#rqsrs-006rbacquotaalter) + * 5.7.11.2 [RQ.SRS-006.RBAC.Quota.Alter.IfExists](#rqsrs-006rbacquotaalterifexists) + * 5.7.11.3 [RQ.SRS-006.RBAC.Quota.Alter.Rename](#rqsrs-006rbacquotaalterrename) + * 5.7.11.4 [RQ.SRS-006.RBAC.Quota.Alter.Cluster](#rqsrs-006rbacquotaaltercluster) + * 5.7.11.5 [RQ.SRS-006.RBAC.Quota.Alter.Interval](#rqsrs-006rbacquotaalterinterval) + * 5.7.11.6 [RQ.SRS-006.RBAC.Quota.Alter.Interval.Randomized](#rqsrs-006rbacquotaalterintervalrandomized) + * 5.7.11.7 [RQ.SRS-006.RBAC.Quota.Alter.Queries](#rqsrs-006rbacquotaalterqueries) + * 5.7.11.8 [RQ.SRS-006.RBAC.Quota.Alter.Errors](#rqsrs-006rbacquotaaltererrors) + * 5.7.11.9 [RQ.SRS-006.RBAC.Quota.Alter.ResultRows](#rqsrs-006rbacquotaalterresultrows) + * 5.7.11.10 [RQ.SRS-006.RBAC.Quota.Alter.ReadRows](#rqsrs-006rbacquotaalterreadrows) + * 5.7.11.11 [RQ.SRS-006.RBAC.Quota.ALter.ResultBytes](#rqsrs-006rbacquotaalterresultbytes) + * 5.7.11.12 [RQ.SRS-006.RBAC.Quota.Alter.ReadBytes](#rqsrs-006rbacquotaalterreadbytes) + * 5.7.11.13 [RQ.SRS-006.RBAC.Quota.Alter.ExecutionTime](#rqsrs-006rbacquotaalterexecutiontime) + * 5.7.11.14 [RQ.SRS-006.RBAC.Quota.Alter.NoLimits](#rqsrs-006rbacquotaalternolimits) + * 5.7.11.15 [RQ.SRS-006.RBAC.Quota.Alter.TrackingOnly](#rqsrs-006rbacquotaaltertrackingonly) + * 5.7.11.16 [RQ.SRS-006.RBAC.Quota.Alter.KeyedBy](#rqsrs-006rbacquotaalterkeyedby) + * 5.7.11.17 [RQ.SRS-006.RBAC.Quota.Alter.KeyedByOptions](#rqsrs-006rbacquotaalterkeyedbyoptions) + * 5.7.11.18 [RQ.SRS-006.RBAC.Quota.Alter.Assignment](#rqsrs-006rbacquotaalterassignment) + * 5.7.11.19 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.None](#rqsrs-006rbacquotaalterassignmentnone) + * 5.7.11.20 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.All](#rqsrs-006rbacquotaalterassignmentall) + * 5.7.11.21 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.Except](#rqsrs-006rbacquotaalterassignmentexcept) + * 5.7.11.22 [RQ.SRS-006.RBAC.Quota.Alter.Syntax](#rqsrs-006rbacquotaaltersyntax) + * 5.7.12 [Drop Quota](#drop-quota) + * 5.7.12.1 [RQ.SRS-006.RBAC.Quota.Drop](#rqsrs-006rbacquotadrop) + * 5.7.12.2 [RQ.SRS-006.RBAC.Quota.Drop.IfExists](#rqsrs-006rbacquotadropifexists) + * 5.7.12.3 [RQ.SRS-006.RBAC.Quota.Drop.Cluster](#rqsrs-006rbacquotadropcluster) + * 5.7.12.4 [RQ.SRS-006.RBAC.Quota.Drop.Syntax](#rqsrs-006rbacquotadropsyntax) + * 5.7.13 [Show Quotas](#show-quotas) + * 5.7.13.1 [RQ.SRS-006.RBAC.Quota.ShowQuotas](#rqsrs-006rbacquotashowquotas) + * 5.7.13.2 [RQ.SRS-006.RBAC.Quota.ShowQuotas.IntoOutfile](#rqsrs-006rbacquotashowquotasintooutfile) + * 5.7.13.3 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Format](#rqsrs-006rbacquotashowquotasformat) + * 5.7.13.4 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Settings](#rqsrs-006rbacquotashowquotassettings) + * 5.7.13.5 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Syntax](#rqsrs-006rbacquotashowquotassyntax) + * 5.7.14 [Show Create Quota](#show-create-quota) + * 5.7.14.1 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Name](#rqsrs-006rbacquotashowcreatequotaname) + * 5.7.14.2 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Current](#rqsrs-006rbacquotashowcreatequotacurrent) + * 5.7.14.3 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Syntax](#rqsrs-006rbacquotashowcreatequotasyntax) + * 5.8 [Row Policy](#row-policy) + * 5.8.1 [RQ.SRS-006.RBAC.RowPolicy](#rqsrs-006rbacrowpolicy) + * 5.8.2 [RQ.SRS-006.RBAC.RowPolicy.Condition](#rqsrs-006rbacrowpolicycondition) + * 5.8.3 [RQ.SRS-006.RBAC.RowPolicy.Restriction](#rqsrs-006rbacrowpolicyrestriction) + * 5.8.4 [RQ.SRS-006.RBAC.RowPolicy.Nesting](#rqsrs-006rbacrowpolicynesting) + * 5.8.5 [Create Row Policy](#create-row-policy) + * 5.8.5.1 [RQ.SRS-006.RBAC.RowPolicy.Create](#rqsrs-006rbacrowpolicycreate) + * 5.8.5.2 [RQ.SRS-006.RBAC.RowPolicy.Create.IfNotExists](#rqsrs-006rbacrowpolicycreateifnotexists) + * 5.8.5.3 [RQ.SRS-006.RBAC.RowPolicy.Create.Replace](#rqsrs-006rbacrowpolicycreatereplace) + * 5.8.5.4 [RQ.SRS-006.RBAC.RowPolicy.Create.OnCluster](#rqsrs-006rbacrowpolicycreateoncluster) + * 5.8.5.5 [RQ.SRS-006.RBAC.RowPolicy.Create.On](#rqsrs-006rbacrowpolicycreateon) + * 5.8.5.6 [RQ.SRS-006.RBAC.RowPolicy.Create.Access](#rqsrs-006rbacrowpolicycreateaccess) + * 5.8.5.7 [RQ.SRS-006.RBAC.RowPolicy.Create.Access.Permissive](#rqsrs-006rbacrowpolicycreateaccesspermissive) + * 5.8.5.8 [RQ.SRS-006.RBAC.RowPolicy.Create.Access.Restrictive](#rqsrs-006rbacrowpolicycreateaccessrestrictive) + * 5.8.5.9 [RQ.SRS-006.RBAC.RowPolicy.Create.ForSelect](#rqsrs-006rbacrowpolicycreateforselect) + * 5.8.5.10 [RQ.SRS-006.RBAC.RowPolicy.Create.Condition](#rqsrs-006rbacrowpolicycreatecondition) + * 5.8.5.11 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment](#rqsrs-006rbacrowpolicycreateassignment) + * 5.8.5.12 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.None](#rqsrs-006rbacrowpolicycreateassignmentnone) + * 5.8.5.13 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.All](#rqsrs-006rbacrowpolicycreateassignmentall) + * 5.8.5.14 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.AllExcept](#rqsrs-006rbacrowpolicycreateassignmentallexcept) + * 5.8.5.15 [RQ.SRS-006.RBAC.RowPolicy.Create.Syntax](#rqsrs-006rbacrowpolicycreatesyntax) + * 5.8.6 [Alter Row Policy](#alter-row-policy) + * 5.8.6.1 [RQ.SRS-006.RBAC.RowPolicy.Alter](#rqsrs-006rbacrowpolicyalter) + * 5.8.6.2 [RQ.SRS-006.RBAC.RowPolicy.Alter.IfExists](#rqsrs-006rbacrowpolicyalterifexists) + * 5.8.6.3 [RQ.SRS-006.RBAC.RowPolicy.Alter.ForSelect](#rqsrs-006rbacrowpolicyalterforselect) + * 5.8.6.4 [RQ.SRS-006.RBAC.RowPolicy.Alter.OnCluster](#rqsrs-006rbacrowpolicyalteroncluster) + * 5.8.6.5 [RQ.SRS-006.RBAC.RowPolicy.Alter.On](#rqsrs-006rbacrowpolicyalteron) + * 5.8.6.6 [RQ.SRS-006.RBAC.RowPolicy.Alter.Rename](#rqsrs-006rbacrowpolicyalterrename) + * 5.8.6.7 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access](#rqsrs-006rbacrowpolicyalteraccess) + * 5.8.6.8 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Permissive](#rqsrs-006rbacrowpolicyalteraccesspermissive) + * 5.8.6.9 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Restrictive](#rqsrs-006rbacrowpolicyalteraccessrestrictive) + * 5.8.6.10 [RQ.SRS-006.RBAC.RowPolicy.Alter.Condition](#rqsrs-006rbacrowpolicyaltercondition) + * 5.8.6.11 [RQ.SRS-006.RBAC.RowPolicy.Alter.Condition.None](#rqsrs-006rbacrowpolicyalterconditionnone) + * 5.8.6.12 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment](#rqsrs-006rbacrowpolicyalterassignment) + * 5.8.6.13 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.None](#rqsrs-006rbacrowpolicyalterassignmentnone) + * 5.8.6.14 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.All](#rqsrs-006rbacrowpolicyalterassignmentall) + * 5.8.6.15 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.AllExcept](#rqsrs-006rbacrowpolicyalterassignmentallexcept) + * 5.8.6.16 [RQ.SRS-006.RBAC.RowPolicy.Alter.Syntax](#rqsrs-006rbacrowpolicyaltersyntax) + * 5.8.7 [Drop Row Policy](#drop-row-policy) + * 5.8.7.1 [RQ.SRS-006.RBAC.RowPolicy.Drop](#rqsrs-006rbacrowpolicydrop) + * 5.8.7.2 [RQ.SRS-006.RBAC.RowPolicy.Drop.IfExists](#rqsrs-006rbacrowpolicydropifexists) + * 5.8.7.3 [RQ.SRS-006.RBAC.RowPolicy.Drop.On](#rqsrs-006rbacrowpolicydropon) + * 5.8.7.4 [RQ.SRS-006.RBAC.RowPolicy.Drop.OnCluster](#rqsrs-006rbacrowpolicydroponcluster) + * 5.8.7.5 [RQ.SRS-006.RBAC.RowPolicy.Drop.Syntax](#rqsrs-006rbacrowpolicydropsyntax) + * 5.8.8 [Show Create Row Policy](#show-create-row-policy) + * 5.8.8.1 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy](#rqsrs-006rbacrowpolicyshowcreaterowpolicy) + * 5.8.8.2 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.On](#rqsrs-006rbacrowpolicyshowcreaterowpolicyon) + * 5.8.8.3 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.Syntax](#rqsrs-006rbacrowpolicyshowcreaterowpolicysyntax) + * 5.8.8.4 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies](#rqsrs-006rbacrowpolicyshowrowpolicies) + * 5.8.8.5 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.On](#rqsrs-006rbacrowpolicyshowrowpolicieson) + * 5.8.8.6 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.Syntax](#rqsrs-006rbacrowpolicyshowrowpoliciessyntax) + * 5.9 [Set Default Role](#set-default-role) + * 5.9.1 [RQ.SRS-006.RBAC.SetDefaultRole](#rqsrs-006rbacsetdefaultrole) + * 5.9.2 [RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser](#rqsrs-006rbacsetdefaultrolecurrentuser) + * 5.9.3 [RQ.SRS-006.RBAC.SetDefaultRole.All](#rqsrs-006rbacsetdefaultroleall) + * 5.9.4 [RQ.SRS-006.RBAC.SetDefaultRole.AllExcept](#rqsrs-006rbacsetdefaultroleallexcept) + * 5.9.5 [RQ.SRS-006.RBAC.SetDefaultRole.None](#rqsrs-006rbacsetdefaultrolenone) + * 5.9.6 [RQ.SRS-006.RBAC.SetDefaultRole.Syntax](#rqsrs-006rbacsetdefaultrolesyntax) + * 5.10 [Set Role](#set-role) + * 5.10.1 [RQ.SRS-006.RBAC.SetRole](#rqsrs-006rbacsetrole) + * 5.10.2 [RQ.SRS-006.RBAC.SetRole.Default](#rqsrs-006rbacsetroledefault) + * 5.10.3 [RQ.SRS-006.RBAC.SetRole.None](#rqsrs-006rbacsetrolenone) + * 5.10.4 [RQ.SRS-006.RBAC.SetRole.All](#rqsrs-006rbacsetroleall) + * 5.10.5 [RQ.SRS-006.RBAC.SetRole.AllExcept](#rqsrs-006rbacsetroleallexcept) + * 5.10.6 [RQ.SRS-006.RBAC.SetRole.Syntax](#rqsrs-006rbacsetrolesyntax) + * 5.11 [Grant](#grant) + * 5.11.1 [RQ.SRS-006.RBAC.Grant.Privilege.To](#rqsrs-006rbacgrantprivilegeto) + * 5.11.2 [RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser](#rqsrs-006rbacgrantprivilegetocurrentuser) + * 5.11.3 [RQ.SRS-006.RBAC.Grant.Privilege.Select](#rqsrs-006rbacgrantprivilegeselect) + * 5.11.4 [RQ.SRS-006.RBAC.Grant.Privilege.Insert](#rqsrs-006rbacgrantprivilegeinsert) + * 5.11.5 [RQ.SRS-006.RBAC.Grant.Privilege.Alter](#rqsrs-006rbacgrantprivilegealter) + * 5.11.6 [RQ.SRS-006.RBAC.Grant.Privilege.Create](#rqsrs-006rbacgrantprivilegecreate) + * 5.11.7 [RQ.SRS-006.RBAC.Grant.Privilege.Drop](#rqsrs-006rbacgrantprivilegedrop) + * 5.11.8 [RQ.SRS-006.RBAC.Grant.Privilege.Truncate](#rqsrs-006rbacgrantprivilegetruncate) + * 5.11.9 [RQ.SRS-006.RBAC.Grant.Privilege.Optimize](#rqsrs-006rbacgrantprivilegeoptimize) + * 5.11.10 [RQ.SRS-006.RBAC.Grant.Privilege.Show](#rqsrs-006rbacgrantprivilegeshow) + * 5.11.11 [RQ.SRS-006.RBAC.Grant.Privilege.KillQuery](#rqsrs-006rbacgrantprivilegekillquery) + * 5.11.12 [RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement](#rqsrs-006rbacgrantprivilegeaccessmanagement) + * 5.11.13 [RQ.SRS-006.RBAC.Grant.Privilege.System](#rqsrs-006rbacgrantprivilegesystem) + * 5.11.14 [RQ.SRS-006.RBAC.Grant.Privilege.Introspection](#rqsrs-006rbacgrantprivilegeintrospection) + * 5.11.15 [RQ.SRS-006.RBAC.Grant.Privilege.Sources](#rqsrs-006rbacgrantprivilegesources) + * 5.11.16 [RQ.SRS-006.RBAC.Grant.Privilege.DictGet](#rqsrs-006rbacgrantprivilegedictget) + * 5.11.17 [RQ.SRS-006.RBAC.Grant.Privilege.None](#rqsrs-006rbacgrantprivilegenone) + * 5.11.18 [RQ.SRS-006.RBAC.Grant.Privilege.All](#rqsrs-006rbacgrantprivilegeall) + * 5.11.19 [RQ.SRS-006.RBAC.Grant.Privilege.GrantOption](#rqsrs-006rbacgrantprivilegegrantoption) + * 5.11.20 [RQ.SRS-006.RBAC.Grant.Privilege.On](#rqsrs-006rbacgrantprivilegeon) + * 5.11.21 [RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns](#rqsrs-006rbacgrantprivilegeprivilegecolumns) + * 5.11.22 [RQ.SRS-006.RBAC.Grant.Privilege.OnCluster](#rqsrs-006rbacgrantprivilegeoncluster) + * 5.11.23 [RQ.SRS-006.RBAC.Grant.Privilege.Syntax](#rqsrs-006rbacgrantprivilegesyntax) + * 5.12 [Revoke](#revoke) + * 5.12.1 [RQ.SRS-006.RBAC.Revoke.Privilege.Cluster](#rqsrs-006rbacrevokeprivilegecluster) + * 5.12.2 [RQ.SRS-006.RBAC.Revoke.Privilege.Select](#rqsrs-006rbacrevokeprivilegeselect) + * 5.12.3 [RQ.SRS-006.RBAC.Revoke.Privilege.Insert](#rqsrs-006rbacrevokeprivilegeinsert) + * 5.12.4 [RQ.SRS-006.RBAC.Revoke.Privilege.Alter](#rqsrs-006rbacrevokeprivilegealter) + * 5.12.5 [RQ.SRS-006.RBAC.Revoke.Privilege.Create](#rqsrs-006rbacrevokeprivilegecreate) + * 5.12.6 [RQ.SRS-006.RBAC.Revoke.Privilege.Drop](#rqsrs-006rbacrevokeprivilegedrop) + * 5.12.7 [RQ.SRS-006.RBAC.Revoke.Privilege.Truncate](#rqsrs-006rbacrevokeprivilegetruncate) + * 5.12.8 [RQ.SRS-006.RBAC.Revoke.Privilege.Optimize](#rqsrs-006rbacrevokeprivilegeoptimize) + * 5.12.9 [RQ.SRS-006.RBAC.Revoke.Privilege.Show](#rqsrs-006rbacrevokeprivilegeshow) + * 5.12.10 [RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery](#rqsrs-006rbacrevokeprivilegekillquery) + * 5.12.11 [RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement](#rqsrs-006rbacrevokeprivilegeaccessmanagement) + * 5.12.12 [RQ.SRS-006.RBAC.Revoke.Privilege.System](#rqsrs-006rbacrevokeprivilegesystem) + * 5.12.13 [RQ.SRS-006.RBAC.Revoke.Privilege.Introspection](#rqsrs-006rbacrevokeprivilegeintrospection) + * 5.12.14 [RQ.SRS-006.RBAC.Revoke.Privilege.Sources](#rqsrs-006rbacrevokeprivilegesources) + * 5.12.15 [RQ.SRS-006.RBAC.Revoke.Privilege.DictGet](#rqsrs-006rbacrevokeprivilegedictget) + * 5.12.16 [RQ.SRS-006.RBAC.Revoke.Privilege.PrivilegeColumns](#rqsrs-006rbacrevokeprivilegeprivilegecolumns) + * 5.12.17 [RQ.SRS-006.RBAC.Revoke.Privilege.Multiple](#rqsrs-006rbacrevokeprivilegemultiple) + * 5.12.18 [RQ.SRS-006.RBAC.Revoke.Privilege.All](#rqsrs-006rbacrevokeprivilegeall) + * 5.12.19 [RQ.SRS-006.RBAC.Revoke.Privilege.None](#rqsrs-006rbacrevokeprivilegenone) + * 5.12.20 [RQ.SRS-006.RBAC.Revoke.Privilege.On](#rqsrs-006rbacrevokeprivilegeon) + * 5.12.21 [RQ.SRS-006.RBAC.Revoke.Privilege.From](#rqsrs-006rbacrevokeprivilegefrom) + * 5.12.22 [RQ.SRS-006.RBAC.Revoke.Privilege.Syntax](#rqsrs-006rbacrevokeprivilegesyntax) + * 5.13 [Grant Role](#grant-role) + * 5.13.1 [RQ.SRS-006.RBAC.Grant.Role](#rqsrs-006rbacgrantrole) + * 5.13.2 [RQ.SRS-006.RBAC.Grant.Role.CurrentUser](#rqsrs-006rbacgrantrolecurrentuser) + * 5.13.3 [RQ.SRS-006.RBAC.Grant.Role.AdminOption](#rqsrs-006rbacgrantroleadminoption) + * 5.13.4 [RQ.SRS-006.RBAC.Grant.Role.OnCluster](#rqsrs-006rbacgrantroleoncluster) + * 5.13.5 [RQ.SRS-006.RBAC.Grant.Role.Syntax](#rqsrs-006rbacgrantrolesyntax) + * 5.14 [Revoke Role](#revoke-role) + * 5.14.1 [RQ.SRS-006.RBAC.Revoke.Role](#rqsrs-006rbacrevokerole) + * 5.14.2 [RQ.SRS-006.RBAC.Revoke.Role.Keywords](#rqsrs-006rbacrevokerolekeywords) + * 5.14.3 [RQ.SRS-006.RBAC.Revoke.Role.Cluster](#rqsrs-006rbacrevokerolecluster) + * 5.14.4 [RQ.SRS-006.RBAC.Revoke.AdminOption](#rqsrs-006rbacrevokeadminoption) + * 5.14.5 [RQ.SRS-006.RBAC.Revoke.Role.Syntax](#rqsrs-006rbacrevokerolesyntax) + * 5.15 [Show Grants](#show-grants) + * 5.15.1 [RQ.SRS-006.RBAC.Show.Grants](#rqsrs-006rbacshowgrants) + * 5.15.2 [RQ.SRS-006.RBAC.Show.Grants.For](#rqsrs-006rbacshowgrantsfor) + * 5.15.3 [RQ.SRS-006.RBAC.Show.Grants.Syntax](#rqsrs-006rbacshowgrantssyntax) + * 5.16 [Table Privileges](#table-privileges) + * 5.16.1 [RQ.SRS-006.RBAC.Table.PublicTables](#rqsrs-006rbactablepublictables) + * 5.16.2 [RQ.SRS-006.RBAC.Table.SensitiveTables](#rqsrs-006rbactablesensitivetables) + * 5.17 [Distributed Tables](#distributed-tables) + * 5.17.1 [RQ.SRS-006.RBAC.DistributedTable.Create](#rqsrs-006rbacdistributedtablecreate) + * 5.17.2 [RQ.SRS-006.RBAC.DistributedTable.Select](#rqsrs-006rbacdistributedtableselect) + * 5.17.3 [RQ.SRS-006.RBAC.DistributedTable.Insert](#rqsrs-006rbacdistributedtableinsert) + * 5.17.4 [RQ.SRS-006.RBAC.DistributedTable.SpecialTables](#rqsrs-006rbacdistributedtablespecialtables) + * 5.17.5 [RQ.SRS-006.RBAC.DistributedTable.LocalUser](#rqsrs-006rbacdistributedtablelocaluser) + * 5.17.6 [RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges](#rqsrs-006rbacdistributedtablesameuserdifferentnodesdifferentprivileges) + * 5.18 [Views](#views) + * 5.18.1 [View](#view) + * 5.18.1.1 [RQ.SRS-006.RBAC.View](#rqsrs-006rbacview) + * 5.18.1.2 [RQ.SRS-006.RBAC.View.Create](#rqsrs-006rbacviewcreate) + * 5.18.1.3 [RQ.SRS-006.RBAC.View.Select](#rqsrs-006rbacviewselect) + * 5.18.1.4 [RQ.SRS-006.RBAC.View.Drop](#rqsrs-006rbacviewdrop) + * 5.18.2 [Materialized View](#materialized-view) + * 5.18.2.1 [RQ.SRS-006.RBAC.MaterializedView](#rqsrs-006rbacmaterializedview) + * 5.18.2.2 [RQ.SRS-006.RBAC.MaterializedView.Create](#rqsrs-006rbacmaterializedviewcreate) + * 5.18.2.3 [RQ.SRS-006.RBAC.MaterializedView.Select](#rqsrs-006rbacmaterializedviewselect) + * 5.18.2.4 [RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable](#rqsrs-006rbacmaterializedviewselecttargettable) + * 5.18.2.5 [RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable](#rqsrs-006rbacmaterializedviewselectsourcetable) + * 5.18.2.6 [RQ.SRS-006.RBAC.MaterializedView.Drop](#rqsrs-006rbacmaterializedviewdrop) + * 5.18.2.7 [RQ.SRS-006.RBAC.MaterializedView.ModifyQuery](#rqsrs-006rbacmaterializedviewmodifyquery) + * 5.18.2.8 [RQ.SRS-006.RBAC.MaterializedView.Insert](#rqsrs-006rbacmaterializedviewinsert) + * 5.18.2.9 [RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable](#rqsrs-006rbacmaterializedviewinsertsourcetable) + * 5.18.2.10 [RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable](#rqsrs-006rbacmaterializedviewinserttargettable) + * 5.18.3 [Live View](#live-view) + * 5.18.3.1 [RQ.SRS-006.RBAC.LiveView](#rqsrs-006rbacliveview) + * 5.18.3.2 [RQ.SRS-006.RBAC.LiveView.Create](#rqsrs-006rbacliveviewcreate) + * 5.18.3.3 [RQ.SRS-006.RBAC.LiveView.Select](#rqsrs-006rbacliveviewselect) + * 5.18.3.4 [RQ.SRS-006.RBAC.LiveView.Drop](#rqsrs-006rbacliveviewdrop) + * 5.18.3.5 [RQ.SRS-006.RBAC.LiveView.Refresh](#rqsrs-006rbacliveviewrefresh) + * 5.19 [Select](#select) + * 5.19.1 [RQ.SRS-006.RBAC.Select](#rqsrs-006rbacselect) + * 5.19.2 [RQ.SRS-006.RBAC.Select.Column](#rqsrs-006rbacselectcolumn) + * 5.19.3 [RQ.SRS-006.RBAC.Select.Cluster](#rqsrs-006rbacselectcluster) + * 5.19.4 [RQ.SRS-006.RBAC.Select.TableEngines](#rqsrs-006rbacselecttableengines) + * 5.20 [Insert](#insert) + * 5.20.1 [RQ.SRS-006.RBAC.Insert](#rqsrs-006rbacinsert) + * 5.20.2 [RQ.SRS-006.RBAC.Insert.Column](#rqsrs-006rbacinsertcolumn) + * 5.20.3 [RQ.SRS-006.RBAC.Insert.Cluster](#rqsrs-006rbacinsertcluster) + * 5.20.4 [RQ.SRS-006.RBAC.Insert.TableEngines](#rqsrs-006rbacinserttableengines) + * 5.21 [Alter](#alter) + * 5.21.1 [Alter Column](#alter-column) + * 5.21.1.1 [RQ.SRS-006.RBAC.Privileges.AlterColumn](#rqsrs-006rbacprivilegesaltercolumn) + * 5.21.1.2 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant](#rqsrs-006rbacprivilegesaltercolumngrant) + * 5.21.1.3 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke](#rqsrs-006rbacprivilegesaltercolumnrevoke) + * 5.21.1.4 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Column](#rqsrs-006rbacprivilegesaltercolumncolumn) + * 5.21.1.5 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster](#rqsrs-006rbacprivilegesaltercolumncluster) + * 5.21.1.6 [RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines](#rqsrs-006rbacprivilegesaltercolumntableengines) + * 5.21.2 [Alter Index](#alter-index) + * 5.21.2.1 [RQ.SRS-006.RBAC.Privileges.AlterIndex](#rqsrs-006rbacprivilegesalterindex) + * 5.21.2.2 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant](#rqsrs-006rbacprivilegesalterindexgrant) + * 5.21.2.3 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke](#rqsrs-006rbacprivilegesalterindexrevoke) + * 5.21.2.4 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster](#rqsrs-006rbacprivilegesalterindexcluster) + * 5.21.2.5 [RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines](#rqsrs-006rbacprivilegesalterindextableengines) + * 5.21.3 [Alter Constraint](#alter-constraint) + * 5.21.3.1 [RQ.SRS-006.RBAC.Privileges.AlterConstraint](#rqsrs-006rbacprivilegesalterconstraint) + * 5.21.3.2 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant](#rqsrs-006rbacprivilegesalterconstraintgrant) + * 5.21.3.3 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke](#rqsrs-006rbacprivilegesalterconstraintrevoke) + * 5.21.3.4 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster](#rqsrs-006rbacprivilegesalterconstraintcluster) + * 5.21.3.5 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines](#rqsrs-006rbacprivilegesalterconstrainttableengines) + * 5.21.4 [Alter TTL](#alter-ttl) + * 5.21.4.1 [RQ.SRS-006.RBAC.Privileges.AlterTTL](#rqsrs-006rbacprivilegesalterttl) + * 5.21.4.2 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant](#rqsrs-006rbacprivilegesalterttlgrant) + * 5.21.4.3 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke](#rqsrs-006rbacprivilegesalterttlrevoke) + * 5.21.4.4 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster](#rqsrs-006rbacprivilegesalterttlcluster) + * 5.21.4.5 [RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines](#rqsrs-006rbacprivilegesalterttltableengines) + * 5.21.5 [Alter Settings](#alter-settings) + * 5.21.5.1 [RQ.SRS-006.RBAC.Privileges.AlterSettings](#rqsrs-006rbacprivilegesaltersettings) + * 5.21.5.2 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant](#rqsrs-006rbacprivilegesaltersettingsgrant) + * 5.21.5.3 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke](#rqsrs-006rbacprivilegesaltersettingsrevoke) + * 5.21.5.4 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster](#rqsrs-006rbacprivilegesaltersettingscluster) + * 5.21.5.5 [RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines](#rqsrs-006rbacprivilegesaltersettingstableengines) + * 5.21.6 [Alter Update](#alter-update) + * 5.21.6.1 [RQ.SRS-006.RBAC.Privileges.AlterUpdate](#rqsrs-006rbacprivilegesalterupdate) + * 5.21.6.2 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant](#rqsrs-006rbacprivilegesalterupdategrant) + * 5.21.6.3 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke](#rqsrs-006rbacprivilegesalterupdaterevoke) + * 5.21.6.4 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines](#rqsrs-006rbacprivilegesalterupdatetableengines) + * 5.21.7 [Alter Delete](#alter-delete) + * 5.21.7.1 [RQ.SRS-006.RBAC.Privileges.AlterDelete](#rqsrs-006rbacprivilegesalterdelete) + * 5.21.7.2 [RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant](#rqsrs-006rbacprivilegesalterdeletegrant) + * 5.21.7.3 [RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke](#rqsrs-006rbacprivilegesalterdeleterevoke) + * 5.21.7.4 [RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines](#rqsrs-006rbacprivilegesalterdeletetableengines) + * 5.21.8 [Alter Freeze Partition](#alter-freeze-partition) + * 5.21.8.1 [RQ.SRS-006.RBAC.Privileges.AlterFreeze](#rqsrs-006rbacprivilegesalterfreeze) + * 5.21.8.2 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant](#rqsrs-006rbacprivilegesalterfreezegrant) + * 5.21.8.3 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke](#rqsrs-006rbacprivilegesalterfreezerevoke) + * 5.21.8.4 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines](#rqsrs-006rbacprivilegesalterfreezetableengines) + * 5.21.9 [Alter Fetch Partition](#alter-fetch-partition) + * 5.21.9.1 [RQ.SRS-006.RBAC.Privileges.AlterFetch](#rqsrs-006rbacprivilegesalterfetch) + * 5.21.9.2 [RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant](#rqsrs-006rbacprivilegesalterfetchgrant) + * 5.21.9.3 [RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke](#rqsrs-006rbacprivilegesalterfetchrevoke) + * 5.21.9.4 [RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines](#rqsrs-006rbacprivilegesalterfetchtableengines) + * 5.21.10 [Alter Move Partition](#alter-move-partition) + * 5.21.10.1 [RQ.SRS-006.RBAC.Privileges.AlterMove](#rqsrs-006rbacprivilegesaltermove) + * 5.21.10.2 [RQ.SRS-006.RBAC.Privileges.AlterMove.Grant](#rqsrs-006rbacprivilegesaltermovegrant) + * 5.21.10.3 [RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke](#rqsrs-006rbacprivilegesaltermoverevoke) + * 5.21.10.4 [RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines](#rqsrs-006rbacprivilegesaltermovetableengines) + * 5.22 [Create](#create) + * 5.22.1 [RQ.SRS-006.RBAC.Privileges.CreateTable](#rqsrs-006rbacprivilegescreatetable) + * 5.22.2 [RQ.SRS-006.RBAC.Privileges.CreateDatabase](#rqsrs-006rbacprivilegescreatedatabase) + * 5.22.3 [RQ.SRS-006.RBAC.Privileges.CreateDictionary](#rqsrs-006rbacprivilegescreatedictionary) + * 5.22.4 [RQ.SRS-006.RBAC.Privileges.CreateTemporaryTable](#rqsrs-006rbacprivilegescreatetemporarytable) + * 5.23 [Attach](#attach) + * 5.23.1 [RQ.SRS-006.RBAC.Privileges.AttachDatabase](#rqsrs-006rbacprivilegesattachdatabase) + * 5.23.2 [RQ.SRS-006.RBAC.Privileges.AttachDictionary](#rqsrs-006rbacprivilegesattachdictionary) + * 5.23.3 [RQ.SRS-006.RBAC.Privileges.AttachTemporaryTable](#rqsrs-006rbacprivilegesattachtemporarytable) + * 5.23.4 [RQ.SRS-006.RBAC.Privileges.AttachTable](#rqsrs-006rbacprivilegesattachtable) + * 5.24 [Drop](#drop) + * 5.24.1 [RQ.SRS-006.RBAC.Privileges.DropTable](#rqsrs-006rbacprivilegesdroptable) + * 5.24.2 [RQ.SRS-006.RBAC.Privileges.DropDatabase](#rqsrs-006rbacprivilegesdropdatabase) + * 5.24.3 [RQ.SRS-006.RBAC.Privileges.DropDictionary](#rqsrs-006rbacprivilegesdropdictionary) + * 5.25 [Detach](#detach) + * 5.25.1 [RQ.SRS-006.RBAC.Privileges.DetachTable](#rqsrs-006rbacprivilegesdetachtable) + * 5.25.2 [RQ.SRS-006.RBAC.Privileges.DetachView](#rqsrs-006rbacprivilegesdetachview) + * 5.25.3 [RQ.SRS-006.RBAC.Privileges.DetachDatabase](#rqsrs-006rbacprivilegesdetachdatabase) + * 5.25.4 [RQ.SRS-006.RBAC.Privileges.DetachDictionary](#rqsrs-006rbacprivilegesdetachdictionary) + * 5.26 [Truncate](#truncate) + * 5.26.1 [RQ.SRS-006.RBAC.Privileges.Truncate](#rqsrs-006rbacprivilegestruncate) + * 5.27 [Optimize](#optimize) + * 5.27.1 [RQ.SRS-006.RBAC.Privileges.Optimize](#rqsrs-006rbacprivilegesoptimize) + * 5.28 [Kill Query](#kill-query) + * 5.28.1 [RQ.SRS-006.RBAC.Privileges.KillQuery](#rqsrs-006rbacprivilegeskillquery) + * 5.29 [Kill Mutation](#kill-mutation) + * 5.29.1 [RQ.SRS-006.RBAC.Privileges.KillMutation](#rqsrs-006rbacprivilegeskillmutation) + * 5.29.2 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate](#rqsrs-006rbacprivilegeskillmutationalterupdate) + * 5.29.3 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete](#rqsrs-006rbacprivilegeskillmutationalterdelete) + * 5.29.4 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn](#rqsrs-006rbacprivilegeskillmutationalterdropcolumn) + * 5.30 [Show](#show) + * 5.30.1 [RQ.SRS-006.RBAC.ShowTables.Privilege](#rqsrs-006rbacshowtablesprivilege) + * 5.30.2 [RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege](#rqsrs-006rbacshowtablesrequiredprivilege) + * 5.30.3 [RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege](#rqsrs-006rbacexiststablerequiredprivilege) + * 5.30.4 [RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege](#rqsrs-006rbacchecktablerequiredprivilege) + * 5.30.5 [RQ.SRS-006.RBAC.ShowDatabases.Privilege](#rqsrs-006rbacshowdatabasesprivilege) + * 5.30.6 [RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege](#rqsrs-006rbacshowdatabasesrequiredprivilege) + * 5.30.7 [RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege](#rqsrs-006rbacshowcreatedatabaserequiredprivilege) + * 5.30.8 [RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege](#rqsrs-006rbacusedatabaserequiredprivilege) + * 5.30.9 [RQ.SRS-006.RBAC.ShowColumns.Privilege](#rqsrs-006rbacshowcolumnsprivilege) + * 5.30.10 [RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege](#rqsrs-006rbacshowcreatetablerequiredprivilege) + * 5.30.11 [RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege](#rqsrs-006rbacdescribetablerequiredprivilege) + * 5.30.12 [RQ.SRS-006.RBAC.ShowDictionaries.Privilege](#rqsrs-006rbacshowdictionariesprivilege) + * 5.30.13 [RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege](#rqsrs-006rbacshowdictionariesrequiredprivilege) + * 5.30.14 [RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege](#rqsrs-006rbacshowcreatedictionaryrequiredprivilege) + * 5.30.15 [RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege](#rqsrs-006rbacexistsdictionaryrequiredprivilege) + * 5.31 [Access Management](#access-management) + * 5.31.1 [RQ.SRS-006.RBAC.Privileges.CreateUser](#rqsrs-006rbacprivilegescreateuser) + * 5.31.2 [RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole](#rqsrs-006rbacprivilegescreateuserdefaultrole) + * 5.31.3 [RQ.SRS-006.RBAC.Privileges.AlterUser](#rqsrs-006rbacprivilegesalteruser) + * 5.31.4 [RQ.SRS-006.RBAC.Privileges.DropUser](#rqsrs-006rbacprivilegesdropuser) + * 5.31.5 [RQ.SRS-006.RBAC.Privileges.CreateRole](#rqsrs-006rbacprivilegescreaterole) + * 5.31.6 [RQ.SRS-006.RBAC.Privileges.AlterRole](#rqsrs-006rbacprivilegesalterrole) + * 5.31.7 [RQ.SRS-006.RBAC.Privileges.DropRole](#rqsrs-006rbacprivilegesdroprole) + * 5.31.8 [RQ.SRS-006.RBAC.Privileges.CreateRowPolicy](#rqsrs-006rbacprivilegescreaterowpolicy) + * 5.31.9 [RQ.SRS-006.RBAC.Privileges.AlterRowPolicy](#rqsrs-006rbacprivilegesalterrowpolicy) + * 5.31.10 [RQ.SRS-006.RBAC.Privileges.DropRowPolicy](#rqsrs-006rbacprivilegesdroprowpolicy) + * 5.31.11 [RQ.SRS-006.RBAC.Privileges.CreateQuota](#rqsrs-006rbacprivilegescreatequota) + * 5.31.12 [RQ.SRS-006.RBAC.Privileges.AlterQuota](#rqsrs-006rbacprivilegesalterquota) + * 5.31.13 [RQ.SRS-006.RBAC.Privileges.DropQuota](#rqsrs-006rbacprivilegesdropquota) + * 5.31.14 [RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile](#rqsrs-006rbacprivilegescreatesettingsprofile) + * 5.31.15 [RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile](#rqsrs-006rbacprivilegesaltersettingsprofile) + * 5.31.16 [RQ.SRS-006.RBAC.Privileges.DropSettingsProfile](#rqsrs-006rbacprivilegesdropsettingsprofile) + * 5.31.17 [RQ.SRS-006.RBAC.Privileges.RoleAdmin](#rqsrs-006rbacprivilegesroleadmin) + * 5.31.18 [Show Access](#show-access) + * 5.31.18.1 [RQ.SRS-006.RBAC.ShowUsers.Privilege](#rqsrs-006rbacshowusersprivilege) + * 5.31.18.2 [RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege](#rqsrs-006rbacshowusersrequiredprivilege) + * 5.31.18.3 [RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege](#rqsrs-006rbacshowcreateuserrequiredprivilege) + * 5.31.18.4 [RQ.SRS-006.RBAC.ShowRoles.Privilege](#rqsrs-006rbacshowrolesprivilege) + * 5.31.18.5 [RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege](#rqsrs-006rbacshowrolesrequiredprivilege) + * 5.31.18.6 [RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege](#rqsrs-006rbacshowcreaterolerequiredprivilege) + * 5.31.18.7 [RQ.SRS-006.RBAC.ShowRowPolicies.Privilege](#rqsrs-006rbacshowrowpoliciesprivilege) + * 5.31.18.8 [RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege](#rqsrs-006rbacshowrowpoliciesrequiredprivilege) + * 5.31.18.9 [RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege](#rqsrs-006rbacshowcreaterowpolicyrequiredprivilege) + * 5.31.18.10 [RQ.SRS-006.RBAC.ShowQuotas.Privilege](#rqsrs-006rbacshowquotasprivilege) + * 5.31.18.11 [RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege](#rqsrs-006rbacshowquotasrequiredprivilege) + * 5.31.18.12 [RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege](#rqsrs-006rbacshowcreatequotarequiredprivilege) + * 5.31.18.13 [RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege](#rqsrs-006rbacshowsettingsprofilesprivilege) + * 5.31.18.14 [RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege](#rqsrs-006rbacshowsettingsprofilesrequiredprivilege) + * 5.31.18.15 [RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege](#rqsrs-006rbacshowcreatesettingsprofilerequiredprivilege) + * 5.32 [dictGet](#dictget) + * 5.32.1 [RQ.SRS-006.RBAC.dictGet.Privilege](#rqsrs-006rbacdictgetprivilege) + * 5.32.2 [RQ.SRS-006.RBAC.dictGet.RequiredPrivilege](#rqsrs-006rbacdictgetrequiredprivilege) + * 5.32.3 [RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege](#rqsrs-006rbacdictgettyperequiredprivilege) + * 5.32.4 [RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege](#rqsrs-006rbacdictgetordefaultrequiredprivilege) + * 5.32.5 [RQ.SRS-006.RBAC.dictHas.RequiredPrivilege](#rqsrs-006rbacdicthasrequiredprivilege) + * 5.32.6 [RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege](#rqsrs-006rbacdictgethierarchyrequiredprivilege) + * 5.32.7 [RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege](#rqsrs-006rbacdictisinrequiredprivilege) + * 5.33 [Introspection](#introspection) + * 5.33.1 [RQ.SRS-006.RBAC.Privileges.Introspection](#rqsrs-006rbacprivilegesintrospection) + * 5.33.2 [RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine](#rqsrs-006rbacprivilegesintrospectionaddresstoline) + * 5.33.3 [RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol](#rqsrs-006rbacprivilegesintrospectionaddresstosymbol) + * 5.33.4 [RQ.SRS-006.RBAC.Privileges.Introspection.demangle](#rqsrs-006rbacprivilegesintrospectiondemangle) + * 5.34 [System](#system) + * 5.34.1 [RQ.SRS-006.RBAC.Privileges.System.Shutdown](#rqsrs-006rbacprivilegessystemshutdown) + * 5.34.2 [RQ.SRS-006.RBAC.Privileges.System.DropCache](#rqsrs-006rbacprivilegessystemdropcache) + * 5.34.3 [RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS](#rqsrs-006rbacprivilegessystemdropcachedns) + * 5.34.4 [RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark](#rqsrs-006rbacprivilegessystemdropcachemark) + * 5.34.5 [RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed](#rqsrs-006rbacprivilegessystemdropcacheuncompressed) + * 5.34.6 [RQ.SRS-006.RBAC.Privileges.System.Reload](#rqsrs-006rbacprivilegessystemreload) + * 5.34.7 [RQ.SRS-006.RBAC.Privileges.System.Reload.Config](#rqsrs-006rbacprivilegessystemreloadconfig) + * 5.34.8 [RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary](#rqsrs-006rbacprivilegessystemreloaddictionary) + * 5.34.9 [RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries](#rqsrs-006rbacprivilegessystemreloaddictionaries) + * 5.34.10 [RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries](#rqsrs-006rbacprivilegessystemreloadembeddeddictionaries) + * 5.34.11 [RQ.SRS-006.RBAC.Privileges.System.Merges](#rqsrs-006rbacprivilegessystemmerges) + * 5.34.12 [RQ.SRS-006.RBAC.Privileges.System.TTLMerges](#rqsrs-006rbacprivilegessystemttlmerges) + * 5.34.13 [RQ.SRS-006.RBAC.Privileges.System.Fetches](#rqsrs-006rbacprivilegessystemfetches) + * 5.34.14 [RQ.SRS-006.RBAC.Privileges.System.Moves](#rqsrs-006rbacprivilegessystemmoves) + * 5.34.15 [RQ.SRS-006.RBAC.Privileges.System.Sends](#rqsrs-006rbacprivilegessystemsends) + * 5.34.16 [RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed](#rqsrs-006rbacprivilegessystemsendsdistributed) + * 5.34.17 [RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated](#rqsrs-006rbacprivilegessystemsendsreplicated) + * 5.34.18 [RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues](#rqsrs-006rbacprivilegessystemreplicationqueues) + * 5.34.19 [RQ.SRS-006.RBAC.Privileges.System.SyncReplica](#rqsrs-006rbacprivilegessystemsyncreplica) + * 5.34.20 [RQ.SRS-006.RBAC.Privileges.System.RestartReplica](#rqsrs-006rbacprivilegessystemrestartreplica) + * 5.34.21 [RQ.SRS-006.RBAC.Privileges.System.Flush](#rqsrs-006rbacprivilegessystemflush) + * 5.34.22 [RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed](#rqsrs-006rbacprivilegessystemflushdistributed) + * 5.34.23 [RQ.SRS-006.RBAC.Privileges.System.Flush.Logs](#rqsrs-006rbacprivilegessystemflushlogs) + * 5.35 [Sources](#sources) + * 5.35.1 [RQ.SRS-006.RBAC.Privileges.Sources](#rqsrs-006rbacprivilegessources) + * 5.35.2 [RQ.SRS-006.RBAC.Privileges.Sources.File](#rqsrs-006rbacprivilegessourcesfile) + * 5.35.3 [RQ.SRS-006.RBAC.Privileges.Sources.URL](#rqsrs-006rbacprivilegessourcesurl) + * 5.35.4 [RQ.SRS-006.RBAC.Privileges.Sources.Remote](#rqsrs-006rbacprivilegessourcesremote) + * 5.35.5 [RQ.SRS-006.RBAC.Privileges.Sources.MySQL](#rqsrs-006rbacprivilegessourcesmysql) + * 5.35.6 [RQ.SRS-006.RBAC.Privileges.Sources.ODBC](#rqsrs-006rbacprivilegessourcesodbc) + * 5.35.7 [RQ.SRS-006.RBAC.Privileges.Sources.JDBC](#rqsrs-006rbacprivilegessourcesjdbc) + * 5.35.8 [RQ.SRS-006.RBAC.Privileges.Sources.HDFS](#rqsrs-006rbacprivilegessourceshdfs) + * 5.35.9 [RQ.SRS-006.RBAC.Privileges.Sources.S3](#rqsrs-006rbacprivilegessourcess3) + * 5.36 [RQ.SRS-006.RBAC.Privileges.GrantOption](#rqsrs-006rbacprivilegesgrantoption) + * 5.37 [RQ.SRS-006.RBAC.Privileges.All](#rqsrs-006rbacprivilegesall) + * 5.38 [RQ.SRS-006.RBAC.Privileges.RoleAll](#rqsrs-006rbacprivilegesroleall) + * 5.39 [RQ.SRS-006.RBAC.Privileges.None](#rqsrs-006rbacprivilegesnone) + * 5.40 [RQ.SRS-006.RBAC.Privileges.AdminOption](#rqsrs-006rbacprivilegesadminoption) * 6 [References](#references) ## Revision History @@ -631,256 +663,103 @@ version: 1.0 [ClickHouse] SHALL support role based access control. -#### Login +### Login -##### RQ.SRS-006.RBAC.Login +#### RQ.SRS-006.RBAC.Login version: 1.0 [ClickHouse] SHALL only allow access to the server for a given user only when correct username and password are used during the connection to the server. -##### RQ.SRS-006.RBAC.Login.DefaultUser +#### RQ.SRS-006.RBAC.Login.DefaultUser version: 1.0 [ClickHouse] SHALL use the **default user** when no username and password are specified during the connection to the server. -#### User +### User -##### RQ.SRS-006.RBAC.User +#### RQ.SRS-006.RBAC.User version: 1.0 [ClickHouse] SHALL support creation and manipulation of one or more **user** accounts to which roles, privileges, settings profile, quotas and row policies can be assigned. -##### RQ.SRS-006.RBAC.User.Roles +#### RQ.SRS-006.RBAC.User.Roles version: 1.0 [ClickHouse] SHALL support assigning one or more **roles** to a **user**. -##### RQ.SRS-006.RBAC.User.Privileges +#### RQ.SRS-006.RBAC.User.Privileges version: 1.0 [ClickHouse] SHALL support assigning one or more privileges to a **user**. -##### RQ.SRS-006.RBAC.User.Variables +#### RQ.SRS-006.RBAC.User.Variables version: 1.0 [ClickHouse] SHALL support assigning one or more variables to a **user**. -##### RQ.SRS-006.RBAC.User.Variables.Constraints +#### RQ.SRS-006.RBAC.User.Variables.Constraints version: 1.0 [ClickHouse] SHALL support assigning min, max and read-only constraints for the variables that can be set and read by the **user**. -##### RQ.SRS-006.RBAC.User.SettingsProfile +#### RQ.SRS-006.RBAC.User.SettingsProfile version: 1.0 [ClickHouse] SHALL support assigning one or more **settings profiles** to a **user**. -##### RQ.SRS-006.RBAC.User.Quotas +#### RQ.SRS-006.RBAC.User.Quotas version: 1.0 [ClickHouse] SHALL support assigning one or more **quotas** to a **user**. -##### RQ.SRS-006.RBAC.User.RowPolicies +#### RQ.SRS-006.RBAC.User.RowPolicies version: 1.0 [ClickHouse] SHALL support assigning one or more **row policies** to a **user**. -##### RQ.SRS-006.RBAC.User.AccountLock -version: 1.0 - -[ClickHouse] SHALL support locking and unlocking of **user** accounts. - -##### RQ.SRS-006.RBAC.User.AccountLock.DenyAccess -version: 1.0 - -[ClickHouse] SHALL deny access to the user whose account is locked. - -##### RQ.SRS-006.RBAC.User.DefaultRole +#### RQ.SRS-006.RBAC.User.DefaultRole version: 1.0 [ClickHouse] SHALL support assigning a default role to a **user**. -##### RQ.SRS-006.RBAC.User.RoleSelection +#### RQ.SRS-006.RBAC.User.RoleSelection version: 1.0 [ClickHouse] SHALL support selection of one or more **roles** from the available roles -that are assigned to a **user**. +that are assigned to a **user** using `SET ROLE` statement. -##### RQ.SRS-006.RBAC.User.ShowCreate +#### RQ.SRS-006.RBAC.User.ShowCreate version: 1.0 [ClickHouse] SHALL support showing the command of how **user** account was created. -##### RQ.SRS-006.RBAC.User.ShowPrivileges +#### RQ.SRS-006.RBAC.User.ShowPrivileges version: 1.0 [ClickHouse] SHALL support listing the privileges of the **user**. -#### Role - -##### RQ.SRS-006.RBAC.Role -version: 1.0 - -[ClikHouse] SHALL support creation and manipulation of **roles** -to which privileges, settings profile, quotas and row policies can be -assigned. - -##### RQ.SRS-006.RBAC.Role.Privileges -version: 1.0 - -[ClickHouse] SHALL support assigning one or more privileges to a **role**. - -##### RQ.SRS-006.RBAC.Role.Variables -version: 1.0 - -[ClickHouse] SHALL support assigning one or more variables to a **role**. - -##### RQ.SRS-006.RBAC.Role.SettingsProfile -version: 1.0 - -[ClickHouse] SHALL support assigning one or more **settings profiles** -to a **role**. - -##### RQ.SRS-006.RBAC.Role.Quotas -version: 1.0 - -[ClickHouse] SHALL support assigning one or more **quotas** to a **role**. - -##### RQ.SRS-006.RBAC.Role.RowPolicies -version: 1.0 - -[ClickHouse] SHALL support assigning one or more **row policies** to a **role**. - -#### Partial Revokes - -##### RQ.SRS-006.RBAC.PartialRevokes -version: 1.0 - -[ClickHouse] SHALL support partial revoking of privileges granted -to a **user** or a **role**. - -#### Settings Profile - -##### RQ.SRS-006.RBAC.SettingsProfile -version: 1.0 - -[ClickHouse] SHALL support creation and manipulation of **settings profiles** -that can include value definition for one or more variables and can -can be assigned to one or more **users** or **roles**. - -##### RQ.SRS-006.RBAC.SettingsProfile.Constraints -version: 1.0 - -[ClickHouse] SHALL support assigning min, max and read-only constraints -for the variables specified in the **settings profile**. - -##### RQ.SRS-006.RBAC.SettingsProfile.ShowCreate -version: 1.0 - -[ClickHouse] SHALL support showing the command of how **setting profile** was created. - -#### Quotas - -##### RQ.SRS-006.RBAC.Quotas -version: 1.0 - -[ClickHouse] SHALL support creation and manipulation of **quotas** -that can be used to limit resource usage by a **user** or a **role** -over a period of time. - -##### RQ.SRS-006.RBAC.Quotas.Keyed -version: 1.0 - -[ClickHouse] SHALL support creating **quotas** that are keyed -so that a quota is tracked separately for each key value. - -##### RQ.SRS-006.RBAC.Quotas.Queries -version: 1.0 - -[ClickHouse] SHALL support setting **queries** quota to limit the total number of requests. - -##### RQ.SRS-006.RBAC.Quotas.Errors -version: 1.0 - -[ClickHouse] SHALL support setting **errors** quota to limit the number of queries that threw an exception. - -##### RQ.SRS-006.RBAC.Quotas.ResultRows -version: 1.0 - -[ClickHouse] SHALL support setting **result rows** quota to limit the -the total number of rows given as the result. - -##### RQ.SRS-006.RBAC.Quotas.ReadRows -version: 1.0 - -[ClickHouse] SHALL support setting **read rows** quota to limit the total -number of source rows read from tables for running the query on all remote servers. - -##### RQ.SRS-006.RBAC.Quotas.ResultBytes -version: 1.0 - -[ClickHouse] SHALL support setting **result bytes** quota to limit the total number -of bytes that can be returned as the result. - -##### RQ.SRS-006.RBAC.Quotas.ReadBytes -version: 1.0 - -[ClickHouse] SHALL support setting **read bytes** quota to limit the total number -of source bytes read from tables for running the query on all remote servers. - -##### RQ.SRS-006.RBAC.Quotas.ExecutionTime -version: 1.0 - -[ClickHouse] SHALL support setting **execution time** quota to limit the maximum -query execution time. - -##### RQ.SRS-006.RBAC.Quotas.ShowCreate -version: 1.0 - -[ClickHouse] SHALL support showing the command of how **quota** was created. - -#### Row Policy - -##### RQ.SRS-006.RBAC.RowPolicy -version: 1.0 - -[ClickHouse] SHALL support creation and manipulation of table **row policies** -that can be used to limit access to the table contents for a **user** or a **role** -using a specified **condition**. - -##### RQ.SRS-006.RBAC.RowPolicy.Condition -version: 1.0 - -[ClickHouse] SHALL support row policy **conditions** that can be any SQL -expression that returns a boolean. - -##### RQ.SRS-006.RBAC.RowPolicy.ShowCreate -version: 1.0 - -[ClickHouse] SHALL support showing the command of how **row policy** was created. - -### Specific - -##### RQ.SRS-006.RBAC.User.Use.DefaultRole +#### RQ.SRS-006.RBAC.User.Use.DefaultRole version: 1.0 [ClickHouse] SHALL by default use default role or roles assigned to the user if specified. -##### RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole +#### RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole version: 1.0 [ClickHouse] SHALL by default use all the roles assigned to the user if no default role or roles are specified for the user. +#### Create User + ##### RQ.SRS-006.RBAC.User.Create version: 1.0 @@ -1078,6 +957,8 @@ CREATE USER [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name] [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] ``` +#### Alter User + ##### RQ.SRS-006.RBAC.User.Alter version: 1.0 @@ -1094,7 +975,8 @@ the left. version: 1.0 [ClickHouse] SHALL support `IF EXISTS` clause in the `ALTER USER` statement -to skip raising an exception (producing a warning instead) if a user with the specified **name** does not exist. If the `IF EXISTS` clause is not specified then an exception SHALL be raised if a user with the **name** does not exist. +to skip raising an exception (producing a warning instead) if a user with the specified **name** does not exist. +If the `IF EXISTS` clause is not specified then an exception SHALL be raised if a user with the **name** does not exist. ##### RQ.SRS-006.RBAC.User.Alter.Cluster version: 1.0 @@ -1132,7 +1014,8 @@ to some password as identification when altering user account using ##### RQ.SRS-006.RBAC.User.Alter.Host.AddDrop version: 1.0 -[ClickHouse] SHALL support altering user by adding and dropping access to hosts with the `ADD HOST` or the `DROP HOST`in the `ALTER USER` statement. +[ClickHouse] SHALL support altering user by adding and dropping access to hosts +with the `ADD HOST` or the `DROP HOST` in the `ALTER USER` statement. ##### RQ.SRS-006.RBAC.User.Alter.Host.Local version: 1.0 @@ -1164,7 +1047,8 @@ which user can access the server using the `HOST IP` clause in the ##### RQ.SRS-006.RBAC.User.Alter.Host.Like version: 1.0 -[ClickHouse] SHALL support specifying sone or more similar hosts using `LIKE` command syntax using the `HOST LIKE` clause in the `ALTER USER` statement. +[ClickHouse] SHALL support specifying one or more similar hosts using `LIKE` command syntax +using the `HOST LIKE` clause in the `ALTER USER` statement. ##### RQ.SRS-006.RBAC.User.Alter.Host.Any version: 1.0 @@ -1207,7 +1091,6 @@ version: 1.0 [ClickHouse] SHALL support specifying a minimum value for the variable specifed using `SETTINGS` with `MIN` clause in the `ALTER USER` statement. - ##### RQ.SRS-006.RBAC.User.Alter.Settings.Max version: 1.0 @@ -1232,85 +1115,7 @@ ALTER USER [IF EXISTS] name [ON CLUSTER cluster_name] [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] ``` -##### RQ.SRS-006.RBAC.SetDefaultRole -version: 1.0 - -[ClickHouse] SHALL support setting or changing granted roles to default for one or more -users using `SET DEFAULT ROLE` statement which -SHALL permanently change the default roles for the user or users if successful. - -##### RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser -version: 1.0 - -[ClickHouse] SHALL support setting or changing granted roles to default for -the current user using `CURRENT_USER` clause in the `SET DEFAULT ROLE` statement. - -##### RQ.SRS-006.RBAC.SetDefaultRole.All -version: 1.0 - -[ClickHouse] SHALL support setting or changing all granted roles to default -for one or more users using `ALL` clause in the `SET DEFAULT ROLE` statement. - -##### RQ.SRS-006.RBAC.SetDefaultRole.AllExcept -version: 1.0 - -[ClickHouse] SHALL support setting or changing all granted roles except those specified -to default for one or more users using `ALL EXCEPT` clause in the `SET DEFAULT ROLE` statement. - -##### RQ.SRS-006.RBAC.SetDefaultRole.None -version: 1.0 - -[ClickHouse] SHALL support removing all granted roles from default -for one or more users using `NONE` clause in the `SET DEFAULT ROLE` statement. - -##### RQ.SRS-006.RBAC.SetDefaultRole.Syntax -version: 1.0 - -[ClickHouse] SHALL support the following syntax for the `SET DEFAULT ROLE` statement. - -```sql -SET DEFAULT ROLE - {NONE | role [,...] | ALL | ALL EXCEPT role [,...]} - TO {user|CURRENT_USER} [,...] - -``` - -##### RQ.SRS-006.RBAC.SetRole -version: 1.0 - -[ClickHouse] SHALL support activating role or roles for the current user -using `SET ROLE` statement. - -##### RQ.SRS-006.RBAC.SetRole.Default -version: 1.0 - -[ClickHouse] SHALL support activating default roles for the current user -using `DEFAULT` clause in the `SET ROLE` statement. - -##### RQ.SRS-006.RBAC.SetRole.None -version: 1.0 - -[ClickHouse] SHALL support activating no roles for the current user -using `NONE` clause in the `SET ROLE` statement. - -##### RQ.SRS-006.RBAC.SetRole.All -version: 1.0 - -[ClickHouse] SHALL support activating all roles for the current user -using `ALL` clause in the `SET ROLE` statement. - -##### RQ.SRS-006.RBAC.SetRole.AllExcept -version: 1.0 - -[ClickHouse] SHALL support activating all roles except those specified -for the current user using `ALL EXCEPT` clause in the `SET ROLE` statement. - -##### RQ.SRS-006.RBAC.SetRole.Syntax -version: 1.0 - -```sql -SET ROLE {DEFAULT | NONE | role [,...] | ALL | ALL EXCEPT role [,...]} -``` +#### Show Create User ##### RQ.SRS-006.RBAC.User.ShowCreateUser version: 1.0 @@ -1333,6 +1138,8 @@ version: 1.0 SHOW CREATE USER [name | CURRENT_USER] ``` +#### Drop User + ##### RQ.SRS-006.RBAC.User.Drop version: 1.0 @@ -1361,6 +1168,43 @@ version: 1.0 DROP USER [IF EXISTS] name [,...] [ON CLUSTER cluster_name] ``` +### Role + +#### RQ.SRS-006.RBAC.Role +version: 1.0 + +[ClikHouse] SHALL support creation and manipulation of **roles** +to which privileges, settings profile, quotas and row policies can be +assigned. + +#### RQ.SRS-006.RBAC.Role.Privileges +version: 1.0 + +[ClickHouse] SHALL support assigning one or more privileges to a **role**. + +#### RQ.SRS-006.RBAC.Role.Variables +version: 1.0 + +[ClickHouse] SHALL support assigning one or more variables to a **role**. + +#### RQ.SRS-006.RBAC.Role.SettingsProfile +version: 1.0 + +[ClickHouse] SHALL support assigning one or more **settings profiles** +to a **role**. + +#### RQ.SRS-006.RBAC.Role.Quotas +version: 1.0 + +[ClickHouse] SHALL support assigning one or more **quotas** to a **role**. + +#### RQ.SRS-006.RBAC.Role.RowPolicies +version: 1.0 + +[ClickHouse] SHALL support assigning one or more **row policies** to a **role**. + +#### Create Role + ##### RQ.SRS-006.RBAC.Role.Create version: 1.0 @@ -1396,6 +1240,8 @@ CREATE ROLE [IF NOT EXISTS | OR REPLACE] name [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] ``` +#### Alter Role + ##### RQ.SRS-006.RBAC.Role.Alter version: 1.0 @@ -1442,6 +1288,8 @@ ALTER ROLE [IF EXISTS] name [ON CLUSTER cluster_name] [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] ``` +#### Drop Role + ##### RQ.SRS-006.RBAC.Role.Drop version: 1.0 @@ -1469,6 +1317,8 @@ version: 1.0 DROP ROLE [IF EXISTS] name [,...] [ON CLUSTER cluster_name] ``` +#### Show Create Role + ##### RQ.SRS-006.RBAC.Role.ShowCreate version: 1.0 @@ -1484,326 +1334,15 @@ version: 1.0 SHOW CREATE ROLE name ``` -##### RQ.SRS-006.RBAC.Grant.Privilege.To +### Partial Revokes + +#### RQ.SRS-006.RBAC.PartialRevokes version: 1.0 -[ClickHouse] SHALL support granting privileges to one or more users or roles using `TO` clause -in the `GRANT PRIVILEGE` statement. +[ClickHouse] SHALL support partial revoking of privileges granted +to a **user** or a **role**. -##### RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser -version: 1.0 - -[ClickHouse] SHALL support granting privileges to current user using `TO CURRENT_USER` clause -in the `GRANT PRIVILEGE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Select -version: 1.0 - -[ClickHouse] SHALL support granting the **select** privilege to one or more users or roles -for a database or a table using the `GRANT SELECT` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Insert -version: 1.0 - -[ClickHouse] SHALL support granting the **insert** privilege to one or more users or roles -for a database or a table using the `GRANT INSERT` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Alter -version: 1.0 - -[ClickHouse] SHALL support granting the **alter** privilege to one or more users or roles -for a database or a table using the `GRANT ALTER` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Create -version: 1.0 - -[ClickHouse] SHALL support granting the **create** privilege to one or more users or roles -using the `GRANT CREATE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Drop -version: 1.0 - -[ClickHouse] SHALL support granting the **drop** privilege to one or more users or roles -using the `GRANT DROP` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Truncate -version: 1.0 - -[ClickHouse] SHALL support granting the **truncate** privilege to one or more users or roles -for a database or a table using `GRANT TRUNCATE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Optimize -version: 1.0 - -[ClickHouse] SHALL support granting the **optimize** privilege to one or more users or roles -for a database or a table using `GRANT OPTIMIZE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Show -version: 1.0 - -[ClickHouse] SHALL support granting the **show** privilege to one or more users or roles -for a database or a table using `GRANT SHOW` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.KillQuery -version: 1.0 - -[ClickHouse] SHALL support granting the **kill query** privilege to one or more users or roles -for a database or a table using `GRANT KILL QUERY` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement -version: 1.0 - -[ClickHouse] SHALL support granting the **access management** privileges to one or more users or roles -for a database or a table using `GRANT ACCESS MANAGEMENT` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.System -version: 1.0 - -[ClickHouse] SHALL support granting the **system** privileges to one or more users or roles -for a database or a table using `GRANT SYSTEM` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Introspection -version: 1.0 - -[ClickHouse] SHALL support granting the **introspection** privileges to one or more users or roles -for a database or a table using `GRANT INTROSPECTION` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Sources -version: 1.0 - -[ClickHouse] SHALL support granting the **sources** privileges to one or more users or roles -for a database or a table using `GRANT SOURCES` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.DictGet -version: 1.0 - -[ClickHouse] SHALL support granting the **dictGet** privilege to one or more users or roles -for a database or a table using `GRANT dictGet` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.None -version: 1.0 - -[ClickHouse] SHALL support granting no privileges to one or more users or roles -for a database or a table using `GRANT NONE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.All -version: 1.0 - -[ClickHouse] SHALL support granting the **all** privileges to one or more users or roles -for a database or a table using the `GRANT ALL` or `GRANT ALL PRIVILEGES` statements. - -##### RQ.SRS-006.RBAC.Grant.Privilege.GrantOption -version: 1.0 - -[ClickHouse] SHALL support granting the **grant option** privilege to one or more users or roles -for a database or a table using the `WITH GRANT OPTION` clause in the `GRANT` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.On -version: 1.0 - -[ClickHouse] SHALL support the `ON` clause in the `GRANT` privilege statement -which SHALL allow to specify one or more tables to which the privilege SHALL -be granted using the following patterns - -* `*.*` any table in any database -* `database.*` any table in the specified database -* `database.table` specific table in the specified database -* `*` any table in the current database -* `table` specific table in the current database - -##### RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns -version: 1.0 - -[ClickHouse] SHALL support granting the privilege **some_privilege** to one or more users or roles -for a database or a table using the `GRANT some_privilege(column)` statement for one column. -Multiple columns will be supported with `GRANT some_privilege(column1, column2...)` statement. -The privileges will be granted for only the specified columns. - -##### RQ.SRS-006.RBAC.Grant.Privilege.OnCluster -version: 1.0 - -[ClickHouse] SHALL support specifying cluster on which to grant privileges using the `ON CLUSTER` -clause in the `GRANT PRIVILEGE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Syntax -version: 1.0 - -[ClickHouse] SHALL support the following syntax for the `GRANT` statement that -grants explicit privileges to a user or a role. - -```sql -GRANT [ON CLUSTER cluster_name] privilege[(column_name [,...])] [,...] - ON {db.table|db.*|*.*|table|*} - TO {user | role | CURRENT_USER} [,...] - [WITH GRANT OPTION] -``` - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Cluster -version: 1.0 - -[ClickHouse] SHALL support revoking privileges to one or more users or roles -for a database or a table on some specific cluster using the `REVOKE ON CLUSTER cluster_name` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Any -version: 1.0 - -[ClickHouse] SHALL support revoking ANY privilege to one or more users or roles -for a database or a table using the `REVOKE some_privilege` statement. -**some_privilege** refers to any Clickhouse defined privilege, whose hierarchy includes -SELECT, INSERT, ALTER, CREATE, DROP, TRUNCATE, OPTIMIZE, SHOW, KILL QUERY, ACCESS MANAGEMENT, -SYSTEM, INTROSPECTION, SOURCES, dictGet and all of their sub-privileges. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Select -version: 1.0 - -[ClickHouse] SHALL support revoking the **select** privilege to one or more users or roles -for a database or a table using the `REVOKE SELECT` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Insert -version: 1.0 - -[ClickHouse] SHALL support revoking the **insert** privilege to one or more users or roles -for a database or a table using the `REVOKE INSERT` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Alter -version: 1.0 - -[ClickHouse] SHALL support revoking the **alter** privilege to one or more users or roles -for a database or a table using the `REVOKE ALTER` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Create -version: 1.0 - -[ClickHouse] SHALL support revoking the **create** privilege to one or more users or roles -using the `REVOKE CREATE` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Drop -version: 1.0 - -[ClickHouse] SHALL support revoking the **drop** privilege to one or more users or roles -using the `REVOKE DROP` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Truncate -version: 1.0 - -[ClickHouse] SHALL support revoking the **truncate** privilege to one or more users or roles -for a database or a table using the `REVOKE TRUNCATE` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Optimize -version: 1.0 - -[ClickHouse] SHALL support revoking the **optimize** privilege to one or more users or roles -for a database or a table using the `REVOKE OPTIMIZE` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Show -version: 1.0 - -[ClickHouse] SHALL support revoking the **show** privilege to one or more users or roles -for a database or a table using the `REVOKE SHOW` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery -version: 1.0 - -[ClickHouse] SHALL support revoking the **kill query** privilege to one or more users or roles -for a database or a table using the `REVOKE KILL QUERY` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement -version: 1.0 - -[ClickHouse] SHALL support revoking the **access management** privilege to one or more users or roles -for a database or a table using the `REVOKE ACCESS MANAGEMENT` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.System -version: 1.0 - -[ClickHouse] SHALL support revoking the **system** privilege to one or more users or roles -for a database or a table using the `REVOKE SYSTEM` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Introspection -version: 1.0 - -[ClickHouse] SHALL support revoking the **introspection** privilege to one or more users or roles -for a database or a table using the `REVOKE INTROSPECTION` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Sources -version: 1.0 - -[ClickHouse] SHALL support revoking the **sources** privilege to one or more users or roles -for a database or a table using the `REVOKE SOURCES` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.DictGet -version: 1.0 - -[ClickHouse] SHALL support revoking the **dictGet** privilege to one or more users or roles -for a database or a table using the `REVOKE dictGet` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.PrivelegeColumns -version: 1.0 - -[ClickHouse] SHALL support revoking the privilege **some_privilege** to one or more users or roles -for a database or a table using the `REVOKE some_privilege(column)` statement for one column. -Multiple columns will be supported with `REVOKE some_privilege(column1, column2...)` statement. -The privileges will be revoked for only the specified columns. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Multiple -version: 1.0 - -[ClickHouse] SHALL support revoking MULTIPLE **privileges** to one or more users or roles -for a database or a table using the `REVOKE privilege1, privilege2...` statement. -**privileges** refers to any set of Clickhouse defined privilege, whose hierarchy includes -SELECT, INSERT, ALTER, CREATE, DROP, TRUNCATE, OPTIMIZE, SHOW, KILL QUERY, ACCESS MANAGEMENT, -SYSTEM, INTROSPECTION, SOURCES, dictGet and all of their sub-privileges. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.All -version: 1.0 - -[ClickHouse] SHALL support revoking **all** privileges to one or more users or roles -for a database or a table using the `REVOKE ALL` or `REVOKE ALL PRIVILEGES` statements. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.None -version: 1.0 - -[ClickHouse] SHALL support revoking **no** privileges to one or more users or roles -for a database or a table using the `REVOKE NONE` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.On -version: 1.0 - -[ClickHouse] SHALL support the `ON` clause in the `REVOKE` privilege statement -which SHALL allow to specify one or more tables to which the privilege SHALL -be revoked using the following patterns - -* `db.table` specific table in the specified database -* `db.*` any table in the specified database -* `*.*` any table in any database -* `table` specific table in the current database -* `*` any table in the current database - -##### RQ.SRS-006.RBAC.Revoke.Privilege.From -version: 1.0 - -[ClickHouse] SHALL support the `FROM` clause in the `REVOKE` privilege statement -which SHALL allow to specify one or more users to which the privilege SHALL -be revoked using the following patterns - -* `{user | CURRENT_USER} [,...]` some combination of users by name, which may include the current user -* `ALL` all users -* `ALL EXCEPT {user | CURRENT_USER} [,...]` the logical reverse of the first pattern - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Syntax -version: 1.0 - -[ClickHouse] SHALL support the following syntax for the `REVOKE` statement that -revokes explicit privileges of a user or a role. - -```sql -REVOKE [ON CLUSTER cluster_name] privilege - [(column_name [,...])] [,...] - ON {db.table|db.*|*.*|table|*} - FROM {user | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user | CURRENT_USER} [,...] -``` - -##### RQ.SRS-006.RBAC.PartialRevoke.Syntax +#### RQ.SRS-006.RBAC.PartialRevoke.Syntax version: 1.0 [ClickHouse] SHALL support partial revokes by using `partial_revokes` variable @@ -1821,102 +1360,22 @@ To enable partial revokes the `partial revokes` variable SHALL be set to `1` SET partial_revokes = 1 ``` -##### RQ.SRS-006.RBAC.Grant.Role +### Settings Profile + +#### RQ.SRS-006.RBAC.SettingsProfile version: 1.0 -[ClickHouse] SHALL support granting one or more roles to -one or more users or roles using the `GRANT` role statement. +[ClickHouse] SHALL support creation and manipulation of **settings profiles** +that can include value definition for one or more variables and can +can be assigned to one or more **users** or **roles**. -##### RQ.SRS-006.RBAC.Grant.Role.CurrentUser +#### RQ.SRS-006.RBAC.SettingsProfile.Constraints version: 1.0 -[ClickHouse] SHALL support granting one or more roles to current user using -`TO CURRENT_USER` clause in the `GRANT` role statement. +[ClickHouse] SHALL support assigning min, max and read-only constraints +for the variables specified in the **settings profile**. -##### RQ.SRS-006.RBAC.Grant.Role.AdminOption -version: 1.0 - -[ClickHouse] SHALL support granting `admin option` privilege -to one or more users or roles using the `WITH ADMIN OPTION` clause -in the `GRANT` role statement. - -##### RQ.SRS-006.RBAC.Grant.Role.OnCluster -version: 1.0 - -[ClickHouse] SHALL support specifying cluster on which the user is to be granted one or more roles -using `ON CLUSTER` clause in the `GRANT` statement. - -##### RQ.SRS-006.RBAC.Grant.Role.Syntax -version: 1.0 - -[ClickHouse] SHALL support the following syntax for `GRANT` role statement - -``` sql -GRANT - ON CLUSTER cluster_name - role [, role ...] - TO {user | role | CURRENT_USER} [,...] - [WITH ADMIN OPTION] -``` - -##### RQ.SRS-006.RBAC.Revoke.Role -version: 1.0 - -[ClickHouse] SHALL support revoking one or more roles from -one or more users or roles using the `REVOKE` role statement. - -##### RQ.SRS-006.RBAC.Revoke.Role.Keywords -version: 1.0 - -[ClickHouse] SHALL support revoking one or more roles from -special groupings of one or more users or roles with the `ALL`, `ALL EXCEPT`, -and `CURRENT_USER` keywords. - -##### RQ.SRS-006.RBAC.Revoke.Role.Cluster -version: 1.0 - -[ClickHouse] SHALL support revoking one or more roles from -one or more users or roles from one or more clusters -using the `REVOKE ON CLUSTER` role statement. - -##### RQ.SRS-006.RBAC.Revoke.AdminOption -version: 1.0 - -[ClickHouse] SHALL support revoking `admin option` privilege -in one or more users or roles using the `ADMIN OPTION FOR` clause -in the `REVOKE` role statement. - -##### RQ.SRS-006.RBAC.Revoke.Role.Syntax -version: 1.0 - -[ClickHouse] SHALL support the following syntax for the `REVOKE` role statement - -```sql -REVOKE [ON CLUSTER cluster_name] [ADMIN OPTION FOR] - role [,...] - FROM {user | role | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user_name | role_name | CURRENT_USER} [,...] -``` - -##### RQ.SRS-006.RBAC.Show.Grants -version: 1.0 - -[ClickHouse] SHALL support listing all the privileges granted to current user and role -using the `SHOW GRANTS` statement. - -##### RQ.SRS-006.RBAC.Show.Grants.For -version: 1.0 - -[ClickHouse] SHALL support listing all the privileges granted to a user or a role -using the `FOR` clause in the `SHOW GRANTS` statement. - -##### RQ.SRS-006.RBAC.Show.Grants.Syntax -version: 1.0 - -[Clickhouse] SHALL use the following syntax for the `SHOW GRANTS` statement - -``` sql -SHOW GRANTS [FOR user_or_role] -``` +#### Create Settings Profile ##### RQ.SRS-006.RBAC.SettingsProfile.Create version: 1.0 @@ -2002,6 +1461,8 @@ CREATE SETTINGS PROFILE [IF NOT EXISTS | OR REPLACE] name [TO {user_or_role [,...] | NONE | ALL | ALL EXCEPT user_or_role [,...]}] ``` +#### Alter Settings Profile + ##### RQ.SRS-006.RBAC.SettingsProfile.Alter version: 1.0 @@ -2087,6 +1548,8 @@ ALTER SETTINGS PROFILE [IF EXISTS] name [TO {user_or_role [,...] | NONE | ALL | ALL EXCEPT user_or_role [,...]]} ``` +#### Drop Settings Profile + ##### RQ.SRS-006.RBAC.SettingsProfile.Drop version: 1.0 @@ -2115,6 +1578,8 @@ version: 1.0 DROP SETTINGS PROFILE [IF EXISTS] name [,name,...] ``` +#### Show Create Settings Profile + ##### RQ.SRS-006.RBAC.SettingsProfile.ShowCreateSettingsProfile version: 1.0 @@ -2125,6 +1590,63 @@ using the `SHOW CREATE SETTINGS PROFILE` statement with the following syntax SHOW CREATE SETTINGS PROFILE name ``` +### Quotas + +#### RQ.SRS-006.RBAC.Quotas +version: 1.0 + +[ClickHouse] SHALL support creation and manipulation of **quotas** +that can be used to limit resource usage by a **user** or a **role** +over a period of time. + +#### RQ.SRS-006.RBAC.Quotas.Keyed +version: 1.0 + +[ClickHouse] SHALL support creating **quotas** that are keyed +so that a quota is tracked separately for each key value. + +#### RQ.SRS-006.RBAC.Quotas.Queries +version: 1.0 + +[ClickHouse] SHALL support setting **queries** quota to limit the total number of requests. + +#### RQ.SRS-006.RBAC.Quotas.Errors +version: 1.0 + +[ClickHouse] SHALL support setting **errors** quota to limit the number of queries that threw an exception. + +#### RQ.SRS-006.RBAC.Quotas.ResultRows +version: 1.0 + +[ClickHouse] SHALL support setting **result rows** quota to limit the +the total number of rows given as the result. + +#### RQ.SRS-006.RBAC.Quotas.ReadRows +version: 1.0 + +[ClickHouse] SHALL support setting **read rows** quota to limit the total +number of source rows read from tables for running the query on all remote servers. + +#### RQ.SRS-006.RBAC.Quotas.ResultBytes +version: 1.0 + +[ClickHouse] SHALL support setting **result bytes** quota to limit the total number +of bytes that can be returned as the result. + +#### RQ.SRS-006.RBAC.Quotas.ReadBytes +version: 1.0 + +[ClickHouse] SHALL support setting **read bytes** quota to limit the total number +of source bytes read from tables for running the query on all remote servers. + +#### RQ.SRS-006.RBAC.Quotas.ExecutionTime +version: 1.0 + +[ClickHouse] SHALL support setting **execution time** quota to limit the maximum +query execution time. + +#### Create Quotas + ##### RQ.SRS-006.RBAC.Quota.Create version: 1.0 @@ -2163,7 +1685,6 @@ of `{SECOND | MINUTE | HOUR | DAY | MONTH}`. Thus, the complete syntax SHALL be: `FOR INTERVAL number {SECOND | MINUTE | HOUR | DAY}` where number is some real number to define the interval. - ##### RQ.SRS-006.RBAC.Quota.Create.Interval.Randomized version: 1.0 @@ -2286,6 +1807,8 @@ CREATE QUOTA [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name] [TO {role [,...] | ALL | ALL EXCEPT role [,...]}] ``` +#### Alter Quota + ##### RQ.SRS-006.RBAC.Quota.Alter version: 1.0 @@ -2444,6 +1967,8 @@ ALTER QUOTA [IF EXIST] name [TO {user_or_role [,...] | NONE | ALL} [EXCEPT user_or_role [,...]]] ``` +#### Drop Quota + ##### RQ.SRS-006.RBAC.Quota.Drop version: 1.0 @@ -2472,6 +1997,8 @@ version: 1.0 DROP QUOTA [IF EXISTS] name [,name...] ``` +#### Show Quotas + ##### RQ.SRS-006.RBAC.Quota.ShowQuotas version: 1.0 @@ -2496,7 +2023,6 @@ version: 1.0 [ClickHouse] SHALL support the `SETTINGS` clause in the `SHOW QUOTAS` statement to define settings in the showing of all quotas. - ##### RQ.SRS-006.RBAC.Quota.ShowQuotas.Syntax version: 1.0 @@ -2505,6 +2031,9 @@ with the following syntax ``` sql SHOW QUOTAS ``` + +#### Show Create Quota + ##### RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Name version: 1.0 @@ -2532,6 +2061,34 @@ using the `SHOW CREATE QUOTA` statement. SHOW CREATE QUOTA [name | CURRENT] ``` +### Row Policy + +#### RQ.SRS-006.RBAC.RowPolicy +version: 1.0 + +[ClickHouse] SHALL support creation and manipulation of table **row policies** +that can be used to limit access to the table contents for a **user** or a **role** +using a specified **condition**. + +#### RQ.SRS-006.RBAC.RowPolicy.Condition +version: 1.0 + +[ClickHouse] SHALL support row policy **conditions** that can be any SQL +expression that returns a boolean. + +#### RQ.SRS-006.RBAC.RowPolicy.Restriction +version: 1.0 + +[ClickHouse] SHALL restrict all access to a table when a row policy with a condition is created on that table. +All users require a permissive row policy in order to view the table. + +#### RQ.SRS-006.RBAC.RowPolicy.Nesting +version: 1.0 + +[ClickHouse] SHALL restrict rows of tables or views created on top of a table with row policies according to those policies. + +#### Create Row Policy + ##### RQ.SRS-006.RBAC.RowPolicy.Create version: 1.0 @@ -2586,14 +2143,14 @@ version: 1.0 [ClickHouse] SHALL support specifying which rows are affected using the `FOR SELECT` clause in the `CREATE ROW POLICY` statement. -REQUIRES CONFIRMATION +REQUIRES CONDITION. ##### RQ.SRS-006.RBAC.RowPolicy.Create.Condition version: 1.0 [ClickHouse] SHALL support specifying a condition that that can be any SQL expression which returns a boolean using the `USING` -clause in the `CREATE ROW POLOCY` statement. +clause in the `CREATE ROW POLICY` statement. ##### RQ.SRS-006.RBAC.RowPolicy.Create.Assignment version: 1.0 @@ -2632,6 +2189,8 @@ CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name [ON CLUSTER cluster [TO {role [,...] | ALL | ALL EXCEPT role [,...]}] ``` +#### Alter Row Policy + ##### RQ.SRS-006.RBAC.RowPolicy.Alter version: 1.0 @@ -2738,6 +2297,8 @@ ALTER [ROW] POLICY [IF EXISTS] name [ON CLUSTER cluster_name] ON [database.]tabl [TO {role [,...] | ALL | ALL EXCEPT role [,...]}] ``` +#### Drop Row Policy + ##### RQ.SRS-006.RBAC.RowPolicy.Drop version: 1.0 @@ -2772,6 +2333,8 @@ version: 1.0 DROP [ROW] POLICY [IF EXISTS] name [,...] ON [database.]table [,...] [ON CLUSTER cluster_name] ``` +#### Show Create Row Policy + ##### RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy version: 1.0 @@ -2813,9 +2376,510 @@ version: 1.0 SHOW [ROW] POLICIES [ON [database.]table] ``` -#### Table Privileges +### Set Default Role -##### RQ.SRS-006.RBAC.Table.PublicTables +#### RQ.SRS-006.RBAC.SetDefaultRole +version: 1.0 + +[ClickHouse] SHALL support setting or changing granted roles to default for one or more +users using `SET DEFAULT ROLE` statement which +SHALL permanently change the default roles for the user or users if successful. + +#### RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser +version: 1.0 + +[ClickHouse] SHALL support setting or changing granted roles to default for +the current user using `CURRENT_USER` clause in the `SET DEFAULT ROLE` statement. + +#### RQ.SRS-006.RBAC.SetDefaultRole.All +version: 1.0 + +[ClickHouse] SHALL support setting or changing all granted roles to default +for one or more users using `ALL` clause in the `SET DEFAULT ROLE` statement. + +#### RQ.SRS-006.RBAC.SetDefaultRole.AllExcept +version: 1.0 + +[ClickHouse] SHALL support setting or changing all granted roles except those specified +to default for one or more users using `ALL EXCEPT` clause in the `SET DEFAULT ROLE` statement. + +#### RQ.SRS-006.RBAC.SetDefaultRole.None +version: 1.0 + +[ClickHouse] SHALL support removing all granted roles from default +for one or more users using `NONE` clause in the `SET DEFAULT ROLE` statement. + +#### RQ.SRS-006.RBAC.SetDefaultRole.Syntax +version: 1.0 + +[ClickHouse] SHALL support the following syntax for the `SET DEFAULT ROLE` statement. + +```sql +SET DEFAULT ROLE + {NONE | role [,...] | ALL | ALL EXCEPT role [,...]} + TO {user|CURRENT_USER} [,...] + +``` + +### Set Role + +#### RQ.SRS-006.RBAC.SetRole +version: 1.0 + +[ClickHouse] SHALL support activating role or roles for the current user +using `SET ROLE` statement. + +#### RQ.SRS-006.RBAC.SetRole.Default +version: 1.0 + +[ClickHouse] SHALL support activating default roles for the current user +using `DEFAULT` clause in the `SET ROLE` statement. + +#### RQ.SRS-006.RBAC.SetRole.None +version: 1.0 + +[ClickHouse] SHALL support activating no roles for the current user +using `NONE` clause in the `SET ROLE` statement. + +#### RQ.SRS-006.RBAC.SetRole.All +version: 1.0 + +[ClickHouse] SHALL support activating all roles for the current user +using `ALL` clause in the `SET ROLE` statement. + +#### RQ.SRS-006.RBAC.SetRole.AllExcept +version: 1.0 + +[ClickHouse] SHALL support activating all roles except those specified +for the current user using `ALL EXCEPT` clause in the `SET ROLE` statement. + +#### RQ.SRS-006.RBAC.SetRole.Syntax +version: 1.0 + +```sql +SET ROLE {DEFAULT | NONE | role [,...] | ALL | ALL EXCEPT role [,...]} +``` + +### Grant + +#### RQ.SRS-006.RBAC.Grant.Privilege.To +version: 1.0 + +[ClickHouse] SHALL support granting privileges to one or more users or roles using `TO` clause +in the `GRANT PRIVILEGE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser +version: 1.0 + +[ClickHouse] SHALL support granting privileges to current user using `TO CURRENT_USER` clause +in the `GRANT PRIVILEGE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Select +version: 1.0 + +[ClickHouse] SHALL support granting the **select** privilege to one or more users or roles +for a database or a table using the `GRANT SELECT` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Insert +version: 1.0 + +[ClickHouse] SHALL support granting the **insert** privilege to one or more users or roles +for a database or a table using the `GRANT INSERT` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Alter +version: 1.0 + +[ClickHouse] SHALL support granting the **alter** privilege to one or more users or roles +for a database or a table using the `GRANT ALTER` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Create +version: 1.0 + +[ClickHouse] SHALL support granting the **create** privilege to one or more users or roles +using the `GRANT CREATE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Drop +version: 1.0 + +[ClickHouse] SHALL support granting the **drop** privilege to one or more users or roles +using the `GRANT DROP` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Truncate +version: 1.0 + +[ClickHouse] SHALL support granting the **truncate** privilege to one or more users or roles +for a database or a table using `GRANT TRUNCATE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Optimize +version: 1.0 + +[ClickHouse] SHALL support granting the **optimize** privilege to one or more users or roles +for a database or a table using `GRANT OPTIMIZE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Show +version: 1.0 + +[ClickHouse] SHALL support granting the **show** privilege to one or more users or roles +for a database or a table using `GRANT SHOW` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.KillQuery +version: 1.0 + +[ClickHouse] SHALL support granting the **kill query** privilege to one or more users or roles +for a database or a table using `GRANT KILL QUERY` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement +version: 1.0 + +[ClickHouse] SHALL support granting the **access management** privileges to one or more users or roles +for a database or a table using `GRANT ACCESS MANAGEMENT` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.System +version: 1.0 + +[ClickHouse] SHALL support granting the **system** privileges to one or more users or roles +for a database or a table using `GRANT SYSTEM` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Introspection +version: 1.0 + +[ClickHouse] SHALL support granting the **introspection** privileges to one or more users or roles +for a database or a table using `GRANT INTROSPECTION` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Sources +version: 1.0 + +[ClickHouse] SHALL support granting the **sources** privileges to one or more users or roles +for a database or a table using `GRANT SOURCES` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.DictGet +version: 1.0 + +[ClickHouse] SHALL support granting the **dictGet** privilege to one or more users or roles +for a database or a table using `GRANT dictGet` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.None +version: 1.0 + +[ClickHouse] SHALL support granting no privileges to one or more users or roles +for a database or a table using `GRANT NONE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.All +version: 1.0 + +[ClickHouse] SHALL support granting the **all** privileges to one or more users or roles +using the `GRANT ALL` or `GRANT ALL PRIVILEGES` statements. + +#### RQ.SRS-006.RBAC.Grant.Privilege.GrantOption +version: 1.0 + +[ClickHouse] SHALL support granting the **grant option** privilege to one or more users or roles +for a database or a table using the `WITH GRANT OPTION` clause in the `GRANT` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.On +version: 1.0 + +[ClickHouse] SHALL support the `ON` clause in the `GRANT` privilege statement +which SHALL allow to specify one or more tables to which the privilege SHALL +be granted using the following patterns + +* `*.*` any table in any database +* `database.*` any table in the specified database +* `database.table` specific table in the specified database +* `*` any table in the current database +* `table` specific table in the current database + +#### RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns +version: 1.0 + +[ClickHouse] SHALL support granting the privilege **some_privilege** to one or more users or roles +for a database or a table using the `GRANT some_privilege(column)` statement for one column. +Multiple columns will be supported with `GRANT some_privilege(column1, column2...)` statement. +The privileges will be granted for only the specified columns. + +#### RQ.SRS-006.RBAC.Grant.Privilege.OnCluster +version: 1.0 + +[ClickHouse] SHALL support specifying cluster on which to grant privileges using the `ON CLUSTER` +clause in the `GRANT PRIVILEGE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Syntax +version: 1.0 + +[ClickHouse] SHALL support the following syntax for the `GRANT` statement that +grants explicit privileges to a user or a role. + +```sql +GRANT [ON CLUSTER cluster_name] privilege[(column_name [,...])] [,...] + ON {db.table|db.*|*.*|table|*} + TO {user | role | CURRENT_USER} [,...] + [WITH GRANT OPTION] +``` + +### Revoke + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Cluster +version: 1.0 + +[ClickHouse] SHALL support revoking privileges to one or more users or roles +for a database or a table on some specific cluster using the `REVOKE ON CLUSTER cluster_name` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Select +version: 1.0 + +[ClickHouse] SHALL support revoking the **select** privilege to one or more users or roles +for a database or a table using the `REVOKE SELECT` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Insert +version: 1.0 + +[ClickHouse] SHALL support revoking the **insert** privilege to one or more users or roles +for a database or a table using the `REVOKE INSERT` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Alter +version: 1.0 + +[ClickHouse] SHALL support revoking the **alter** privilege to one or more users or roles +for a database or a table using the `REVOKE ALTER` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Create +version: 1.0 + +[ClickHouse] SHALL support revoking the **create** privilege to one or more users or roles +using the `REVOKE CREATE` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Drop +version: 1.0 + +[ClickHouse] SHALL support revoking the **drop** privilege to one or more users or roles +using the `REVOKE DROP` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Truncate +version: 1.0 + +[ClickHouse] SHALL support revoking the **truncate** privilege to one or more users or roles +for a database or a table using the `REVOKE TRUNCATE` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Optimize +version: 1.0 + +[ClickHouse] SHALL support revoking the **optimize** privilege to one or more users or roles +for a database or a table using the `REVOKE OPTIMIZE` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Show +version: 1.0 + +[ClickHouse] SHALL support revoking the **show** privilege to one or more users or roles +for a database or a table using the `REVOKE SHOW` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery +version: 1.0 + +[ClickHouse] SHALL support revoking the **kill query** privilege to one or more users or roles +for a database or a table using the `REVOKE KILL QUERY` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement +version: 1.0 + +[ClickHouse] SHALL support revoking the **access management** privilege to one or more users or roles +for a database or a table using the `REVOKE ACCESS MANAGEMENT` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.System +version: 1.0 + +[ClickHouse] SHALL support revoking the **system** privilege to one or more users or roles +for a database or a table using the `REVOKE SYSTEM` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Introspection +version: 1.0 + +[ClickHouse] SHALL support revoking the **introspection** privilege to one or more users or roles +for a database or a table using the `REVOKE INTROSPECTION` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Sources +version: 1.0 + +[ClickHouse] SHALL support revoking the **sources** privilege to one or more users or roles +for a database or a table using the `REVOKE SOURCES` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.DictGet +version: 1.0 + +[ClickHouse] SHALL support revoking the **dictGet** privilege to one or more users or roles +for a database or a table using the `REVOKE dictGet` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.PrivilegeColumns +version: 1.0 + +[ClickHouse] SHALL support revoking the privilege **some_privilege** to one or more users or roles +for a database or a table using the `REVOKE some_privilege(column)` statement for one column. +Multiple columns will be supported with `REVOKE some_privilege(column1, column2...)` statement. +The privileges will be revoked for only the specified columns. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Multiple +version: 1.0 + +[ClickHouse] SHALL support revoking MULTIPLE **privileges** to one or more users or roles +for a database or a table using the `REVOKE privilege1, privilege2...` statement. +**privileges** refers to any set of Clickhouse defined privilege, whose hierarchy includes +SELECT, INSERT, ALTER, CREATE, DROP, TRUNCATE, OPTIMIZE, SHOW, KILL QUERY, ACCESS MANAGEMENT, +SYSTEM, INTROSPECTION, SOURCES, dictGet and all of their sub-privileges. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.All +version: 1.0 + +[ClickHouse] SHALL support revoking **all** privileges to one or more users or roles +for a database or a table using the `REVOKE ALL` or `REVOKE ALL PRIVILEGES` statements. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.None +version: 1.0 + +[ClickHouse] SHALL support revoking **no** privileges to one or more users or roles +for a database or a table using the `REVOKE NONE` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.On +version: 1.0 + +[ClickHouse] SHALL support the `ON` clause in the `REVOKE` privilege statement +which SHALL allow to specify one or more tables to which the privilege SHALL +be revoked using the following patterns + +* `db.table` specific table in the specified database +* `db.*` any table in the specified database +* `*.*` any table in any database +* `table` specific table in the current database +* `*` any table in the current database + +#### RQ.SRS-006.RBAC.Revoke.Privilege.From +version: 1.0 + +[ClickHouse] SHALL support the `FROM` clause in the `REVOKE` privilege statement +which SHALL allow to specify one or more users to which the privilege SHALL +be revoked using the following patterns + +* `{user | CURRENT_USER} [,...]` some combination of users by name, which may include the current user +* `ALL` all users +* `ALL EXCEPT {user | CURRENT_USER} [,...]` the logical reverse of the first pattern + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Syntax +version: 1.0 + +[ClickHouse] SHALL support the following syntax for the `REVOKE` statement that +revokes explicit privileges of a user or a role. + +```sql +REVOKE [ON CLUSTER cluster_name] privilege + [(column_name [,...])] [,...] + ON {db.table|db.*|*.*|table|*} + FROM {user | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user | CURRENT_USER} [,...] +``` + +### Grant Role + +#### RQ.SRS-006.RBAC.Grant.Role +version: 1.0 + +[ClickHouse] SHALL support granting one or more roles to +one or more users or roles using the `GRANT` role statement. + +#### RQ.SRS-006.RBAC.Grant.Role.CurrentUser +version: 1.0 + +[ClickHouse] SHALL support granting one or more roles to current user using +`TO CURRENT_USER` clause in the `GRANT` role statement. + +#### RQ.SRS-006.RBAC.Grant.Role.AdminOption +version: 1.0 + +[ClickHouse] SHALL support granting `admin option` privilege +to one or more users or roles using the `WITH ADMIN OPTION` clause +in the `GRANT` role statement. + +#### RQ.SRS-006.RBAC.Grant.Role.OnCluster +version: 1.0 + +[ClickHouse] SHALL support specifying cluster on which the user is to be granted one or more roles +using `ON CLUSTER` clause in the `GRANT` statement. + +#### RQ.SRS-006.RBAC.Grant.Role.Syntax +version: 1.0 + +[ClickHouse] SHALL support the following syntax for `GRANT` role statement + +``` sql +GRANT + ON CLUSTER cluster_name + role [, role ...] + TO {user | role | CURRENT_USER} [,...] + [WITH ADMIN OPTION] +``` + +### Revoke Role + +#### RQ.SRS-006.RBAC.Revoke.Role +version: 1.0 + +[ClickHouse] SHALL support revoking one or more roles from +one or more users or roles using the `REVOKE` role statement. + +#### RQ.SRS-006.RBAC.Revoke.Role.Keywords +version: 1.0 + +[ClickHouse] SHALL support revoking one or more roles from +special groupings of one or more users or roles with the `ALL`, `ALL EXCEPT`, +and `CURRENT_USER` keywords. + +#### RQ.SRS-006.RBAC.Revoke.Role.Cluster +version: 1.0 + +[ClickHouse] SHALL support revoking one or more roles from +one or more users or roles from one or more clusters +using the `REVOKE ON CLUSTER` role statement. + +#### RQ.SRS-006.RBAC.Revoke.AdminOption +version: 1.0 + +[ClickHouse] SHALL support revoking `admin option` privilege +in one or more users or roles using the `ADMIN OPTION FOR` clause +in the `REVOKE` role statement. + +#### RQ.SRS-006.RBAC.Revoke.Role.Syntax +version: 1.0 + +[ClickHouse] SHALL support the following syntax for the `REVOKE` role statement + +```sql +REVOKE [ON CLUSTER cluster_name] [ADMIN OPTION FOR] + role [,...] + FROM {user | role | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user_name | role_name | CURRENT_USER} [,...] +``` + +### Show Grants + +#### RQ.SRS-006.RBAC.Show.Grants +version: 1.0 + +[ClickHouse] SHALL support listing all the privileges granted to current user and role +using the `SHOW GRANTS` statement. + +#### RQ.SRS-006.RBAC.Show.Grants.For +version: 1.0 + +[ClickHouse] SHALL support listing all the privileges granted to a user or a role +using the `FOR` clause in the `SHOW GRANTS` statement. + +#### RQ.SRS-006.RBAC.Show.Grants.Syntax +version: 1.0 + +[Clickhouse] SHALL use the following syntax for the `SHOW GRANTS` statement + +``` sql +SHOW GRANTS [FOR user_or_role] +``` + +### Table Privileges + +#### RQ.SRS-006.RBAC.Table.PublicTables version: 1.0 [ClickHouse] SHALL support that a user without any privileges will be able to access the following tables @@ -2825,7 +2889,7 @@ version: 1.0 * system.contributors * system.functions -##### RQ.SRS-006.RBAC.Table.SensitiveTables +#### RQ.SRS-006.RBAC.Table.SensitiveTables version: 1.0 [ClickHouse] SHALL not support a user with no privileges accessing the following `system` tables: @@ -2842,15 +2906,15 @@ version: 1.0 * zookeeper * macros -#### Distributed Tables +### Distributed Tables -##### RQ.SRS-006.RBAC.DistributedTable.Create +#### RQ.SRS-006.RBAC.DistributedTable.Create version: 1.0 [ClickHouse] SHALL successfully `CREATE` a distributed table if and only if the user has **create table** privilege on the table and **remote** privilege on *.* -##### RQ.SRS-006.RBAC.DistributedTable.Select +#### RQ.SRS-006.RBAC.DistributedTable.Select version: 1.0 [ClickHouse] SHALL successfully `SELECT` from a distributed table if and only if @@ -2858,7 +2922,7 @@ the user has **select** privilege on the table and on the remote table specified Does not require **select** privilege for the remote table if the remote table does not exist on the same server as the user. -##### RQ.SRS-006.RBAC.DistributedTable.Insert +#### RQ.SRS-006.RBAC.DistributedTable.Insert version: 1.0 [ClickHouse] SHALL successfully `INSERT` into a distributed table if and only if @@ -2867,7 +2931,7 @@ the user has **insert** privilege on the table and on the remote table specified Does not require **insert** privilege for the remote table if the remote table does not exist on the same server as the user, insert executes into the remote table on a different server. -##### RQ.SRS-006.RBAC.DistributedTable.SpecialTables +#### RQ.SRS-006.RBAC.DistributedTable.SpecialTables version: 1.0 [ClickHouse] SHALL successfully execute a query using a distributed table that uses one of the special tables if and only if @@ -2877,29 +2941,29 @@ Special tables include: * distributed table * source table of a materialized view -##### RQ.SRS-006.RBAC.DistributedTable.LocalUser +#### RQ.SRS-006.RBAC.DistributedTable.LocalUser version: 1.0 [ClickHouse] SHALL successfully execute a query using a distributed table from a user present locally, but not remotely. -##### RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges +#### RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges version: 1.0 [ClickHouse] SHALL successfully execute a query using a distributed table by a user that exists on multiple nodes if and only if the user has the required privileges on the node the query is being executed from. -#### Views +### Views -##### View +#### View -###### RQ.SRS-006.RBAC.View +##### RQ.SRS-006.RBAC.View version: 1.0 [ClickHouse] SHALL support controlling access to **create**, **select** and **drop** privileges for a view for users or roles. -###### RQ.SRS-006.RBAC.View.Create +##### RQ.SRS-006.RBAC.View.Create version: 1.0 [ClickHouse] SHALL only successfully execute a `CREATE VIEW` command if and only if @@ -2917,7 +2981,7 @@ CREATE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNION ALL CREATE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2 ``` -###### RQ.SRS-006.RBAC.View.Select +##### RQ.SRS-006.RBAC.View.Select version: 1.0 [ClickHouse] SHALL only successfully `SELECT` from a view if and only if @@ -2937,21 +3001,21 @@ CREATE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2 SELECT * FROM view ``` -###### RQ.SRS-006.RBAC.View.Drop +##### RQ.SRS-006.RBAC.View.Drop version: 1.0 [ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if the user has **drop view** privilege on that view either explicitly or through a role. -##### Materialized View +#### Materialized View -###### RQ.SRS-006.RBAC.MaterializedView +##### RQ.SRS-006.RBAC.MaterializedView version: 1.0 [ClickHouse] SHALL support controlling access to **create**, **select**, **alter** and **drop** privileges for a materialized view for users or roles. -###### RQ.SRS-006.RBAC.MaterializedView.Create +##### RQ.SRS-006.RBAC.MaterializedView.Create version: 1.0 [ClickHouse] SHALL only successfully execute a `CREATE MATERIALIZED VIEW` command if and only if @@ -2983,7 +3047,7 @@ For example, CREATE MATERIALIZED VIEW view TO target_table AS SELECT * FROM source_table ``` -###### RQ.SRS-006.RBAC.MaterializedView.Select +##### RQ.SRS-006.RBAC.MaterializedView.Select version: 1.0 [ClickHouse] SHALL only successfully `SELECT` from a materialized view if and only if @@ -3003,25 +3067,25 @@ CREATE MATERIALIZED VIEW view0 ENGINE = Memory AS SELECT column FROM view1 UNION SELECT * FROM view ``` -###### RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable +##### RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable version: 1.0 [ClickHouse] SHALL only successfully `SELECT` from the target table, implicit or explicit, of a materialized view if and only if the user has `SELECT` privilege for the table, either explicitly or through a role. -###### RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable +##### RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable version: 1.0 [ClickHouse] SHALL only successfully `SELECT` from the source table of a materialized view if and only if the user has `SELECT` privilege for the table, either explicitly or through a role. -###### RQ.SRS-006.RBAC.MaterializedView.Drop +##### RQ.SRS-006.RBAC.MaterializedView.Drop version: 1.0 [ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if the user has **drop view** privilege on that view either explicitly or through a role. -###### RQ.SRS-006.RBAC.MaterializedView.ModifyQuery +##### RQ.SRS-006.RBAC.MaterializedView.ModifyQuery version: 1.0 [ClickHouse] SHALL only successfully execute a `MODIFY QUERY` command if and only if @@ -3034,33 +3098,33 @@ For example, ALTER TABLE view MODIFY QUERY SELECT * FROM source_table ``` -###### RQ.SRS-006.RBAC.MaterializedView.Insert +##### RQ.SRS-006.RBAC.MaterializedView.Insert version: 1.0 [ClickHouse] SHALL only succesfully `INSERT` into a materialized view if and only if the user has `INSERT` privilege on the view, either explicitly or through a role. -###### RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable +##### RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable version: 1.0 [ClickHouse] SHALL only succesfully `INSERT` into a source table of a materialized view if and only if the user has `INSERT` privilege on the source table, either explicitly or through a role. -###### RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable +##### RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable version: 1.0 [ClickHouse] SHALL only succesfully `INSERT` into a target table of a materialized view if and only if the user has `INSERT` privelege on the target table, either explicitly or through a role. -##### Live View +#### Live View -###### RQ.SRS-006.RBAC.LiveView +##### RQ.SRS-006.RBAC.LiveView version: 1.0 [ClickHouse] SHALL support controlling access to **create**, **select**, **alter** and **drop** privileges for a live view for users or roles. -###### RQ.SRS-006.RBAC.LiveView.Create +##### RQ.SRS-006.RBAC.LiveView.Create version: 1.0 [ClickHouse] SHALL only successfully execute a `CREATE LIVE VIEW` command if and only if @@ -3078,7 +3142,7 @@ CREATE LIVE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNIO CREATE LIVE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2 ``` -###### RQ.SRS-006.RBAC.LiveView.Select +##### RQ.SRS-006.RBAC.LiveView.Select version: 1.0 [ClickHouse] SHALL only successfully `SELECT` from a live view if and only if @@ -3098,28 +3162,28 @@ CREATE LIVE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM SELECT * FROM view ``` -###### RQ.SRS-006.RBAC.LiveView.Drop +##### RQ.SRS-006.RBAC.LiveView.Drop version: 1.0 [ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if the user has **drop view** privilege on that view either explicitly or through a role. -###### RQ.SRS-006.RBAC.LiveView.Refresh +##### RQ.SRS-006.RBAC.LiveView.Refresh version: 1.0 [ClickHouse] SHALL only successfully execute an `ALTER LIVE VIEW REFRESH` command if and only if the user has **refresh** privilege on that view either explicitly or through a role. -#### Select +### Select -##### RQ.SRS-006.RBAC.Select +#### RQ.SRS-006.RBAC.Select version: 1.0 [ClickHouse] SHALL execute `SELECT` if and only if the user has the **select** privilege for the destination table either because of the explicit grant or through one of the roles assigned to the user. -##### RQ.SRS-006.RBAC.Select.Column +#### RQ.SRS-006.RBAC.Select.Column version: 1.0 [ClickHouse] SHALL support granting or revoking **select** privilege @@ -3128,7 +3192,7 @@ Any `SELECT` statements SHALL not to be executed, unless the user has the **select** privilege for the destination column either because of the explicit grant or through one of the roles assigned to the user. -##### RQ.SRS-006.RBAC.Select.Cluster +#### RQ.SRS-006.RBAC.Select.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **select** privilege @@ -3136,7 +3200,7 @@ on a specified cluster to one or more **users** or **roles**. Any `SELECT` statements SHALL succeed only on nodes where the table exists and privilege was granted. -##### RQ.SRS-006.RBAC.Select.TableEngines +#### RQ.SRS-006.RBAC.Select.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **select** privilege @@ -3157,16 +3221,16 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -#### Insert +### Insert -##### RQ.SRS-006.RBAC.Insert +#### RQ.SRS-006.RBAC.Insert version: 1.0 [ClickHouse] SHALL execute `INSERT INTO` if and only if the user has the **insert** privilege for the destination table either because of the explicit grant or through one of the roles assigned to the user. -##### RQ.SRS-006.RBAC.Insert.Column +#### RQ.SRS-006.RBAC.Insert.Column version: 1.0 [ClickHouse] SHALL support granting or revoking **insert** privilege @@ -3175,7 +3239,7 @@ Any `INSERT INTO` statements SHALL not to be executed, unless the user has the **insert** privilege for the destination column either because of the explicit grant or through one of the roles assigned to the user. -##### RQ.SRS-006.RBAC.Insert.Cluster +#### RQ.SRS-006.RBAC.Insert.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **insert** privilege @@ -3183,7 +3247,7 @@ on a specified cluster to one or more **users** or **roles**. Any `INSERT INTO` statements SHALL succeed only on nodes where the table exists and privilege was granted. -##### RQ.SRS-006.RBAC.Insert.TableEngines +#### RQ.SRS-006.RBAC.Insert.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **insert** privilege @@ -3204,11 +3268,11 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -#### Alter +### Alter -##### Alter Column +#### Alter Column -###### RQ.SRS-006.RBAC.Privileges.AlterColumn +##### RQ.SRS-006.RBAC.Privileges.AlterColumn version: 1.0 [ClickHouse] SHALL support controlling access to the **alter column** privilege @@ -3218,19 +3282,19 @@ return an error, unless the user has the **alter column** privilege for the destination table either because of the explicit grant or through one of the roles assigned to the user. -###### RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant version: 1.0 [ClickHouse] SHALL support granting **alter column** privilege for a database or a specific table to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter column** privilege for a database or a specific table to one or more **users** or **roles** -###### RQ.SRS-006.RBAC.Privileges.AlterColumn.Column +##### RQ.SRS-006.RBAC.Privileges.AlterColumn.Column version: 1.0 [ClickHouse] SHALL support granting or revoking **alter column** privilege @@ -3239,7 +3303,7 @@ Any `ALTER TABLE ... ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN` statements SHALL retu unless the user has the **alter column** privilege for the destination column either because of the explicit grant or through one of the roles assigned to the user. -###### RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster +##### RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **alter column** privilege @@ -3247,7 +3311,7 @@ on a specified cluster to one or more **users** or **roles**. Any `ALTER TABLE ... ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN` statements SHALL succeed only on nodes where the table exists and privilege was granted. -###### RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter column** privilege @@ -3268,9 +3332,9 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Index +#### Alter Index -###### RQ.SRS-006.RBAC.Privileges.AlterIndex +##### RQ.SRS-006.RBAC.Privileges.AlterIndex version: 1.0 [ClickHouse] SHALL support controlling access to the **alter index** privilege @@ -3280,19 +3344,19 @@ return an error, unless the user has the **alter index** privilege for the destination table either because of the explicit grant or through one of the roles assigned to the user. -###### RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant version: 1.0 [ClickHouse] SHALL support granting **alter index** privilege for a database or a specific table to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter index** privilege for a database or a specific table to one or more **users** or **roles** -###### RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster +##### RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **alter index** privilege @@ -3300,7 +3364,7 @@ on a specified cluster to one or more **users** or **roles**. Any `ALTER TABLE ... ORDER BY | ADD|DROP|MATERIALIZE|CLEAR INDEX` statements SHALL succeed only on nodes where the table exists and privilege was granted. -###### RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter index** privilege @@ -3321,9 +3385,9 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Constraint +#### Alter Constraint -###### RQ.SRS-006.RBAC.Privileges.AlterConstraint +##### RQ.SRS-006.RBAC.Privileges.AlterConstraint version: 1.0 [ClickHouse] SHALL support controlling access to the **alter constraint** privilege @@ -3333,19 +3397,19 @@ return an error, unless the user has the **alter constraint** privilege for the destination table either because of the explicit grant or through one of the roles assigned to the user. -###### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant version: 1.0 [ClickHouse] SHALL support granting **alter constraint** privilege for a database or a specific table to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter constraint** privilege for a database or a specific table to one or more **users** or **roles** -###### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster +##### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **alter constraint** privilege @@ -3353,7 +3417,7 @@ on a specified cluster to one or more **users** or **roles**. Any `ALTER TABLE ... ADD|DROP CONSTRAINT` statements SHALL succeed only on nodes where the table exists and privilege was granted. -###### RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter constraint** privilege @@ -3374,9 +3438,9 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter TTL +#### Alter TTL -###### RQ.SRS-006.RBAC.Privileges.AlterTTL +##### RQ.SRS-006.RBAC.Privileges.AlterTTL version: 1.0 [ClickHouse] SHALL support controlling access to the **alter ttl** or **alter materialize ttl** privilege @@ -3386,19 +3450,19 @@ return an error, unless the user has the **alter ttl** or **alter materialize tt the destination table either because of the explicit grant or through one of the roles assigned to the user. -###### RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant version: 1.0 [ClickHouse] SHALL support granting **alter ttl** or **alter materialize ttl** privilege for a database or a specific table to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter ttl** or **alter materialize ttl** privilege for a database or a specific table to one or more **users** or **roles** -###### RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster +##### RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **alter ttl** or **alter materialize ttl** privilege @@ -3406,7 +3470,7 @@ on a specified cluster to one or more **users** or **roles**. Any `ALTER TABLE ... ALTER TTL | ALTER MATERIALIZE TTL` statements SHALL succeed only on nodes where the table exists and privilege was granted. -###### RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter ttl** or **alter materialize ttl** privilege @@ -3414,9 +3478,9 @@ on tables created using the following engines * MergeTree -##### Alter Settings +#### Alter Settings -###### RQ.SRS-006.RBAC.Privileges.AlterSettings +##### RQ.SRS-006.RBAC.Privileges.AlterSettings version: 1.0 [ClickHouse] SHALL support controlling access to the **alter settings** privilege @@ -3427,19 +3491,19 @@ the destination table either because of the explicit grant or through one of the roles assigned to the user. The **alter settings** privilege allows modifying table engine settings. It doesn’t affect settings or server configuration parameters. -###### RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant version: 1.0 [ClickHouse] SHALL support granting **alter settings** privilege for a database or a specific table to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter settings** privilege for a database or a specific table to one or more **users** or **roles** -###### RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster +##### RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **alter settings** privilege @@ -3447,7 +3511,7 @@ on a specified cluster to one or more **users** or **roles**. Any `ALTER TABLE ... MODIFY SETTING setting` statements SHALL succeed only on nodes where the table exists and privilege was granted. -###### RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter settings** privilege @@ -3468,27 +3532,27 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Update +#### Alter Update -###### RQ.SRS-006.RBAC.Privileges.AlterUpdate +##### RQ.SRS-006.RBAC.Privileges.AlterUpdate version: 1.0 [ClickHouse] SHALL successfully execute `ALTER UPDATE` statement if and only if the user has **alter update** privilege for that column, either directly or through a role. -###### RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant version: 1.0 [ClickHouse] SHALL support granting **alter update** privilege on a column level to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter update** privilege on a column level from one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter update** privilege @@ -3509,27 +3573,27 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Delete +#### Alter Delete -###### RQ.SRS-006.RBAC.Privileges.AlterDelete +##### RQ.SRS-006.RBAC.Privileges.AlterDelete version: 1.0 [ClickHouse] SHALL successfully execute `ALTER DELETE` statement if and only if the user has **alter delete** privilege for that table, either directly or through a role. -###### RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant version: 1.0 [ClickHouse] SHALL support granting **alter delete** privilege on a column level to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter delete** privilege on a column level from one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter delete** privilege @@ -3550,27 +3614,27 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Freeze Partition +#### Alter Freeze Partition -###### RQ.SRS-006.RBAC.Privileges.AlterFreeze +##### RQ.SRS-006.RBAC.Privileges.AlterFreeze version: 1.0 [ClickHouse] SHALL successfully execute `ALTER FREEZE` statement if and only if the user has **alter freeze** privilege for that table, either directly or through a role. -###### RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant version: 1.0 [ClickHouse] SHALL support granting **alter freeze** privilege on a column level to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter freeze** privilege on a column level from one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter freeze** privilege @@ -3591,27 +3655,27 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Fetch Partition +#### Alter Fetch Partition -###### RQ.SRS-006.RBAC.Privileges.AlterFetch +##### RQ.SRS-006.RBAC.Privileges.AlterFetch version: 1.0 [ClickHouse] SHALL successfully execute `ALTER FETCH` statement if and only if the user has **alter fetch** privilege for that table, either directly or through a role. -###### RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant version: 1.0 [ClickHouse] SHALL support granting **alter fetch** privilege on a column level to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter fetch** privilege on a column level from one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter fetch** privilege @@ -3625,9 +3689,9 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Move Partition +#### Alter Move Partition -###### RQ.SRS-006.RBAC.Privileges.AlterMove +##### RQ.SRS-006.RBAC.Privileges.AlterMove version: 1.0 [ClickHouse] SHALL successfully execute `ALTER MOVE` statement if and only if the user has **alter move**, **select**, and **alter delete** privilege on the source table @@ -3637,19 +3701,19 @@ For example, ALTER TABLE source_table MOVE PARTITION 1 TO target_table ``` -###### RQ.SRS-006.RBAC.Privileges.AlterMove.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterMove.Grant version: 1.0 [ClickHouse] SHALL support granting **alter move** privilege on a column level to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter move** privilege on a column level from one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter move** privilege @@ -3670,6 +3734,8 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree +### Create + #### RQ.SRS-006.RBAC.Privileges.CreateTable version: 1.0 @@ -3706,6 +3772,8 @@ version: 1.0 [ClickHouse] SHALL successfully execute `CREATE TEMPORARY TABLE` statement if and only if the user has **create temporary table** privilege on the table, either directly or through a role. +### Attach + #### RQ.SRS-006.RBAC.Privileges.AttachDatabase version: 1.0 @@ -3730,6 +3798,8 @@ version: 1.0 [ClickHouse] SHALL successfully execute `ATTACH TABLE` statement if and only if the user has **create table** privilege on the table, either directly or through a role. +### Drop + #### RQ.SRS-006.RBAC.Privileges.DropTable version: 1.0 @@ -3748,6 +3818,8 @@ version: 1.0 [ClickHouse] SHALL successfully execute `DROP DICTIONARY` statement if and only if the user has **drop dictionary** privilege on the dictionary, either directly or through a role. +### Detach + #### RQ.SRS-006.RBAC.Privileges.DetachTable version: 1.0 @@ -3772,354 +3844,360 @@ version: 1.0 [ClickHouse] SHALL successfully execute `DETACH DICTIONARY` statement if and only if the user has **drop dictionary** privilege on the dictionary, either directly or through a role. +### Truncate + #### RQ.SRS-006.RBAC.Privileges.Truncate version: 1.0 [ClickHouse] SHALL successfully execute `TRUNCATE TABLE` statement if and only if the user has **truncate table** privilege on the table, either directly or through a role. +### Optimize + #### RQ.SRS-006.RBAC.Privileges.Optimize version: 1.0 [ClickHouse] SHALL successfully execute `OPTIMIZE TABLE` statement if and only if the user has **optimize table** privilege on the table, either directly or through a role. +### Kill Query + #### RQ.SRS-006.RBAC.Privileges.KillQuery version: 1.0 [ClickHouse] SHALL successfully execute `KILL QUERY` statement if and only if the user has **kill query** privilege, either directly or through a role. -#### Kill Mutation +### Kill Mutation -##### RQ.SRS-006.RBAC.Privileges.KillMutation +#### RQ.SRS-006.RBAC.Privileges.KillMutation version: 1.0 [ClickHouse] SHALL successfully execute `KILL MUTATION` statement if and only if the user has the privilege that created the mutation, either directly or through a role. For example, to `KILL MUTATION` after `ALTER UPDATE` query, the user needs `ALTER UPDATE` privilege. -##### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate +#### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate version: 1.0 [ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER UPDATE` mutation if and only if the user has `ALTER UPDATE` privilege on the table where the mutation was created, either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete +#### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete version: 1.0 [ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER DELETE` mutation if and only if the user has `ALTER DELETE` privilege on the table where the mutation was created, either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn +#### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn version: 1.0 [ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER DROP COLUMN` mutation if and only if the user has `ALTER DROP COLUMN` privilege on the table where the mutation was created, either directly or through a role. -#### Show +### Show -##### RQ.SRS-006.RBAC.ShowTables.Privilege +#### RQ.SRS-006.RBAC.ShowTables.Privilege version: 1.0 [ClickHouse] SHALL grant **show tables** privilege on a table to a user if that user has recieved any grant, including `SHOW TABLES`, on that table, either directly or through a role. -##### RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW TABLES` statement if and only if the user has **show tables** privilege, or any privilege on the table either directly or through a role. -##### RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege +#### RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `EXISTS table` statement if and only if the user has **show tables** privilege, or any privilege on the table either directly or through a role. -##### RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege +#### RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `CHECK table` statement if and only if the user has **show tables** privilege, or any privilege on the table either directly or through a role. -##### RQ.SRS-006.RBAC.ShowDatabases.Privilege +#### RQ.SRS-006.RBAC.ShowDatabases.Privilege version: 1.0 [ClickHouse] SHALL grant **show databases** privilege on a database to a user if that user has recieved any grant, including `SHOW DATABASES`, on that table, either directly or through a role. -##### RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW DATABASES` statement if and only if the user has **show databases** privilege, or any privilege on the database either directly or through a role. -##### RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE DATABASE` statement if and only if the user has **show databases** privilege, or any privilege on the database either directly or through a role. -##### RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege +#### RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `USE database` statement if and only if the user has **show databases** privilege, or any privilege on the database either directly or through a role. -##### RQ.SRS-006.RBAC.ShowColumns.Privilege +#### RQ.SRS-006.RBAC.ShowColumns.Privilege version: 1.0 [ClickHouse] SHALL support granting or revoking the `SHOW COLUMNS` privilege. -##### RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE TABLE` statement if and only if the user has **show columns** privilege on that table, either directly or through a role. -##### RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege +#### RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `DESCRIBE table` statement if and only if the user has **show columns** privilege on that table, either directly or through a role. -##### RQ.SRS-006.RBAC.ShowDictionaries.Privilege +#### RQ.SRS-006.RBAC.ShowDictionaries.Privilege version: 1.0 [ClickHouse] SHALL grant **show dictionaries** privilege on a dictionary to a user if that user has recieved any grant, including `SHOW DICTIONARIES`, on that dictionary, either directly or through a role. -##### RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW DICTIONARIES` statement if and only if the user has **show dictionaries** privilege, or any privilege on the dictionary either directly or through a role. -##### RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE DICTIONARY` statement if and only if the user has **show dictionaries** privilege, or any privilege on the dictionary either directly or through a role. -##### RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege +#### RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `EXISTS dictionary` statement if and only if the user has **show dictionaries** privilege, or any privilege on the dictionary either directly or through a role. -#### Access Management +### Access Management -##### RQ.SRS-006.RBAC.Privileges.CreateUser +#### RQ.SRS-006.RBAC.Privileges.CreateUser version: 1.0 [ClickHouse] SHALL successfully execute `CREATE USER` statement if and only if the user has **create user** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole +#### RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole version: 1.0 [ClickHouse] SHALL successfully execute `CREATE USER` statement with `DEFAULT ROLE ` clause if and only if the user has **create user** privilege and the role with **admin option**, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.AlterUser +#### RQ.SRS-006.RBAC.Privileges.AlterUser version: 1.0 [ClickHouse] SHALL successfully execute `ALTER USER` statement if and only if the user has **alter user** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.DropUser +#### RQ.SRS-006.RBAC.Privileges.DropUser version: 1.0 [ClickHouse] SHALL successfully execute `DROP USER` statement if and only if the user has **drop user** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.CreateRole +#### RQ.SRS-006.RBAC.Privileges.CreateRole version: 1.0 [ClickHouse] SHALL successfully execute `CREATE ROLE` statement if and only if the user has **create role** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.AlterRole +#### RQ.SRS-006.RBAC.Privileges.AlterRole version: 1.0 [ClickHouse] SHALL successfully execute `ALTER ROLE` statement if and only if the user has **alter role** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.DropRole +#### RQ.SRS-006.RBAC.Privileges.DropRole version: 1.0 [ClickHouse] SHALL successfully execute `DROP ROLE` statement if and only if the user has **drop role** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.CreateRowPolicy +#### RQ.SRS-006.RBAC.Privileges.CreateRowPolicy version: 1.0 [ClickHouse] SHALL successfully execute `CREATE ROW POLICY` statement if and only if the user has **create row policy** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.AlterRowPolicy +#### RQ.SRS-006.RBAC.Privileges.AlterRowPolicy version: 1.0 [ClickHouse] SHALL successfully execute `ALTER ROW POLICY` statement if and only if the user has **alter row policy** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.DropRowPolicy +#### RQ.SRS-006.RBAC.Privileges.DropRowPolicy version: 1.0 [ClickHouse] SHALL successfully execute `DROP ROW POLICY` statement if and only if the user has **drop row policy** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.CreateQuota +#### RQ.SRS-006.RBAC.Privileges.CreateQuota version: 1.0 [ClickHouse] SHALL successfully execute `CREATE QUOTA` statement if and only if the user has **create quota** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.AlterQuota +#### RQ.SRS-006.RBAC.Privileges.AlterQuota version: 1.0 [ClickHouse] SHALL successfully execute `ALTER QUOTA` statement if and only if the user has **alter quota** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.DropQuota +#### RQ.SRS-006.RBAC.Privileges.DropQuota version: 1.0 [ClickHouse] SHALL successfully execute `DROP QUOTA` statement if and only if the user has **drop quota** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile +#### RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile version: 1.0 [ClickHouse] SHALL successfully execute `CREATE SETTINGS PROFILE` statement if and only if the user has **create settings profile** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile +#### RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile version: 1.0 [ClickHouse] SHALL successfully execute `ALTER SETTINGS PROFILE` statement if and only if the user has **alter settings profile** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.DropSettingsProfile +#### RQ.SRS-006.RBAC.Privileges.DropSettingsProfile version: 1.0 [ClickHouse] SHALL successfully execute `DROP SETTINGS PROFILE` statement if and only if the user has **drop settings profile** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.RoleAdmin +#### RQ.SRS-006.RBAC.Privileges.RoleAdmin version: 1.0 [ClickHouse] SHALL successfully execute any role grant or revoke by a user with `ROLE ADMIN` privilege. -##### Show Access +#### Show Access -###### RQ.SRS-006.RBAC.ShowUsers.Privilege +##### RQ.SRS-006.RBAC.ShowUsers.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `SHOW USERS` privilege when the user is granted `SHOW USERS`, `SHOW CREATE USER`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`. -###### RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW USERS` statement if and only if the user has **show users** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE USER` statement if and only if the user has **show users** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowRoles.Privilege +##### RQ.SRS-006.RBAC.ShowRoles.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `SHOW ROLES` privilege when the user is granted `SHOW ROLES`, `SHOW CREATE ROLE`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`. -###### RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW ROLES` statement if and only if the user has **show roles** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE ROLE` statement if and only if the user has **show roles** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowRowPolicies.Privilege +##### RQ.SRS-006.RBAC.ShowRowPolicies.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `SHOW ROW POLICIES` privilege when the user is granted `SHOW ROW POLICIES`, `SHOW POLICIES`, `SHOW CREATE ROW POLICY`, `SHOW CREATE POLICY`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`. -###### RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW ROW POLICIES` or `SHOW POLICIES` statement if and only if the user has **show row policies** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE ROW POLICY` or `SHOW CREATE POLICY` statement if and only if the user has **show row policies** privilege,either directly or through a role. -###### RQ.SRS-006.RBAC.ShowQuotas.Privilege +##### RQ.SRS-006.RBAC.ShowQuotas.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `SHOW QUOTAS` privilege when the user is granted `SHOW QUOTAS`, `SHOW CREATE QUOTA`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`. -###### RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW QUOTAS` statement if and only if the user has **show quotas** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE QUOTA` statement if and only if the user has **show quotas** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege +##### RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `SHOW SETTINGS PROFILES` privilege when the user is granted `SHOW SETTINGS PROFILES`, `SHOW PROFILES`, `SHOW CREATE SETTINGS PROFILE`, `SHOW SETTINGS PROFILE`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`. -###### RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW SETTINGS PROFILES` or `SHOW PROFILES` statement if and only if the user has **show settings profiles** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE SETTINGS PROFILE` or `SHOW CREATE PROFILE` statement if and only if the user has **show settings profiles** privilege, either directly or through a role. -#### dictGet +### dictGet -##### RQ.SRS-006.RBAC.dictGet.Privilege +#### RQ.SRS-006.RBAC.dictGet.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `dictGet` privilege when the user is granted `dictGet`, `dictHas`, `dictGetHierarchy`, or `dictIsIn`. -##### RQ.SRS-006.RBAC.dictGet.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictGet.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictGet` statement if and only if the user has **dictGet** privilege on that dictionary, either directly or through a role. -##### RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictGet[TYPE]` statement @@ -4141,270 +4219,283 @@ Available types: * UUID * String -##### RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictGetOrDefault` statement if and only if the user has **dictGet** privilege on that dictionary, either directly or through a role. -##### RQ.SRS-006.RBAC.dictHas.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictHas.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictHas` statement if and only if the user has **dictGet** privilege, either directly or through a role. -##### RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictGetHierarchy` statement if and only if the user has **dictGet** privilege, either directly or through a role. -##### RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictIsIn` statement if and only if the user has **dictGet** privilege, either directly or through a role. -#### Introspection +### Introspection -##### RQ.SRS-006.RBAC.Privileges.Introspection +#### RQ.SRS-006.RBAC.Privileges.Introspection version: 1.0 [ClickHouse] SHALL successfully grant `INTROSPECTION` privilege when the user is granted `INTROSPECTION` or `INTROSPECTION FUNCTIONS`. -##### RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine +#### RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine version: 1.0 [ClickHouse] SHALL successfully execute `addressToLine` statement if and only if the user has **introspection** privilege, either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol +#### RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol version: 1.0 [ClickHouse] SHALL successfully execute `addressToSymbol` statement if and only if the user has **introspection** privilege, either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Introspection.demangle +#### RQ.SRS-006.RBAC.Privileges.Introspection.demangle version: 1.0 [ClickHouse] SHALL successfully execute `demangle` statement if and only if the user has **introspection** privilege, either directly or through a role. -#### System +### System -##### RQ.SRS-006.RBAC.Privileges.System.Shutdown +#### RQ.SRS-006.RBAC.Privileges.System.Shutdown version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM SHUTDOWN` privilege when the user is granted `SYSTEM`, `SYSTEM SHUTDOWN`, `SHUTDOWN`,or `SYSTEM KILL`. -##### RQ.SRS-006.RBAC.Privileges.System.DropCache +#### RQ.SRS-006.RBAC.Privileges.System.DropCache version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM DROP CACHE` privilege when the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, or `DROP CACHE`. -##### RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS +#### RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM DROP DNS CACHE` privilege when the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP DNS CACHE`, `SYSTEM DROP DNS`, `DROP DNS CACHE`, or `DROP DNS`. -##### RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark +#### RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM DROP MARK CACHE` privilege when the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP MARK CACHE`, `SYSTEM DROP MARK`, `DROP MARK CACHE`, or `DROP MARKS`. -##### RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed +#### RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM DROP UNCOMPRESSED CACHE` privilege when the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP UNCOMPRESSED CACHE`, `SYSTEM DROP UNCOMPRESSED`, `DROP UNCOMPRESSED CACHE`, or `DROP UNCOMPRESSED`. -##### RQ.SRS-006.RBAC.Privileges.System.Reload +#### RQ.SRS-006.RBAC.Privileges.System.Reload version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RELOAD` privilege when the user is granted `SYSTEM` or `SYSTEM RELOAD`. -##### RQ.SRS-006.RBAC.Privileges.System.Reload.Config +#### RQ.SRS-006.RBAC.Privileges.System.Reload.Config version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RELOAD CONFIG` privilege when the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD CONFIG`, or `RELOAD CONFIG`. -##### RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary +#### RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RELOAD DICTIONARY` privilege when the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARIES`, `RELOAD DICTIONARIES`, or `RELOAD DICTIONARY`. -##### RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries +#### RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RELOAD DICTIONARIES` privilege when the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARIES`, `RELOAD DICTIONARIES`, or `RELOAD DICTIONARY`. -##### RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries +#### RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RELOAD EMBEDDED DICTIONARIES` privilege when the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARY ON *.*`, or `SYSTEM RELOAD EMBEDDED DICTIONARIES`. -##### RQ.SRS-006.RBAC.Privileges.System.Merges +#### RQ.SRS-006.RBAC.Privileges.System.Merges version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM MERGES` privilege when the user is granted `SYSTEM`, `SYSTEM MERGES`, `SYSTEM STOP MERGES`, `SYSTEM START MERGES`, `STOP MERGES`, or `START MERGES`. -##### RQ.SRS-006.RBAC.Privileges.System.TTLMerges +#### RQ.SRS-006.RBAC.Privileges.System.TTLMerges version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM TTL MERGES` privilege when the user is granted `SYSTEM`, `SYSTEM TTL MERGES`, `SYSTEM STOP TTL MERGES`, `SYSTEM START TTL MERGES`, `STOP TTL MERGES`, or `START TTL MERGES`. -##### RQ.SRS-006.RBAC.Privileges.System.Fetches +#### RQ.SRS-006.RBAC.Privileges.System.Fetches version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM FETCHES` privilege when the user is granted `SYSTEM`, `SYSTEM FETCHES`, `SYSTEM STOP FETCHES`, `SYSTEM START FETCHES`, `STOP FETCHES`, or `START FETCHES`. -##### RQ.SRS-006.RBAC.Privileges.System.Moves +#### RQ.SRS-006.RBAC.Privileges.System.Moves version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM MOVES` privilege when the user is granted `SYSTEM`, `SYSTEM MOVES`, `SYSTEM STOP MOVES`, `SYSTEM START MOVES`, `STOP MOVES`, or `START MOVES`. -##### RQ.SRS-006.RBAC.Privileges.System.Sends +#### RQ.SRS-006.RBAC.Privileges.System.Sends version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM SENDS` privilege when the user is granted `SYSTEM`, `SYSTEM SENDS`, `SYSTEM STOP SENDS`, `SYSTEM START SENDS`, `STOP SENDS`, or `START SENDS`. -##### RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed +#### RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM DISTRIBUTED SENDS` privilege when the user is granted `SYSTEM`, `SYSTEM DISTRIBUTED SENDS`, `SYSTEM STOP DISTRIBUTED SENDS`, `SYSTEM START DISTRIBUTED SENDS`, `STOP DISTRIBUTED SENDS`, or `START DISTRIBUTED SENDS`. -##### RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated +#### RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM REPLICATED SENDS` privilege when the user is granted `SYSTEM`, `SYSTEM REPLICATED SENDS`, `SYSTEM STOP REPLICATED SENDS`, `SYSTEM START REPLICATED SENDS`, `STOP REPLICATED SENDS`, or `START REPLICATED SENDS`. -##### RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues +#### RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM REPLICATION QUEUES` privilege when the user is granted `SYSTEM`, `SYSTEM REPLICATION QUEUES`, `SYSTEM STOP REPLICATION QUEUES`, `SYSTEM START REPLICATION QUEUES`, `STOP REPLICATION QUEUES`, or `START REPLICATION QUEUES`. -##### RQ.SRS-006.RBAC.Privileges.System.SyncReplica +#### RQ.SRS-006.RBAC.Privileges.System.SyncReplica version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM SYNC REPLICA` privilege when the user is granted `SYSTEM`, `SYSTEM SYNC REPLICA`, or `SYNC REPLICA`. -##### RQ.SRS-006.RBAC.Privileges.System.RestartReplica +#### RQ.SRS-006.RBAC.Privileges.System.RestartReplica version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RESTART REPLICA` privilege when the user is granted `SYSTEM`, `SYSTEM RESTART REPLICA`, or `RESTART REPLICA`. -##### RQ.SRS-006.RBAC.Privileges.System.Flush +#### RQ.SRS-006.RBAC.Privileges.System.Flush version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM FLUSH` privilege when the user is granted `SYSTEM` or `SYSTEM FLUSH`. -##### RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed +#### RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM FLUSH DISTRIBUTED` privilege when the user is granted `SYSTEM`, `SYSTEM FLUSH DISTRIBUTED`, or `FLUSH DISTRIBUTED`. -##### RQ.SRS-006.RBAC.Privileges.System.Flush.Logs +#### RQ.SRS-006.RBAC.Privileges.System.Flush.Logs version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM FLUSH LOGS` privilege when the user is granted `SYSTEM`, `SYSTEM FLUSH LOGS`, or `FLUSH LOGS`. -#### Sources +### Sources -##### RQ.SRS-006.RBAC.Privileges.Sources +#### RQ.SRS-006.RBAC.Privileges.Sources version: 1.0 [ClickHouse] SHALL support granting or revoking `SOURCES` privilege from the user, either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.File +#### RQ.SRS-006.RBAC.Privileges.Sources.File version: 1.0 [ClickHouse] SHALL support the use of `FILE` source by a user if and only if the user has `FILE` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.URL +#### RQ.SRS-006.RBAC.Privileges.Sources.URL version: 1.0 [ClickHouse] SHALL support the use of `URL` source by a user if and only if the user has `URL` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.Remote +#### RQ.SRS-006.RBAC.Privileges.Sources.Remote version: 1.0 [ClickHouse] SHALL support the use of `REMOTE` source by a user if and only if the user has `REMOTE` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.MySQL +#### RQ.SRS-006.RBAC.Privileges.Sources.MySQL version: 1.0 [ClickHouse] SHALL support the use of `MySQL` source by a user if and only if the user has `MySQL` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.ODBC +#### RQ.SRS-006.RBAC.Privileges.Sources.ODBC version: 1.0 [ClickHouse] SHALL support the use of `ODBC` source by a user if and only if the user has `ODBC` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.JDBC +#### RQ.SRS-006.RBAC.Privileges.Sources.JDBC version: 1.0 [ClickHouse] SHALL support the use of `JDBC` source by a user if and only if the user has `JDBC` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.HDFS +#### RQ.SRS-006.RBAC.Privileges.Sources.HDFS version: 1.0 [ClickHouse] SHALL support the use of `HDFS` source by a user if and only if the user has `HDFS` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.S3 +#### RQ.SRS-006.RBAC.Privileges.Sources.S3 version: 1.0 [ClickHouse] SHALL support the use of `S3` source by a user if and only if the user has `S3` or `SOURCES` privileges granted to them directly or through a role. -#### RQ.SRS-006.RBAC.Privileges.GrantOption +### RQ.SRS-006.RBAC.Privileges.GrantOption version: 1.0 [ClickHouse] SHALL successfully execute `GRANT` or `REVOKE` privilege statements by a user if and only if the user has that privilege with `GRANT OPTION`, either directly or through a role. -#### RQ.SRS-006.RBAC.Privileges.All +### RQ.SRS-006.RBAC.Privileges.All version: 1.0 -[ClickHouse] SHALL support granting or revoking `ALL` privilege. +[ClickHouse] SHALL support granting or revoking `ALL` privilege +using `GRANT ALL ON *.* TO user`. -#### RQ.SRS-006.RBAC.Privileges.AdminOption +### RQ.SRS-006.RBAC.Privileges.RoleAll +version: 1.0 + +[ClickHouse] SHALL support granting a role named `ALL` using `GRANT ALL TO user`. +This shall only grant the user the privileges that have been granted to the role. + +### RQ.SRS-006.RBAC.Privileges.None +version: 1.0 + +[ClickHouse] SHALL support granting or revoking `NONE` privilege +using `GRANT NONE TO user` or `GRANT USAGE ON *.* TO user`. + +### RQ.SRS-006.RBAC.Privileges.AdminOption version: 1.0 [ClickHouse] SHALL support a user granting or revoking a role if and only if diff --git a/tests/testflows/rbac/requirements/requirements.py b/tests/testflows/rbac/requirements/requirements.py index f276d811f19..27f455d3fe6 100755 --- a/tests/testflows/rbac/requirements/requirements.py +++ b/tests/testflows/rbac/requirements/requirements.py @@ -1,28 +1,9983 @@ # These requirements were auto generated # from software requirements specification (SRS) -# document by TestFlows v1.6.201124.1002350. +# document by TestFlows v1.6.201216.1172002. # Do not edit by hand but re-generate instead # using 'tfs requirements generate' command. from testflows.core import Specification from testflows.core import Requirement +Heading = Specification.Heading + +RQ_SRS_006_RBAC = Requirement( + name='RQ.SRS-006.RBAC', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support role based access control.\n' + '\n' + ), + link=None, + level=3, + num='5.1.1') + +RQ_SRS_006_RBAC_Login = Requirement( + name='RQ.SRS-006.RBAC.Login', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only allow access to the server for a given\n' + 'user only when correct username and password are used during\n' + 'the connection to the server.\n' + '\n' + ), + link=None, + level=3, + num='5.2.1') + +RQ_SRS_006_RBAC_Login_DefaultUser = Requirement( + name='RQ.SRS-006.RBAC.Login.DefaultUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL use the **default user** when no username and password\n' + 'are specified during the connection to the server.\n' + '\n' + ), + link=None, + level=3, + num='5.2.2') + +RQ_SRS_006_RBAC_User = Requirement( + name='RQ.SRS-006.RBAC.User', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creation and manipulation of\n' + 'one or more **user** accounts to which roles, privileges,\n' + 'settings profile, quotas and row policies can be assigned.\n' + '\n' + ), + link=None, + level=3, + num='5.3.1') + +RQ_SRS_006_RBAC_User_Roles = Requirement( + name='RQ.SRS-006.RBAC.User.Roles', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more **roles**\n' + 'to a **user**.\n' + '\n' + ), + link=None, + level=3, + num='5.3.2') + +RQ_SRS_006_RBAC_User_Privileges = Requirement( + name='RQ.SRS-006.RBAC.User.Privileges', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more privileges to a **user**.\n' + '\n' + ), + link=None, + level=3, + num='5.3.3') + +RQ_SRS_006_RBAC_User_Variables = Requirement( + name='RQ.SRS-006.RBAC.User.Variables', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more variables to a **user**.\n' + '\n' + ), + link=None, + level=3, + num='5.3.4') + +RQ_SRS_006_RBAC_User_Variables_Constraints = Requirement( + name='RQ.SRS-006.RBAC.User.Variables.Constraints', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning min, max and read-only constraints\n' + 'for the variables that can be set and read by the **user**.\n' + '\n' + ), + link=None, + level=3, + num='5.3.5') + +RQ_SRS_006_RBAC_User_SettingsProfile = Requirement( + name='RQ.SRS-006.RBAC.User.SettingsProfile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more **settings profiles**\n' + 'to a **user**.\n' + '\n' + ), + link=None, + level=3, + num='5.3.6') + +RQ_SRS_006_RBAC_User_Quotas = Requirement( + name='RQ.SRS-006.RBAC.User.Quotas', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more **quotas** to a **user**.\n' + '\n' + ), + link=None, + level=3, + num='5.3.7') + +RQ_SRS_006_RBAC_User_RowPolicies = Requirement( + name='RQ.SRS-006.RBAC.User.RowPolicies', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more **row policies** to a **user**.\n' + '\n' + ), + link=None, + level=3, + num='5.3.8') + +RQ_SRS_006_RBAC_User_DefaultRole = Requirement( + name='RQ.SRS-006.RBAC.User.DefaultRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning a default role to a **user**.\n' + '\n' + ), + link=None, + level=3, + num='5.3.9') + +RQ_SRS_006_RBAC_User_RoleSelection = Requirement( + name='RQ.SRS-006.RBAC.User.RoleSelection', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support selection of one or more **roles** from the available roles\n' + 'that are assigned to a **user** using `SET ROLE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.3.10') + +RQ_SRS_006_RBAC_User_ShowCreate = Requirement( + name='RQ.SRS-006.RBAC.User.ShowCreate', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing the command of how **user** account was created.\n' + '\n' + ), + link=None, + level=3, + num='5.3.11') + +RQ_SRS_006_RBAC_User_ShowPrivileges = Requirement( + name='RQ.SRS-006.RBAC.User.ShowPrivileges', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support listing the privileges of the **user**.\n' + '\n' + ), + link=None, + level=3, + num='5.3.12') + +RQ_SRS_006_RBAC_User_Use_DefaultRole = Requirement( + name='RQ.SRS-006.RBAC.User.Use.DefaultRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL by default use default role or roles assigned\n' + 'to the user if specified.\n' + '\n' + ), + link=None, + level=3, + num='5.3.13') + +RQ_SRS_006_RBAC_User_Use_AllRolesWhenNoDefaultRole = Requirement( + name='RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL by default use all the roles assigned to the user\n' + 'if no default role or roles are specified for the user.\n' + '\n' + ), + link=None, + level=3, + num='5.3.14') + +RQ_SRS_006_RBAC_User_Create = Requirement( + name='RQ.SRS-006.RBAC.User.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creating **user** accounts using `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.1') + +RQ_SRS_006_RBAC_User_Create_IfNotExists = Requirement( + name='RQ.SRS-006.RBAC.User.Create.IfNotExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `IF NOT EXISTS` clause in the `CREATE USER` statement\n' + 'to skip raising an exception if a user with the same **name** already exists.\n' + 'If the `IF NOT EXISTS` clause is not specified then an exception SHALL be\n' + 'raised if a user with the same **name** already exists.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.2') + +RQ_SRS_006_RBAC_User_Create_Replace = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Replace', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `OR REPLACE` clause in the `CREATE USER` statement\n' + 'to replace existing user account if already exists.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.3') + +RQ_SRS_006_RBAC_User_Create_Password_NoPassword = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.NoPassword', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying no password when creating\n' + 'user account using `IDENTIFIED WITH NO_PASSWORD` clause .\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.4') + +RQ_SRS_006_RBAC_User_Create_Password_NoPassword_Login = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.NoPassword.Login', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL use no password for the user when connecting to the server\n' + 'when an account was created with `IDENTIFIED WITH NO_PASSWORD` clause.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.5') + +RQ_SRS_006_RBAC_User_Create_Password_PlainText = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.PlainText', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying plaintext password when creating\n' + 'user account using `IDENTIFIED WITH PLAINTEXT_PASSWORD BY` clause.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.6') + +RQ_SRS_006_RBAC_User_Create_Password_PlainText_Login = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.PlainText.Login', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL use the plaintext password passed by the user when connecting to the server\n' + 'when an account was created with `IDENTIFIED WITH PLAINTEXT_PASSWORD` clause\n' + 'and compare the password with the one used in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.7') + +RQ_SRS_006_RBAC_User_Create_Password_Sha256Password = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Password', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying the result of applying SHA256\n' + 'to some password when creating user account using `IDENTIFIED WITH SHA256_PASSWORD BY` or `IDENTIFIED BY`\n' + 'clause.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.8') + +RQ_SRS_006_RBAC_User_Create_Password_Sha256Password_Login = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Password.Login', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL calculate `SHA256` of the password passed by the user when connecting to the server\n' + "when an account was created with `IDENTIFIED WITH SHA256_PASSWORD` or with 'IDENTIFIED BY' clause\n" + 'and compare the calculated hash to the one used in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.9') + +RQ_SRS_006_RBAC_User_Create_Password_Sha256Hash = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying the result of applying SHA256\n' + 'to some already calculated hash when creating user account using `IDENTIFIED WITH SHA256_HASH`\n' + 'clause.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.10') + +RQ_SRS_006_RBAC_User_Create_Password_Sha256Hash_Login = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash.Login', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL calculate `SHA256` of the already calculated hash passed by\n' + 'the user when connecting to the server\n' + 'when an account was created with `IDENTIFIED WITH SHA256_HASH` clause\n' + 'and compare the calculated hash to the one used in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.11') + +RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Password = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying the result of applying SHA1 two times\n' + 'to a password when creating user account using `IDENTIFIED WITH DOUBLE_SHA1_PASSWORD`\n' + 'clause.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.12') + +RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Password_Login = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password.Login', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL calculate `SHA1` two times over the password passed by\n' + 'the user when connecting to the server\n' + 'when an account was created with `IDENTIFIED WITH DOUBLE_SHA1_PASSWORD` clause\n' + 'and compare the calculated value to the one used in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.13') + +RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Hash = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying the result of applying SHA1 two times\n' + 'to a hash when creating user account using `IDENTIFIED WITH DOUBLE_SHA1_HASH`\n' + 'clause.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.14') + +RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Hash_Login = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash.Login', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL calculate `SHA1` two times over the hash passed by\n' + 'the user when connecting to the server\n' + 'when an account was created with `IDENTIFIED WITH DOUBLE_SHA1_HASH` clause\n' + 'and compare the calculated value to the one used in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.15') + +RQ_SRS_006_RBAC_User_Create_Host_Name = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Host.Name', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more hostnames from\n' + 'which user can access the server using the `HOST NAME` clause\n' + 'in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.16') + +RQ_SRS_006_RBAC_User_Create_Host_Regexp = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Host.Regexp', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more regular expressions\n' + 'to match hostnames from which user can access the server\n' + 'using the `HOST REGEXP` clause in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.17') + +RQ_SRS_006_RBAC_User_Create_Host_IP = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Host.IP', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more IP address or subnet from\n' + 'which user can access the server using the `HOST IP` clause in the\n' + '`CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.18') + +RQ_SRS_006_RBAC_User_Create_Host_Any = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Host.Any', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying `HOST ANY` clause in the `CREATE USER` statement\n' + 'to indicate that user can access the server from any host.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.19') + +RQ_SRS_006_RBAC_User_Create_Host_None = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Host.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support fobidding access from any host using `HOST NONE` clause in the\n' + '`CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.20') + +RQ_SRS_006_RBAC_User_Create_Host_Local = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Host.Local', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting user access to local only using `HOST LOCAL` clause in the\n' + '`CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.21') + +RQ_SRS_006_RBAC_User_Create_Host_Like = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Host.Like', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying host using `LIKE` command syntax using the\n' + '`HOST LIKE` clause in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.22') + +RQ_SRS_006_RBAC_User_Create_Host_Default = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Host.Default', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support user access to server from any host\n' + 'if no `HOST` clause is specified in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.23') + +RQ_SRS_006_RBAC_User_Create_DefaultRole = Requirement( + name='RQ.SRS-006.RBAC.User.Create.DefaultRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more default roles\n' + 'using `DEFAULT ROLE` clause in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.24') + +RQ_SRS_006_RBAC_User_Create_DefaultRole_None = Requirement( + name='RQ.SRS-006.RBAC.User.Create.DefaultRole.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying no default roles\n' + 'using `DEFAULT ROLE NONE` clause in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.25') + +RQ_SRS_006_RBAC_User_Create_DefaultRole_All = Requirement( + name='RQ.SRS-006.RBAC.User.Create.DefaultRole.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying all roles to be used as default\n' + 'using `DEFAULT ROLE ALL` clause in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.26') + +RQ_SRS_006_RBAC_User_Create_Settings = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Settings', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying settings and profile\n' + 'using `SETTINGS` clause in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.27') + +RQ_SRS_006_RBAC_User_Create_OnCluster = Requirement( + name='RQ.SRS-006.RBAC.User.Create.OnCluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying cluster on which the user\n' + 'will be created using `ON CLUSTER` clause in the `CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.28') + +RQ_SRS_006_RBAC_User_Create_Syntax = Requirement( + name='RQ.SRS-006.RBAC.User.Create.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for `CREATE USER` statement.\n' + '\n' + '```sql\n' + 'CREATE USER [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name]\n' + " [IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH}] BY {'password'|'hash'}]\n" + " [HOST {LOCAL | NAME 'name' | NAME REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]\n" + ' [DEFAULT ROLE role [,...]]\n' + " [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]\n" + '```\n' + '\n' + ), + link=None, + level=4, + num='5.3.15.29') + +RQ_SRS_006_RBAC_User_Alter = Requirement( + name='RQ.SRS-006.RBAC.User.Alter', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering **user** accounts using `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.1') + +RQ_SRS_006_RBAC_User_Alter_OrderOfEvaluation = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.OrderOfEvaluation', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support evaluating `ALTER USER` statement from left to right\n' + 'where things defined on the right override anything that was previously defined on\n' + 'the left.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.2') + +RQ_SRS_006_RBAC_User_Alter_IfExists = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.IfExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `IF EXISTS` clause in the `ALTER USER` statement\n' + 'to skip raising an exception (producing a warning instead) if a user with the specified **name** does not exist.\n' + 'If the `IF EXISTS` clause is not specified then an exception SHALL be raised if a user with the **name** does not exist.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.3') + +RQ_SRS_006_RBAC_User_Alter_Cluster = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying the cluster the user is on\n' + 'when altering user account using `ON CLUSTER` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.4') + +RQ_SRS_006_RBAC_User_Alter_Rename = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Rename', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying a new name for the user when\n' + 'altering user account using `RENAME` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.5') + +RQ_SRS_006_RBAC_User_Alter_Password_PlainText = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Password.PlainText', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying plaintext password when altering\n' + 'user account using `IDENTIFIED WITH PLAINTEXT_PASSWORD BY` or\n' + 'using shorthand `IDENTIFIED BY` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.6') + +RQ_SRS_006_RBAC_User_Alter_Password_Sha256Password = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Password.Sha256Password', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying the result of applying SHA256\n' + 'to some password as identification when altering user account using\n' + '`IDENTIFIED WITH SHA256_PASSWORD` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.7') + +RQ_SRS_006_RBAC_User_Alter_Password_DoubleSha1Password = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Password.DoubleSha1Password', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying the result of applying Double SHA1\n' + 'to some password as identification when altering user account using\n' + '`IDENTIFIED WITH DOUBLE_SHA1_PASSWORD` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.8') + +RQ_SRS_006_RBAC_User_Alter_Host_AddDrop = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Host.AddDrop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering user by adding and dropping access to hosts\n' + 'with the `ADD HOST` or the `DROP HOST` in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.9') + +RQ_SRS_006_RBAC_User_Alter_Host_Local = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Host.Local', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting user access to local only using `HOST LOCAL` clause in the\n' + '`ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.10') + +RQ_SRS_006_RBAC_User_Alter_Host_Name = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Host.Name', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more hostnames from\n' + 'which user can access the server using the `HOST NAME` clause\n' + 'in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.11') + +RQ_SRS_006_RBAC_User_Alter_Host_Regexp = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Host.Regexp', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more regular expressions\n' + 'to match hostnames from which user can access the server\n' + 'using the `HOST REGEXP` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.12') + +RQ_SRS_006_RBAC_User_Alter_Host_IP = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Host.IP', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more IP address or subnet from\n' + 'which user can access the server using the `HOST IP` clause in the\n' + '`ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.13') + +RQ_SRS_006_RBAC_User_Alter_Host_Like = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Host.Like', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more similar hosts using `LIKE` command syntax\n' + 'using the `HOST LIKE` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.14') + +RQ_SRS_006_RBAC_User_Alter_Host_Any = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Host.Any', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying `HOST ANY` clause in the `ALTER USER` statement\n' + 'to indicate that user can access the server from any host.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.15') + +RQ_SRS_006_RBAC_User_Alter_Host_None = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Host.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support fobidding access from any host using `HOST NONE` clause in the\n' + '`ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.16') + +RQ_SRS_006_RBAC_User_Alter_DefaultRole = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.DefaultRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more default roles\n' + 'using `DEFAULT ROLE` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.17') + +RQ_SRS_006_RBAC_User_Alter_DefaultRole_All = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.DefaultRole.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying all roles to be used as default\n' + 'using `DEFAULT ROLE ALL` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.18') + +RQ_SRS_006_RBAC_User_Alter_DefaultRole_AllExcept = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.DefaultRole.AllExcept', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more roles which will not be used as default\n' + 'using `DEFAULT ROLE ALL EXCEPT` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.19') + +RQ_SRS_006_RBAC_User_Alter_Settings = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Settings', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying one or more variables\n' + 'using `SETTINGS` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.20') + +RQ_SRS_006_RBAC_User_Alter_Settings_Min = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Settings.Min', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying a minimum value for the variable specifed using `SETTINGS` with `MIN` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.21') + +RQ_SRS_006_RBAC_User_Alter_Settings_Max = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Settings.Max', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying a maximum value for the variable specifed using `SETTINGS` with `MAX` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.22') + +RQ_SRS_006_RBAC_User_Alter_Settings_Profile = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Settings.Profile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying the name of a profile for the variable specifed using `SETTINGS` with `PROFILE` clause in the `ALTER USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.23') + +RQ_SRS_006_RBAC_User_Alter_Syntax = Requirement( + name='RQ.SRS-006.RBAC.User.Alter.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `ALTER USER` statement.\n' + '\n' + '```sql\n' + 'ALTER USER [IF EXISTS] name [ON CLUSTER cluster_name]\n' + ' [RENAME TO new_name]\n' + " [IDENTIFIED [WITH {PLAINTEXT_PASSWORD|SHA256_PASSWORD|DOUBLE_SHA1_PASSWORD}] BY {'password'|'hash'}]\n" + " [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]\n" + ' [DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]\n' + " [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]\n" + '```\n' + '\n' + ), + link=None, + level=4, + num='5.3.16.24') + +RQ_SRS_006_RBAC_User_ShowCreateUser = Requirement( + name='RQ.SRS-006.RBAC.User.ShowCreateUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing the `CREATE USER` statement used to create the current user object\n' + 'using the `SHOW CREATE USER` statement with `CURRENT_USER` or no argument.\n' + '\n' + ), + link=None, + level=4, + num='5.3.17.1') + +RQ_SRS_006_RBAC_User_ShowCreateUser_For = Requirement( + name='RQ.SRS-006.RBAC.User.ShowCreateUser.For', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing the `CREATE USER` statement used to create the specified user object\n' + 'using the `FOR` clause in the `SHOW CREATE USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.17.2') + +RQ_SRS_006_RBAC_User_ShowCreateUser_Syntax = Requirement( + name='RQ.SRS-006.RBAC.User.ShowCreateUser.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing the following syntax for `SHOW CREATE USER` statement.\n' + '\n' + '```sql\n' + 'SHOW CREATE USER [name | CURRENT_USER]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.3.17.3') + +RQ_SRS_006_RBAC_User_Drop = Requirement( + name='RQ.SRS-006.RBAC.User.Drop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support removing a user account using `DROP USER` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.3.18.1') + +RQ_SRS_006_RBAC_User_Drop_IfExists = Requirement( + name='RQ.SRS-006.RBAC.User.Drop.IfExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using `IF EXISTS` clause in the `DROP USER` statement\n' + 'to skip raising an exception if the user account does not exist.\n' + 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' + 'raised if a user does not exist.\n' + '\n' + ), + link=None, + level=4, + num='5.3.18.2') + +RQ_SRS_006_RBAC_User_Drop_OnCluster = Requirement( + name='RQ.SRS-006.RBAC.User.Drop.OnCluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using `ON CLUSTER` clause in the `DROP USER` statement\n' + 'to specify the name of the cluster the user should be dropped from.\n' + '\n' + ), + link=None, + level=4, + num='5.3.18.3') + +RQ_SRS_006_RBAC_User_Drop_Syntax = Requirement( + name='RQ.SRS-006.RBAC.User.Drop.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for `DROP USER` statement\n' + '\n' + '```sql\n' + 'DROP USER [IF EXISTS] name [,...] [ON CLUSTER cluster_name]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.3.18.4') + +RQ_SRS_006_RBAC_Role = Requirement( + name='RQ.SRS-006.RBAC.Role', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClikHouse] SHALL support creation and manipulation of **roles**\n' + 'to which privileges, settings profile, quotas and row policies can be\n' + 'assigned.\n' + '\n' + ), + link=None, + level=3, + num='5.4.1') + +RQ_SRS_006_RBAC_Role_Privileges = Requirement( + name='RQ.SRS-006.RBAC.Role.Privileges', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more privileges to a **role**.\n' + '\n' + ), + link=None, + level=3, + num='5.4.2') + +RQ_SRS_006_RBAC_Role_Variables = Requirement( + name='RQ.SRS-006.RBAC.Role.Variables', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more variables to a **role**.\n' + '\n' + ), + link=None, + level=3, + num='5.4.3') + +RQ_SRS_006_RBAC_Role_SettingsProfile = Requirement( + name='RQ.SRS-006.RBAC.Role.SettingsProfile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more **settings profiles**\n' + 'to a **role**.\n' + '\n' + ), + link=None, + level=3, + num='5.4.4') + +RQ_SRS_006_RBAC_Role_Quotas = Requirement( + name='RQ.SRS-006.RBAC.Role.Quotas', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more **quotas** to a **role**.\n' + '\n' + ), + link=None, + level=3, + num='5.4.5') + +RQ_SRS_006_RBAC_Role_RowPolicies = Requirement( + name='RQ.SRS-006.RBAC.Role.RowPolicies', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning one or more **row policies** to a **role**.\n' + '\n' + ), + link=None, + level=3, + num='5.4.6') + +RQ_SRS_006_RBAC_Role_Create = Requirement( + name='RQ.SRS-006.RBAC.Role.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creating a **role** using `CREATE ROLE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.4.7.1') + +RQ_SRS_006_RBAC_Role_Create_IfNotExists = Requirement( + name='RQ.SRS-006.RBAC.Role.Create.IfNotExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `IF NOT EXISTS` clause in the `CREATE ROLE` statement\n' + 'to raising an exception if a role with the same **name** already exists.\n' + 'If the `IF NOT EXISTS` clause is not specified then an exception SHALL be\n' + 'raised if a role with the same **name** already exists.\n' + '\n' + ), + link=None, + level=4, + num='5.4.7.2') + +RQ_SRS_006_RBAC_Role_Create_Replace = Requirement( + name='RQ.SRS-006.RBAC.Role.Create.Replace', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `OR REPLACE` clause in the `CREATE ROLE` statement\n' + 'to replace existing role if it already exists.\n' + '\n' + ), + link=None, + level=4, + num='5.4.7.3') + +RQ_SRS_006_RBAC_Role_Create_Settings = Requirement( + name='RQ.SRS-006.RBAC.Role.Create.Settings', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying settings and profile using `SETTINGS`\n' + 'clause in the `CREATE ROLE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.4.7.4') + +RQ_SRS_006_RBAC_Role_Create_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Role.Create.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `CREATE ROLE` statement\n' + '\n' + '``` sql\n' + 'CREATE ROLE [IF NOT EXISTS | OR REPLACE] name\n' + " [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]\n" + '```\n' + '\n' + ), + link=None, + level=4, + num='5.4.7.5') + +RQ_SRS_006_RBAC_Role_Alter = Requirement( + name='RQ.SRS-006.RBAC.Role.Alter', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering one **role** using `ALTER ROLE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.4.8.1') + +RQ_SRS_006_RBAC_Role_Alter_IfExists = Requirement( + name='RQ.SRS-006.RBAC.Role.Alter.IfExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering one **role** using `ALTER ROLE IF EXISTS` statement, where no exception\n' + 'will be thrown if the role does not exist.\n' + '\n' + ), + link=None, + level=4, + num='5.4.8.2') + +RQ_SRS_006_RBAC_Role_Alter_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Role.Alter.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering one **role** using `ALTER ROLE role ON CLUSTER` statement to specify the\n' + 'cluster location of the specified role.\n' + '\n' + ), + link=None, + level=4, + num='5.4.8.3') + +RQ_SRS_006_RBAC_Role_Alter_Rename = Requirement( + name='RQ.SRS-006.RBAC.Role.Alter.Rename', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering one **role** using `ALTER ROLE role RENAME TO` statement which renames the\n' + 'role to a specified new name. If the new name already exists, that an exception SHALL be raised unless the\n' + '`IF EXISTS` clause is specified, by which no exception will be raised and nothing will change.\n' + '\n' + ), + link=None, + level=4, + num='5.4.8.4') + +RQ_SRS_006_RBAC_Role_Alter_Settings = Requirement( + name='RQ.SRS-006.RBAC.Role.Alter.Settings', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering the settings of one **role** using `ALTER ROLE role SETTINGS ...` statement.\n' + 'Altering variable values, creating max and min values, specifying readonly or writable, and specifying the\n' + 'profiles for which this alter change shall be applied to, are all supported, using the following syntax.\n' + '\n' + '```sql\n' + "[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]\n" + '```\n' + '\n' + 'One or more variables and profiles may be specified as shown above.\n' + '\n' + ), + link=None, + level=4, + num='5.4.8.5') + +RQ_SRS_006_RBAC_Role_Alter_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Role.Alter.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '```sql\n' + 'ALTER ROLE [IF EXISTS] name [ON CLUSTER cluster_name]\n' + ' [RENAME TO new_name]\n' + " [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]\n" + '```\n' + '\n' + ), + link=None, + level=4, + num='5.4.8.6') + +RQ_SRS_006_RBAC_Role_Drop = Requirement( + name='RQ.SRS-006.RBAC.Role.Drop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support removing one or more roles using `DROP ROLE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.4.9.1') + +RQ_SRS_006_RBAC_Role_Drop_IfExists = Requirement( + name='RQ.SRS-006.RBAC.Role.Drop.IfExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using `IF EXISTS` clause in the `DROP ROLE` statement\n' + 'to skip raising an exception if the role does not exist.\n' + 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' + 'raised if a role does not exist.\n' + '\n' + ), + link=None, + level=4, + num='5.4.9.2') + +RQ_SRS_006_RBAC_Role_Drop_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Role.Drop.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using `ON CLUSTER` clause in the `DROP ROLE` statement to specify the cluster from which to drop the specified role.\n' + '\n' + ), + link=None, + level=4, + num='5.4.9.3') + +RQ_SRS_006_RBAC_Role_Drop_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Role.Drop.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `DROP ROLE` statement\n' + '\n' + '``` sql\n' + 'DROP ROLE [IF EXISTS] name [,...] [ON CLUSTER cluster_name]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.4.9.4') + +RQ_SRS_006_RBAC_Role_ShowCreate = Requirement( + name='RQ.SRS-006.RBAC.Role.ShowCreate', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support viewing the settings for a role upon creation with the `SHOW CREATE ROLE`\n' + 'statement.\n' + '\n' + ), + link=None, + level=4, + num='5.4.10.1') + +RQ_SRS_006_RBAC_Role_ShowCreate_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Role.ShowCreate.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `SHOW CREATE ROLE` command.\n' + '\n' + '```sql\n' + 'SHOW CREATE ROLE name\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.4.10.2') + +RQ_SRS_006_RBAC_PartialRevokes = Requirement( + name='RQ.SRS-006.RBAC.PartialRevokes', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support partial revoking of privileges granted\n' + 'to a **user** or a **role**.\n' + '\n' + ), + link=None, + level=3, + num='5.5.1') + +RQ_SRS_006_RBAC_PartialRevoke_Syntax = Requirement( + name='RQ.SRS-006.RBAC.PartialRevoke.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support partial revokes by using `partial_revokes` variable\n' + 'that can be set or unset using the following syntax.\n' + '\n' + 'To disable partial revokes the `partial_revokes` variable SHALL be set to `0`\n' + '\n' + '```sql\n' + 'SET partial_revokes = 0\n' + '```\n' + '\n' + 'To enable partial revokes the `partial revokes` variable SHALL be set to `1`\n' + '\n' + '```sql\n' + 'SET partial_revokes = 1\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='5.5.2') + +RQ_SRS_006_RBAC_SettingsProfile = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creation and manipulation of **settings profiles**\n' + 'that can include value definition for one or more variables and can\n' + 'can be assigned to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=3, + num='5.6.1') + +RQ_SRS_006_RBAC_SettingsProfile_Constraints = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Constraints', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning min, max and read-only constraints\n' + 'for the variables specified in the **settings profile**.\n' + '\n' + ), + link=None, + level=3, + num='5.6.2') + +RQ_SRS_006_RBAC_SettingsProfile_Create = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creating settings profile using the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.1') + +RQ_SRS_006_RBAC_SettingsProfile_Create_IfNotExists = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.IfNotExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `IF NOT EXISTS` clause in the `CREATE SETTINGS PROFILE` statement\n' + 'to skip raising an exception if a settings profile with the same **name** already exists.\n' + 'If `IF NOT EXISTS` clause is not specified then an exception SHALL be raised if\n' + 'a settings profile with the same **name** already exists.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.2') + +RQ_SRS_006_RBAC_SettingsProfile_Create_Replace = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.Replace', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `OR REPLACE` clause in the `CREATE SETTINGS PROFILE` statement\n' + 'to replace existing settings profile if it already exists.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.3') + +RQ_SRS_006_RBAC_SettingsProfile_Create_Variables = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.Variables', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning values and constraints to one or more\n' + 'variables in the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.4') + +RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Value = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Value', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning variable value in the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.5') + +RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Constraints', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting `MIN`, `MAX`, `READONLY`, and `WRITABLE`\n' + 'constraints for the variables in the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.6') + +RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning settings profile to one or more users\n' + 'or roles in the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.7') + +RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_None = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning settings profile to no users or roles using\n' + '`TO NONE` clause in the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.8') + +RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_All = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning settings profile to all current users and roles\n' + 'using `TO ALL` clause in the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.9') + +RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_AllExcept = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.AllExcept', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support excluding assignment to one or more users or roles using\n' + 'the `ALL EXCEPT` clause in the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.10') + +RQ_SRS_006_RBAC_SettingsProfile_Create_Inherit = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.Inherit', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support inheriting profile settings from indicated profile using\n' + 'the `INHERIT` clause in the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.11') + +RQ_SRS_006_RBAC_SettingsProfile_Create_OnCluster = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.OnCluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying what cluster to create settings profile on\n' + 'using `ON CLUSTER` clause in the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.12') + +RQ_SRS_006_RBAC_SettingsProfile_Create_Syntax = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Create.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `CREATE SETTINGS PROFILE` statement.\n' + '\n' + '``` sql\n' + 'CREATE SETTINGS PROFILE [IF NOT EXISTS | OR REPLACE] name\n' + ' [ON CLUSTER cluster_name]\n' + " [SET varname [= value] [MIN min] [MAX max] [READONLY|WRITABLE] | [INHERIT 'profile_name'] [,...]]\n" + ' [TO {user_or_role [,...] | NONE | ALL | ALL EXCEPT user_or_role [,...]}]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.6.3.13') + +RQ_SRS_006_RBAC_SettingsProfile_Alter = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering settings profile using the `ALTER STETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.1') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_IfExists = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.IfExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `IF EXISTS` clause in the `ALTER SETTINGS PROFILE` statement\n' + 'to not raise exception if a settings profile does not exist.\n' + 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' + 'raised if a settings profile does not exist.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.2') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Rename = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Rename', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support renaming settings profile using the `RANAME TO` clause\n' + 'in the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.3') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering values and constraints of one or more\n' + 'variables in the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.4') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Value', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering value of the variable in the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.5') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Constraints', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering `MIN`, `MAX`, `READONLY`, and `WRITABLE`\n' + 'constraints for the variables in the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.6') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support reassigning settings profile to one or more users\n' + 'or roles using the `TO` clause in the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.7') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_None = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support reassigning settings profile to no users or roles using the\n' + '`TO NONE` clause in the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.8') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_All = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support reassigning settings profile to all current users and roles\n' + 'using the `TO ALL` clause in the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.9') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_AllExcept = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.AllExcept', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support excluding assignment to one or more users or roles using\n' + 'the `TO ALL EXCEPT` clause in the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.10') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_Inherit = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.Inherit', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering the settings profile by inheriting settings from\n' + 'specified profile using `INHERIT` clause in the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.11') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_OnCluster = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.OnCluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering the settings profile on a specified cluster using\n' + '`ON CLUSTER` clause in the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.12') + +RQ_SRS_006_RBAC_SettingsProfile_Alter_Syntax = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `ALTER SETTINGS PROFILE` statement.\n' + '\n' + '``` sql\n' + 'ALTER SETTINGS PROFILE [IF EXISTS] name\n' + ' [ON CLUSTER cluster_name]\n' + ' [RENAME TO new_name]\n' + " [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | INHERIT 'profile_name'] [,...]\n" + ' [TO {user_or_role [,...] | NONE | ALL | ALL EXCEPT user_or_role [,...]]}\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.6.4.13') + +RQ_SRS_006_RBAC_SettingsProfile_Drop = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Drop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support removing one or more settings profiles using the `DROP SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.5.1') + +RQ_SRS_006_RBAC_SettingsProfile_Drop_IfExists = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Drop.IfExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using `IF EXISTS` clause in the `DROP SETTINGS PROFILE` statement\n' + 'to skip raising an exception if the settings profile does not exist.\n' + 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' + 'raised if a settings profile does not exist.\n' + '\n' + ), + link=None, + level=4, + num='5.6.5.2') + +RQ_SRS_006_RBAC_SettingsProfile_Drop_OnCluster = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Drop.OnCluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support dropping one or more settings profiles on specified cluster using\n' + '`ON CLUSTER` clause in the `DROP SETTINGS PROFILE` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.6.5.3') + +RQ_SRS_006_RBAC_SettingsProfile_Drop_Syntax = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.Drop.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `DROP SETTINGS PROFILE` statement\n' + '\n' + '``` sql\n' + 'DROP SETTINGS PROFILE [IF EXISTS] name [,name,...]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.6.5.4') + +RQ_SRS_006_RBAC_SettingsProfile_ShowCreateSettingsProfile = Requirement( + name='RQ.SRS-006.RBAC.SettingsProfile.ShowCreateSettingsProfile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing the `CREATE SETTINGS PROFILE` statement used to create the settings profile\n' + 'using the `SHOW CREATE SETTINGS PROFILE` statement with the following syntax\n' + '\n' + '``` sql\n' + 'SHOW CREATE SETTINGS PROFILE name\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.6.6.1') + +RQ_SRS_006_RBAC_Quotas = Requirement( + name='RQ.SRS-006.RBAC.Quotas', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creation and manipulation of **quotas**\n' + 'that can be used to limit resource usage by a **user** or a **role**\n' + 'over a period of time.\n' + '\n' + ), + link=None, + level=3, + num='5.7.1') + +RQ_SRS_006_RBAC_Quotas_Keyed = Requirement( + name='RQ.SRS-006.RBAC.Quotas.Keyed', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creating **quotas** that are keyed\n' + 'so that a quota is tracked separately for each key value.\n' + '\n' + ), + link=None, + level=3, + num='5.7.2') + +RQ_SRS_006_RBAC_Quotas_Queries = Requirement( + name='RQ.SRS-006.RBAC.Quotas.Queries', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting **queries** quota to limit the total number of requests.\n' + '\n' + ), + link=None, + level=3, + num='5.7.3') + +RQ_SRS_006_RBAC_Quotas_Errors = Requirement( + name='RQ.SRS-006.RBAC.Quotas.Errors', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting **errors** quota to limit the number of queries that threw an exception.\n' + '\n' + ), + link=None, + level=3, + num='5.7.4') + +RQ_SRS_006_RBAC_Quotas_ResultRows = Requirement( + name='RQ.SRS-006.RBAC.Quotas.ResultRows', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting **result rows** quota to limit the\n' + 'the total number of rows given as the result.\n' + '\n' + ), + link=None, + level=3, + num='5.7.5') + +RQ_SRS_006_RBAC_Quotas_ReadRows = Requirement( + name='RQ.SRS-006.RBAC.Quotas.ReadRows', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting **read rows** quota to limit the total\n' + 'number of source rows read from tables for running the query on all remote servers.\n' + '\n' + ), + link=None, + level=3, + num='5.7.6') + +RQ_SRS_006_RBAC_Quotas_ResultBytes = Requirement( + name='RQ.SRS-006.RBAC.Quotas.ResultBytes', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting **result bytes** quota to limit the total number\n' + 'of bytes that can be returned as the result.\n' + '\n' + ), + link=None, + level=3, + num='5.7.7') + +RQ_SRS_006_RBAC_Quotas_ReadBytes = Requirement( + name='RQ.SRS-006.RBAC.Quotas.ReadBytes', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting **read bytes** quota to limit the total number\n' + 'of source bytes read from tables for running the query on all remote servers.\n' + '\n' + ), + link=None, + level=3, + num='5.7.8') + +RQ_SRS_006_RBAC_Quotas_ExecutionTime = Requirement( + name='RQ.SRS-006.RBAC.Quotas.ExecutionTime', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting **execution time** quota to limit the maximum\n' + 'query execution time.\n' + '\n' + ), + link=None, + level=3, + num='5.7.9') + +RQ_SRS_006_RBAC_Quota_Create = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creating quotas using the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.1') + +RQ_SRS_006_RBAC_Quota_Create_IfNotExists = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.IfNotExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `IF NOT EXISTS` clause in the `CREATE QUOTA` statement\n' + 'to skip raising an exception if a quota with the same **name** already exists.\n' + 'If `IF NOT EXISTS` clause is not specified then an exception SHALL be raised if\n' + 'a quota with the same **name** already exists.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.2') + +RQ_SRS_006_RBAC_Quota_Create_Replace = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Replace', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `OR REPLACE` clause in the `CREATE QUOTA` statement\n' + 'to replace existing quota if it already exists.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.3') + +RQ_SRS_006_RBAC_Quota_Create_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creating quotas on a specific cluster with the\n' + '`ON CLUSTER` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.4') + +RQ_SRS_006_RBAC_Quota_Create_Interval = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Interval', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support defining the quota interval that specifies\n' + 'a period of time over for which the quota SHALL apply using the\n' + '`FOR INTERVAL` clause in the `CREATE QUOTA` statement.\n' + '\n' + 'This statement SHALL also support a number and a time period which will be one\n' + 'of `{SECOND | MINUTE | HOUR | DAY | MONTH}`. Thus, the complete syntax SHALL be:\n' + '\n' + '`FOR INTERVAL number {SECOND | MINUTE | HOUR | DAY}` where number is some real number\n' + 'to define the interval.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.5') + +RQ_SRS_006_RBAC_Quota_Create_Interval_Randomized = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Interval.Randomized', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support defining the quota randomized interval that specifies\n' + 'a period of time over for which the quota SHALL apply using the\n' + '`FOR RANDOMIZED INTERVAL` clause in the `CREATE QUOTA` statement.\n' + '\n' + 'This statement SHALL also support a number and a time period which will be one\n' + 'of `{SECOND | MINUTE | HOUR | DAY | MONTH}`. Thus, the complete syntax SHALL be:\n' + '\n' + '`FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}` where number is some\n' + 'real number to define the interval.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.6') + +RQ_SRS_006_RBAC_Quota_Create_Queries = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Queries', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting number of requests over a period of time\n' + 'using the `QUERIES` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.7') + +RQ_SRS_006_RBAC_Quota_Create_Errors = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Errors', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting number of queries that threw an exception\n' + 'using the `ERRORS` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.8') + +RQ_SRS_006_RBAC_Quota_Create_ResultRows = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.ResultRows', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting the total number of rows given as the result\n' + 'using the `RESULT ROWS` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.9') + +RQ_SRS_006_RBAC_Quota_Create_ReadRows = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.ReadRows', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting the total number of source rows read from tables\n' + 'for running the query on all remote servers\n' + 'using the `READ ROWS` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.10') + +RQ_SRS_006_RBAC_Quota_Create_ResultBytes = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.ResultBytes', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting the total number of bytes that can be returned as the result\n' + 'using the `RESULT BYTES` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.11') + +RQ_SRS_006_RBAC_Quota_Create_ReadBytes = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.ReadBytes', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting the total number of source bytes read from tables\n' + 'for running the query on all remote servers\n' + 'using the `READ BYTES` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.12') + +RQ_SRS_006_RBAC_Quota_Create_ExecutionTime = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.ExecutionTime', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting the maximum query execution time\n' + 'using the `EXECUTION TIME` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.13') + +RQ_SRS_006_RBAC_Quota_Create_NoLimits = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.NoLimits', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting the maximum query execution time\n' + 'using the `NO LIMITS` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.14') + +RQ_SRS_006_RBAC_Quota_Create_TrackingOnly = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.TrackingOnly', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting the maximum query execution time\n' + 'using the `TRACKING ONLY` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.15') + +RQ_SRS_006_RBAC_Quota_Create_KeyedBy = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.KeyedBy', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support to track quota for some key\n' + 'following the `KEYED BY` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.16') + +RQ_SRS_006_RBAC_Quota_Create_KeyedByOptions = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.KeyedByOptions', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support to track quota separately for some parameter\n' + "using the `KEYED BY 'parameter'` clause in the `CREATE QUOTA` statement.\n" + '\n' + "'parameter' can be one of:\n" + "`{'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}`\n" + '\n' + ), + link=None, + level=4, + num='5.7.10.17') + +RQ_SRS_006_RBAC_Quota_Create_Assignment = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Assignment', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning quota to one or more users\n' + 'or roles using the `TO` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.18') + +RQ_SRS_006_RBAC_Quota_Create_Assignment_None = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Assignment.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning quota to no users or roles using\n' + '`TO NONE` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.19') + +RQ_SRS_006_RBAC_Quota_Create_Assignment_All = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Assignment.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning quota to all current users and roles\n' + 'using `TO ALL` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.20') + +RQ_SRS_006_RBAC_Quota_Create_Assignment_Except = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Assignment.Except', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support excluding assignment of quota to one or more users or roles using\n' + 'the `EXCEPT` clause in the `CREATE QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.21') + +RQ_SRS_006_RBAC_Quota_Create_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Quota.Create.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `CREATE QUOTA` statement\n' + '\n' + '```sql\n' + 'CREATE QUOTA [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name]\n' + " [KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]\n" + ' [FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}\n' + ' {MAX { {QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = number } [,...] |\n' + ' NO LIMITS | TRACKING ONLY} [,...]]\n' + ' [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.7.10.22') + +RQ_SRS_006_RBAC_Quota_Alter = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering quotas using the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.1') + +RQ_SRS_006_RBAC_Quota_Alter_IfExists = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.IfExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `IF EXISTS` clause in the `ALTER QUOTA` statement\n' + 'to skip raising an exception if a quota does not exist.\n' + 'If the `IF EXISTS` clause is not specified then an exception SHALL be raised if\n' + 'a quota does not exist.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.2') + +RQ_SRS_006_RBAC_Quota_Alter_Rename = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Rename', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `RENAME TO` clause in the `ALTER QUOTA` statement\n' + 'to rename the quota to the specified name.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.3') + +RQ_SRS_006_RBAC_Quota_Alter_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering quotas on a specific cluster with the\n' + '`ON CLUSTER` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.4') + +RQ_SRS_006_RBAC_Quota_Alter_Interval = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Interval', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support redefining the quota interval that specifies\n' + 'a period of time over for which the quota SHALL apply using the\n' + '`FOR INTERVAL` clause in the `ALTER QUOTA` statement.\n' + '\n' + 'This statement SHALL also support a number and a time period which will be one\n' + 'of `{SECOND | MINUTE | HOUR | DAY | MONTH}`. Thus, the complete syntax SHALL be:\n' + '\n' + '`FOR INTERVAL number {SECOND | MINUTE | HOUR | DAY}` where number is some real number\n' + 'to define the interval.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.5') + +RQ_SRS_006_RBAC_Quota_Alter_Interval_Randomized = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Interval.Randomized', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support redefining the quota randomized interval that specifies\n' + 'a period of time over for which the quota SHALL apply using the\n' + '`FOR RANDOMIZED INTERVAL` clause in the `ALTER QUOTA` statement.\n' + '\n' + 'This statement SHALL also support a number and a time period which will be one\n' + 'of `{SECOND | MINUTE | HOUR | DAY | MONTH}`. Thus, the complete syntax SHALL be:\n' + '\n' + '`FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}` where number is some\n' + 'real number to define the interval.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.6') + +RQ_SRS_006_RBAC_Quota_Alter_Queries = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Queries', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering the limit of number of requests over a period of time\n' + 'using the `QUERIES` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.7') + +RQ_SRS_006_RBAC_Quota_Alter_Errors = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Errors', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering the limit of number of queries that threw an exception\n' + 'using the `ERRORS` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.8') + +RQ_SRS_006_RBAC_Quota_Alter_ResultRows = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.ResultRows', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering the limit of the total number of rows given as the result\n' + 'using the `RESULT ROWS` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.9') + +RQ_SRS_006_RBAC_Quota_Alter_ReadRows = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.ReadRows', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering the limit of the total number of source rows read from tables\n' + 'for running the query on all remote servers\n' + 'using the `READ ROWS` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.10') + +RQ_SRS_006_RBAC_Quota_ALter_ResultBytes = Requirement( + name='RQ.SRS-006.RBAC.Quota.ALter.ResultBytes', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering the limit of the total number of bytes that can be returned as the result\n' + 'using the `RESULT BYTES` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.11') + +RQ_SRS_006_RBAC_Quota_Alter_ReadBytes = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.ReadBytes', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering the limit of the total number of source bytes read from tables\n' + 'for running the query on all remote servers\n' + 'using the `READ BYTES` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.12') + +RQ_SRS_006_RBAC_Quota_Alter_ExecutionTime = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.ExecutionTime', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering the limit of the maximum query execution time\n' + 'using the `EXECUTION TIME` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.13') + +RQ_SRS_006_RBAC_Quota_Alter_NoLimits = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.NoLimits', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting the maximum query execution time\n' + 'using the `NO LIMITS` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.14') + +RQ_SRS_006_RBAC_Quota_Alter_TrackingOnly = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.TrackingOnly', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support limiting the maximum query execution time\n' + 'using the `TRACKING ONLY` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.15') + +RQ_SRS_006_RBAC_Quota_Alter_KeyedBy = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.KeyedBy', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering quota to track quota separately for some key\n' + 'following the `KEYED BY` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.16') + +RQ_SRS_006_RBAC_Quota_Alter_KeyedByOptions = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.KeyedByOptions', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering quota to track quota separately for some parameter\n' + "using the `KEYED BY 'parameter'` clause in the `ALTER QUOTA` statement.\n" + '\n' + "'parameter' can be one of:\n" + "`{'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}`\n" + '\n' + ), + link=None, + level=4, + num='5.7.11.17') + +RQ_SRS_006_RBAC_Quota_Alter_Assignment = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Assignment', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support reassigning quota to one or more users\n' + 'or roles using the `TO` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.18') + +RQ_SRS_006_RBAC_Quota_Alter_Assignment_None = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Assignment.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support reassigning quota to no users or roles using\n' + '`TO NONE` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.19') + +RQ_SRS_006_RBAC_Quota_Alter_Assignment_All = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Assignment.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support reassigning quota to all current users and roles\n' + 'using `TO ALL` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.20') + +RQ_SRS_006_RBAC_Quota_Alter_Assignment_Except = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Assignment.Except', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support excluding assignment of quota to one or more users or roles using\n' + 'the `EXCEPT` clause in the `ALTER QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.21') + +RQ_SRS_006_RBAC_Quota_Alter_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Quota.Alter.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `ALTER QUOTA` statement\n' + '\n' + '``` sql\n' + 'ALTER QUOTA [IF EXIST] name\n' + ' {{{QUERIES | ERRORS | RESULT ROWS | READ ROWS | RESULT BYTES | READ BYTES | EXECUTION TIME} number} [, ...] FOR INTERVAL number time_unit} [, ...]\n' + ' [KEYED BY USERNAME | KEYED BY IP | NOT KEYED] [ALLOW CUSTOM KEY | DISALLOW CUSTOM KEY]\n' + ' [TO {user_or_role [,...] | NONE | ALL} [EXCEPT user_or_role [,...]]]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.7.11.22') + +RQ_SRS_006_RBAC_Quota_Drop = Requirement( + name='RQ.SRS-006.RBAC.Quota.Drop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support removing one or more quotas using the `DROP QUOTA` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.7.12.1') + +RQ_SRS_006_RBAC_Quota_Drop_IfExists = Requirement( + name='RQ.SRS-006.RBAC.Quota.Drop.IfExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using `IF EXISTS` clause in the `DROP QUOTA` statement\n' + 'to skip raising an exception when the quota does not exist.\n' + 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' + 'raised if the quota does not exist.\n' + '\n' + ), + link=None, + level=4, + num='5.7.12.2') + +RQ_SRS_006_RBAC_Quota_Drop_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Quota.Drop.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using `ON CLUSTER` clause in the `DROP QUOTA` statement\n' + 'to indicate the cluster the quota to be dropped is located on.\n' + '\n' + ), + link=None, + level=4, + num='5.7.12.3') + +RQ_SRS_006_RBAC_Quota_Drop_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Quota.Drop.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `DROP QUOTA` statement\n' + '\n' + '``` sql\n' + 'DROP QUOTA [IF EXISTS] name [,name...]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.7.12.4') + +RQ_SRS_006_RBAC_Quota_ShowQuotas = Requirement( + name='RQ.SRS-006.RBAC.Quota.ShowQuotas', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing all of the current quotas\n' + 'using the `SHOW QUOTAS` statement with the following syntax\n' + '\n' + ), + link=None, + level=4, + num='5.7.13.1') + +RQ_SRS_006_RBAC_Quota_ShowQuotas_IntoOutfile = Requirement( + name='RQ.SRS-006.RBAC.Quota.ShowQuotas.IntoOutfile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the `INTO OUTFILE` clause in the `SHOW QUOTAS` statement to define an outfile by some given string literal.\n' + '\n' + ), + link=None, + level=4, + num='5.7.13.2') + +RQ_SRS_006_RBAC_Quota_ShowQuotas_Format = Requirement( + name='RQ.SRS-006.RBAC.Quota.ShowQuotas.Format', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the `FORMAT` clause in the `SHOW QUOTAS` statement to define a format for the output quota list.\n' + '\n' + 'The types of valid formats are many, listed in output column:\n' + 'https://clickhouse.tech/docs/en/interfaces/formats/\n' + '\n' + ), + link=None, + level=4, + num='5.7.13.3') + +RQ_SRS_006_RBAC_Quota_ShowQuotas_Settings = Requirement( + name='RQ.SRS-006.RBAC.Quota.ShowQuotas.Settings', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the `SETTINGS` clause in the `SHOW QUOTAS` statement to define settings in the showing of all quotas.\n' + '\n' + ), + link=None, + level=4, + num='5.7.13.4') + +RQ_SRS_006_RBAC_Quota_ShowQuotas_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Quota.ShowQuotas.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using the `SHOW QUOTAS` statement\n' + 'with the following syntax\n' + '``` sql\n' + 'SHOW QUOTAS\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.7.13.5') + +RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Name = Requirement( + name='RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Name', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing the `CREATE QUOTA` statement used to create the quota with some given name\n' + 'using the `SHOW CREATE QUOTA` statement with the following syntax\n' + '\n' + '``` sql\n' + 'SHOW CREATE QUOTA name\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.7.14.1') + +RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Current = Requirement( + name='RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Current', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing the `CREATE QUOTA` statement used to create the CURRENT quota\n' + 'using the `SHOW CREATE QUOTA CURRENT` statement or the shorthand form\n' + '`SHOW CREATE QUOTA`\n' + '\n' + ), + link=None, + level=4, + num='5.7.14.2') + +RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax when\n' + 'using the `SHOW CREATE QUOTA` statement.\n' + '\n' + '```sql\n' + 'SHOW CREATE QUOTA [name | CURRENT]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.7.14.3') + +RQ_SRS_006_RBAC_RowPolicy = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creation and manipulation of table **row policies**\n' + 'that can be used to limit access to the table contents for a **user** or a **role**\n' + 'using a specified **condition**.\n' + '\n' + ), + link=None, + level=3, + num='5.8.1') + +RQ_SRS_006_RBAC_RowPolicy_Condition = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Condition', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support row policy **conditions** that can be any SQL\n' + 'expression that returns a boolean.\n' + '\n' + ), + link=None, + level=3, + num='5.8.2') + +RQ_SRS_006_RBAC_RowPolicy_Restriction = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Restriction', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL restrict all access to a table when a row policy with a condition is created on that table.\n' + 'All users require a permissive row policy in order to view the table.\n' + '\n' + ), + link=None, + level=3, + num='5.8.3') + +RQ_SRS_006_RBAC_RowPolicy_Nesting = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Nesting', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL restrict rows of tables or views created on top of a table with row policies according to those policies.\n' + '\n' + ), + link=None, + level=3, + num='5.8.4') + +RQ_SRS_006_RBAC_RowPolicy_Create = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creating row policy using the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.1') + +RQ_SRS_006_RBAC_RowPolicy_Create_IfNotExists = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.IfNotExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `IF NOT EXISTS` clause in the `CREATE ROW POLICY` statement\n' + 'to skip raising an exception if a row policy with the same **name** already exists.\n' + 'If the `IF NOT EXISTS` clause is not specified then an exception SHALL be raised if\n' + 'a row policy with the same **name** already exists.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.2') + +RQ_SRS_006_RBAC_RowPolicy_Create_Replace = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.Replace', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `OR REPLACE` clause in the `CREATE ROW POLICY` statement\n' + 'to replace existing row policy if it already exists.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.3') + +RQ_SRS_006_RBAC_RowPolicy_Create_OnCluster = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.OnCluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying cluster on which to create the role policy\n' + 'using the `ON CLUSTER` clause in the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.4') + +RQ_SRS_006_RBAC_RowPolicy_Create_On = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.On', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying table on which to create the role policy\n' + 'using the `ON` clause in the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.5') + +RQ_SRS_006_RBAC_RowPolicy_Create_Access = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.Access', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support allowing or restricting access to rows using the\n' + '`AS` clause in the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.6') + +RQ_SRS_006_RBAC_RowPolicy_Create_Access_Permissive = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.Access.Permissive', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support allowing access to rows using the\n' + '`AS PERMISSIVE` clause in the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.7') + +RQ_SRS_006_RBAC_RowPolicy_Create_Access_Restrictive = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.Access.Restrictive', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support restricting access to rows using the\n' + '`AS RESTRICTIVE` clause in the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.8') + +RQ_SRS_006_RBAC_RowPolicy_Create_ForSelect = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.ForSelect', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying which rows are affected\n' + 'using the `FOR SELECT` clause in the `CREATE ROW POLICY` statement.\n' + 'REQUIRES CONDITION.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.9') + +RQ_SRS_006_RBAC_RowPolicy_Create_Condition = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.Condition', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying a condition that\n' + 'that can be any SQL expression which returns a boolean using the `USING`\n' + 'clause in the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.10') + +RQ_SRS_006_RBAC_RowPolicy_Create_Assignment = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning row policy to one or more users\n' + 'or roles using the `TO` clause in the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.11') + +RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_None = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning row policy to no users or roles using\n' + 'the `TO NONE` clause in the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.12') + +RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_All = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support assigning row policy to all current users and roles\n' + 'using `TO ALL` clause in the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.13') + +RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_AllExcept = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.AllExcept', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support excluding assignment of row policy to one or more users or roles using\n' + 'the `ALL EXCEPT` clause in the `CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.14') + +RQ_SRS_006_RBAC_RowPolicy_Create_Syntax = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Create.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `CRETE ROW POLICY` statement\n' + '\n' + '``` sql\n' + 'CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name [ON CLUSTER cluster_name] ON [db.]table\n' + ' [AS {PERMISSIVE | RESTRICTIVE}]\n' + ' [FOR SELECT]\n' + ' [USING condition]\n' + ' [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.8.5.15') + +RQ_SRS_006_RBAC_RowPolicy_Alter = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering row policy using the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.1') + +RQ_SRS_006_RBAC_RowPolicy_Alter_IfExists = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.IfExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the `IF EXISTS` clause in the `ALTER ROW POLICY` statement\n' + 'to skip raising an exception if a row policy does not exist.\n' + 'If the `IF EXISTS` clause is not specified then an exception SHALL be raised if\n' + 'a row policy does not exist.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.2') + +RQ_SRS_006_RBAC_RowPolicy_Alter_ForSelect = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.ForSelect', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support modifying rows on which to apply the row policy\n' + 'using the `FOR SELECT` clause in the `ALTER ROW POLICY` statement.\n' + 'REQUIRES FUNCTION CONFIRMATION.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.3') + +RQ_SRS_006_RBAC_RowPolicy_Alter_OnCluster = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.OnCluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying cluster on which to alter the row policy\n' + 'using the `ON CLUSTER` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.4') + +RQ_SRS_006_RBAC_RowPolicy_Alter_On = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.On', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying table on which to alter the row policy\n' + 'using the `ON` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.5') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Rename = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Rename', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support renaming the row policy using the `RENAME` clause\n' + 'in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.6') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Access = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Access', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support altering access to rows using the\n' + '`AS` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.7') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Permissive = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Permissive', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support permitting access to rows using the\n' + '`AS PERMISSIVE` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.8') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Restrictive = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Restrictive', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support restricting access to rows using the\n' + '`AS RESTRICTIVE` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.9') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Condition = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Condition', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support re-specifying the row policy condition\n' + 'using the `USING` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.10') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Condition_None = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Condition.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support removing the row policy condition\n' + 'using the `USING NONE` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.11') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support reassigning row policy to one or more users\n' + 'or roles using the `TO` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.12') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_None = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support reassigning row policy to no users or roles using\n' + 'the `TO NONE` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.13') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_All = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support reassigning row policy to all current users and roles\n' + 'using the `TO ALL` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.14') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_AllExcept = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.AllExcept', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support excluding assignment of row policy to one or more users or roles using\n' + 'the `ALL EXCEPT` clause in the `ALTER ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.15') + +RQ_SRS_006_RBAC_RowPolicy_Alter_Syntax = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Alter.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `ALTER ROW POLICY` statement\n' + '\n' + '``` sql\n' + 'ALTER [ROW] POLICY [IF EXISTS] name [ON CLUSTER cluster_name] ON [database.]table\n' + ' [RENAME TO new_name]\n' + ' [AS {PERMISSIVE | RESTRICTIVE}]\n' + ' [FOR SELECT]\n' + ' [USING {condition | NONE}][,...]\n' + ' [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.8.6.16') + +RQ_SRS_006_RBAC_RowPolicy_Drop = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Drop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support removing one or more row policies using the `DROP ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.7.1') + +RQ_SRS_006_RBAC_RowPolicy_Drop_IfExists = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Drop.IfExists', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using the `IF EXISTS` clause in the `DROP ROW POLICY` statement\n' + 'to skip raising an exception when the row policy does not exist.\n' + 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' + 'raised if the row policy does not exist.\n' + '\n' + ), + link=None, + level=4, + num='5.8.7.2') + +RQ_SRS_006_RBAC_RowPolicy_Drop_On = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Drop.On', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support removing row policy from one or more specified tables\n' + 'using the `ON` clause in the `DROP ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.7.3') + +RQ_SRS_006_RBAC_RowPolicy_Drop_OnCluster = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Drop.OnCluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support removing row policy from specified cluster\n' + 'using the `ON CLUSTER` clause in the `DROP ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.7.4') + +RQ_SRS_006_RBAC_RowPolicy_Drop_Syntax = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.Drop.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `DROP ROW POLICY` statement.\n' + '\n' + '``` sql\n' + 'DROP [ROW] POLICY [IF EXISTS] name [,...] ON [database.]table [,...] [ON CLUSTER cluster_name]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.8.7.5') + +RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing the `CREATE ROW POLICY` statement used to create the row policy\n' + 'using the `SHOW CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.8.1') + +RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy_On = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.On', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing statement used to create row policy on specific table\n' + 'using the `ON` in the `SHOW CREATE ROW POLICY` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.8.2') + +RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy_Syntax = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for `SHOW CREATE ROW POLICY`.\n' + '\n' + '``` sql\n' + 'SHOW CREATE [ROW] POLICY name ON [database.]table\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.8.8.3') + +RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing row policies using the `SHOW ROW POLICIES` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.8.4') + +RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_On = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.On', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support showing row policies on a specific table\n' + 'using the `ON` clause in the `SHOW ROW POLICIES` statement.\n' + '\n' + ), + link=None, + level=4, + num='5.8.8.5') + +RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_Syntax = Requirement( + name='RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for `SHOW ROW POLICIES`.\n' + '\n' + '```sql\n' + 'SHOW [ROW] POLICIES [ON [database.]table]\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.8.8.6') + +RQ_SRS_006_RBAC_SetDefaultRole = Requirement( + name='RQ.SRS-006.RBAC.SetDefaultRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting or changing granted roles to default for one or more\n' + 'users using `SET DEFAULT ROLE` statement which\n' + 'SHALL permanently change the default roles for the user or users if successful.\n' + '\n' + ), + link=None, + level=3, + num='5.9.1') + +RQ_SRS_006_RBAC_SetDefaultRole_CurrentUser = Requirement( + name='RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting or changing granted roles to default for\n' + 'the current user using `CURRENT_USER` clause in the `SET DEFAULT ROLE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.9.2') + +RQ_SRS_006_RBAC_SetDefaultRole_All = Requirement( + name='RQ.SRS-006.RBAC.SetDefaultRole.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting or changing all granted roles to default\n' + 'for one or more users using `ALL` clause in the `SET DEFAULT ROLE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.9.3') + +RQ_SRS_006_RBAC_SetDefaultRole_AllExcept = Requirement( + name='RQ.SRS-006.RBAC.SetDefaultRole.AllExcept', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support setting or changing all granted roles except those specified\n' + 'to default for one or more users using `ALL EXCEPT` clause in the `SET DEFAULT ROLE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.9.4') + +RQ_SRS_006_RBAC_SetDefaultRole_None = Requirement( + name='RQ.SRS-006.RBAC.SetDefaultRole.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support removing all granted roles from default\n' + 'for one or more users using `NONE` clause in the `SET DEFAULT ROLE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.9.5') + +RQ_SRS_006_RBAC_SetDefaultRole_Syntax = Requirement( + name='RQ.SRS-006.RBAC.SetDefaultRole.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `SET DEFAULT ROLE` statement.\n' + '\n' + '```sql\n' + 'SET DEFAULT ROLE\n' + ' {NONE | role [,...] | ALL | ALL EXCEPT role [,...]}\n' + ' TO {user|CURRENT_USER} [,...]\n' + '\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='5.9.6') + +RQ_SRS_006_RBAC_SetRole = Requirement( + name='RQ.SRS-006.RBAC.SetRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support activating role or roles for the current user\n' + 'using `SET ROLE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.10.1') + +RQ_SRS_006_RBAC_SetRole_Default = Requirement( + name='RQ.SRS-006.RBAC.SetRole.Default', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support activating default roles for the current user\n' + 'using `DEFAULT` clause in the `SET ROLE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.10.2') + +RQ_SRS_006_RBAC_SetRole_None = Requirement( + name='RQ.SRS-006.RBAC.SetRole.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support activating no roles for the current user\n' + 'using `NONE` clause in the `SET ROLE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.10.3') + +RQ_SRS_006_RBAC_SetRole_All = Requirement( + name='RQ.SRS-006.RBAC.SetRole.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support activating all roles for the current user\n' + 'using `ALL` clause in the `SET ROLE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.10.4') + +RQ_SRS_006_RBAC_SetRole_AllExcept = Requirement( + name='RQ.SRS-006.RBAC.SetRole.AllExcept', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support activating all roles except those specified\n' + 'for the current user using `ALL EXCEPT` clause in the `SET ROLE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.10.5') + +RQ_SRS_006_RBAC_SetRole_Syntax = Requirement( + name='RQ.SRS-006.RBAC.SetRole.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '```sql\n' + 'SET ROLE {DEFAULT | NONE | role [,...] | ALL | ALL EXCEPT role [,...]}\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='5.10.6') + +RQ_SRS_006_RBAC_Grant_Privilege_To = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.To', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting privileges to one or more users or roles using `TO` clause\n' + 'in the `GRANT PRIVILEGE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.1') + +RQ_SRS_006_RBAC_Grant_Privilege_ToCurrentUser = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting privileges to current user using `TO CURRENT_USER` clause\n' + 'in the `GRANT PRIVILEGE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.2') + +RQ_SRS_006_RBAC_Grant_Privilege_Select = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Select', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **select** privilege to one or more users or roles\n' + 'for a database or a table using the `GRANT SELECT` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.3') + +RQ_SRS_006_RBAC_Grant_Privilege_Insert = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Insert', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **insert** privilege to one or more users or roles\n' + 'for a database or a table using the `GRANT INSERT` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.4') + +RQ_SRS_006_RBAC_Grant_Privilege_Alter = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Alter', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **alter** privilege to one or more users or roles\n' + 'for a database or a table using the `GRANT ALTER` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.5') + +RQ_SRS_006_RBAC_Grant_Privilege_Create = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **create** privilege to one or more users or roles\n' + 'using the `GRANT CREATE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.6') + +RQ_SRS_006_RBAC_Grant_Privilege_Drop = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Drop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **drop** privilege to one or more users or roles\n' + 'using the `GRANT DROP` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.7') + +RQ_SRS_006_RBAC_Grant_Privilege_Truncate = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Truncate', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **truncate** privilege to one or more users or roles\n' + 'for a database or a table using `GRANT TRUNCATE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.8') + +RQ_SRS_006_RBAC_Grant_Privilege_Optimize = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Optimize', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **optimize** privilege to one or more users or roles\n' + 'for a database or a table using `GRANT OPTIMIZE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.9') + +RQ_SRS_006_RBAC_Grant_Privilege_Show = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Show', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **show** privilege to one or more users or roles\n' + 'for a database or a table using `GRANT SHOW` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.10') + +RQ_SRS_006_RBAC_Grant_Privilege_KillQuery = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.KillQuery', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **kill query** privilege to one or more users or roles\n' + 'for a database or a table using `GRANT KILL QUERY` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.11') + +RQ_SRS_006_RBAC_Grant_Privilege_AccessManagement = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **access management** privileges to one or more users or roles\n' + 'for a database or a table using `GRANT ACCESS MANAGEMENT` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.12') + +RQ_SRS_006_RBAC_Grant_Privilege_System = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.System', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **system** privileges to one or more users or roles\n' + 'for a database or a table using `GRANT SYSTEM` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.13') + +RQ_SRS_006_RBAC_Grant_Privilege_Introspection = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Introspection', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **introspection** privileges to one or more users or roles\n' + 'for a database or a table using `GRANT INTROSPECTION` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.14') + +RQ_SRS_006_RBAC_Grant_Privilege_Sources = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Sources', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **sources** privileges to one or more users or roles\n' + 'for a database or a table using `GRANT SOURCES` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.15') + +RQ_SRS_006_RBAC_Grant_Privilege_DictGet = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.DictGet', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **dictGet** privilege to one or more users or roles\n' + 'for a database or a table using `GRANT dictGet` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.16') + +RQ_SRS_006_RBAC_Grant_Privilege_None = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting no privileges to one or more users or roles\n' + 'for a database or a table using `GRANT NONE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.17') + +RQ_SRS_006_RBAC_Grant_Privilege_All = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **all** privileges to one or more users or roles\n' + 'using the `GRANT ALL` or `GRANT ALL PRIVILEGES` statements.\n' + '\n' + ), + link=None, + level=3, + num='5.11.18') + +RQ_SRS_006_RBAC_Grant_Privilege_GrantOption = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.GrantOption', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the **grant option** privilege to one or more users or roles\n' + 'for a database or a table using the `WITH GRANT OPTION` clause in the `GRANT` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.19') + +RQ_SRS_006_RBAC_Grant_Privilege_On = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.On', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the `ON` clause in the `GRANT` privilege statement\n' + 'which SHALL allow to specify one or more tables to which the privilege SHALL\n' + 'be granted using the following patterns\n' + '\n' + '* `*.*` any table in any database\n' + '* `database.*` any table in the specified database\n' + '* `database.table` specific table in the specified database\n' + '* `*` any table in the current database\n' + '* `table` specific table in the current database\n' + '\n' + ), + link=None, + level=3, + num='5.11.20') + +RQ_SRS_006_RBAC_Grant_Privilege_PrivilegeColumns = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting the privilege **some_privilege** to one or more users or roles\n' + 'for a database or a table using the `GRANT some_privilege(column)` statement for one column.\n' + 'Multiple columns will be supported with `GRANT some_privilege(column1, column2...)` statement.\n' + 'The privileges will be granted for only the specified columns.\n' + '\n' + ), + link=None, + level=3, + num='5.11.21') + +RQ_SRS_006_RBAC_Grant_Privilege_OnCluster = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.OnCluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying cluster on which to grant privileges using the `ON CLUSTER`\n' + 'clause in the `GRANT PRIVILEGE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.11.22') + +RQ_SRS_006_RBAC_Grant_Privilege_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Grant.Privilege.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `GRANT` statement that\n' + 'grants explicit privileges to a user or a role.\n' + '\n' + '```sql\n' + 'GRANT [ON CLUSTER cluster_name] privilege[(column_name [,...])] [,...]\n' + ' ON {db.table|db.*|*.*|table|*}\n' + ' TO {user | role | CURRENT_USER} [,...]\n' + ' [WITH GRANT OPTION]\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='5.11.23') + +RQ_SRS_006_RBAC_Revoke_Privilege_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking privileges to one or more users or roles\n' + 'for a database or a table on some specific cluster using the `REVOKE ON CLUSTER cluster_name` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.1') + +RQ_SRS_006_RBAC_Revoke_Privilege_Select = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Select', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **select** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE SELECT` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.2') + +RQ_SRS_006_RBAC_Revoke_Privilege_Insert = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Insert', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **insert** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE INSERT` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.3') + +RQ_SRS_006_RBAC_Revoke_Privilege_Alter = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Alter', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **alter** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE ALTER` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.4') + +RQ_SRS_006_RBAC_Revoke_Privilege_Create = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **create** privilege to one or more users or roles\n' + 'using the `REVOKE CREATE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.5') + +RQ_SRS_006_RBAC_Revoke_Privilege_Drop = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Drop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **drop** privilege to one or more users or roles\n' + 'using the `REVOKE DROP` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.6') + +RQ_SRS_006_RBAC_Revoke_Privilege_Truncate = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Truncate', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **truncate** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE TRUNCATE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.7') + +RQ_SRS_006_RBAC_Revoke_Privilege_Optimize = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Optimize', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **optimize** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE OPTIMIZE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.8') + +RQ_SRS_006_RBAC_Revoke_Privilege_Show = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Show', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **show** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE SHOW` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.9') + +RQ_SRS_006_RBAC_Revoke_Privilege_KillQuery = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **kill query** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE KILL QUERY` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.10') + +RQ_SRS_006_RBAC_Revoke_Privilege_AccessManagement = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **access management** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE ACCESS MANAGEMENT` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.11') + +RQ_SRS_006_RBAC_Revoke_Privilege_System = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.System', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **system** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE SYSTEM` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.12') + +RQ_SRS_006_RBAC_Revoke_Privilege_Introspection = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Introspection', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **introspection** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE INTROSPECTION` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.13') + +RQ_SRS_006_RBAC_Revoke_Privilege_Sources = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Sources', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **sources** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE SOURCES` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.14') + +RQ_SRS_006_RBAC_Revoke_Privilege_DictGet = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.DictGet', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the **dictGet** privilege to one or more users or roles\n' + 'for a database or a table using the `REVOKE dictGet` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.15') + +RQ_SRS_006_RBAC_Revoke_Privilege_PrivilegeColumns = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.PrivilegeColumns', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking the privilege **some_privilege** to one or more users or roles\n' + 'for a database or a table using the `REVOKE some_privilege(column)` statement for one column.\n' + 'Multiple columns will be supported with `REVOKE some_privilege(column1, column2...)` statement.\n' + 'The privileges will be revoked for only the specified columns.\n' + '\n' + ), + link=None, + level=3, + num='5.12.16') + +RQ_SRS_006_RBAC_Revoke_Privilege_Multiple = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Multiple', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking MULTIPLE **privileges** to one or more users or roles\n' + 'for a database or a table using the `REVOKE privilege1, privilege2...` statement.\n' + '**privileges** refers to any set of Clickhouse defined privilege, whose hierarchy includes\n' + 'SELECT, INSERT, ALTER, CREATE, DROP, TRUNCATE, OPTIMIZE, SHOW, KILL QUERY, ACCESS MANAGEMENT,\n' + 'SYSTEM, INTROSPECTION, SOURCES, dictGet and all of their sub-privileges.\n' + '\n' + ), + link=None, + level=3, + num='5.12.17') + +RQ_SRS_006_RBAC_Revoke_Privilege_All = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **all** privileges to one or more users or roles\n' + 'for a database or a table using the `REVOKE ALL` or `REVOKE ALL PRIVILEGES` statements.\n' + '\n' + ), + link=None, + level=3, + num='5.12.18') + +RQ_SRS_006_RBAC_Revoke_Privilege_None = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **no** privileges to one or more users or roles\n' + 'for a database or a table using the `REVOKE NONE` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.12.19') + +RQ_SRS_006_RBAC_Revoke_Privilege_On = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.On', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the `ON` clause in the `REVOKE` privilege statement\n' + 'which SHALL allow to specify one or more tables to which the privilege SHALL\n' + 'be revoked using the following patterns\n' + '\n' + '* `db.table` specific table in the specified database\n' + '* `db.*` any table in the specified database\n' + '* `*.*` any table in any database\n' + '* `table` specific table in the current database\n' + '* `*` any table in the current database\n' + '\n' + ), + link=None, + level=3, + num='5.12.20') + +RQ_SRS_006_RBAC_Revoke_Privilege_From = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.From', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the `FROM` clause in the `REVOKE` privilege statement\n' + 'which SHALL allow to specify one or more users to which the privilege SHALL\n' + 'be revoked using the following patterns\n' + '\n' + '* `{user | CURRENT_USER} [,...]` some combination of users by name, which may include the current user\n' + '* `ALL` all users\n' + '* `ALL EXCEPT {user | CURRENT_USER} [,...]` the logical reverse of the first pattern\n' + '\n' + ), + link=None, + level=3, + num='5.12.21') + +RQ_SRS_006_RBAC_Revoke_Privilege_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Privilege.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `REVOKE` statement that\n' + 'revokes explicit privileges of a user or a role.\n' + '\n' + '```sql\n' + 'REVOKE [ON CLUSTER cluster_name] privilege\n' + ' [(column_name [,...])] [,...]\n' + ' ON {db.table|db.*|*.*|table|*}\n' + ' FROM {user | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user | CURRENT_USER} [,...]\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='5.12.22') + +RQ_SRS_006_RBAC_Grant_Role = Requirement( + name='RQ.SRS-006.RBAC.Grant.Role', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting one or more roles to\n' + 'one or more users or roles using the `GRANT` role statement.\n' + '\n' + ), + link=None, + level=3, + num='5.13.1') + +RQ_SRS_006_RBAC_Grant_Role_CurrentUser = Requirement( + name='RQ.SRS-006.RBAC.Grant.Role.CurrentUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting one or more roles to current user using\n' + '`TO CURRENT_USER` clause in the `GRANT` role statement.\n' + '\n' + ), + link=None, + level=3, + num='5.13.2') + +RQ_SRS_006_RBAC_Grant_Role_AdminOption = Requirement( + name='RQ.SRS-006.RBAC.Grant.Role.AdminOption', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting `admin option` privilege\n' + 'to one or more users or roles using the `WITH ADMIN OPTION` clause\n' + 'in the `GRANT` role statement.\n' + '\n' + ), + link=None, + level=3, + num='5.13.3') + +RQ_SRS_006_RBAC_Grant_Role_OnCluster = Requirement( + name='RQ.SRS-006.RBAC.Grant.Role.OnCluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying cluster on which the user is to be granted one or more roles\n' + 'using `ON CLUSTER` clause in the `GRANT` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.13.4') + +RQ_SRS_006_RBAC_Grant_Role_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Grant.Role.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for `GRANT` role statement\n' + '\n' + '``` sql\n' + 'GRANT\n' + ' ON CLUSTER cluster_name\n' + ' role [, role ...]\n' + ' TO {user | role | CURRENT_USER} [,...]\n' + ' [WITH ADMIN OPTION]\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='5.13.5') + +RQ_SRS_006_RBAC_Revoke_Role = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Role', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking one or more roles from\n' + 'one or more users or roles using the `REVOKE` role statement.\n' + '\n' + ), + link=None, + level=3, + num='5.14.1') + +RQ_SRS_006_RBAC_Revoke_Role_Keywords = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Role.Keywords', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking one or more roles from\n' + 'special groupings of one or more users or roles with the `ALL`, `ALL EXCEPT`,\n' + 'and `CURRENT_USER` keywords.\n' + '\n' + ), + link=None, + level=3, + num='5.14.2') + +RQ_SRS_006_RBAC_Revoke_Role_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Role.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking one or more roles from\n' + 'one or more users or roles from one or more clusters\n' + 'using the `REVOKE ON CLUSTER` role statement.\n' + '\n' + ), + link=None, + level=3, + num='5.14.3') + +RQ_SRS_006_RBAC_Revoke_AdminOption = Requirement( + name='RQ.SRS-006.RBAC.Revoke.AdminOption', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking `admin option` privilege\n' + 'in one or more users or roles using the `ADMIN OPTION FOR` clause\n' + 'in the `REVOKE` role statement.\n' + '\n' + ), + link=None, + level=3, + num='5.14.4') + +RQ_SRS_006_RBAC_Revoke_Role_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Revoke.Role.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following syntax for the `REVOKE` role statement\n' + '\n' + '```sql\n' + 'REVOKE [ON CLUSTER cluster_name] [ADMIN OPTION FOR]\n' + ' role [,...]\n' + ' FROM {user | role | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user_name | role_name | CURRENT_USER} [,...]\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='5.14.5') + +RQ_SRS_006_RBAC_Show_Grants = Requirement( + name='RQ.SRS-006.RBAC.Show.Grants', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support listing all the privileges granted to current user and role\n' + 'using the `SHOW GRANTS` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.15.1') + +RQ_SRS_006_RBAC_Show_Grants_For = Requirement( + name='RQ.SRS-006.RBAC.Show.Grants.For', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support listing all the privileges granted to a user or a role\n' + 'using the `FOR` clause in the `SHOW GRANTS` statement.\n' + '\n' + ), + link=None, + level=3, + num='5.15.2') + +RQ_SRS_006_RBAC_Show_Grants_Syntax = Requirement( + name='RQ.SRS-006.RBAC.Show.Grants.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[Clickhouse] SHALL use the following syntax for the `SHOW GRANTS` statement\n' + '\n' + '``` sql\n' + 'SHOW GRANTS [FOR user_or_role]\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='5.15.3') + +RQ_SRS_006_RBAC_Table_PublicTables = Requirement( + name='RQ.SRS-006.RBAC.Table.PublicTables', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support that a user without any privileges will be able to access the following tables\n' + '\n' + '* system.one\n' + '* system.numbers\n' + '* system.contributors\n' + '* system.functions\n' + '\n' + ), + link=None, + level=3, + num='5.16.1') + +RQ_SRS_006_RBAC_Table_SensitiveTables = Requirement( + name='RQ.SRS-006.RBAC.Table.SensitiveTables', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL not support a user with no privileges accessing the following `system` tables:\n' + '\n' + '* processes\n' + '* query_log\n' + '* query_thread_log\n' + '* clusters\n' + '* events\n' + '* graphite_retentions\n' + '* stack_trace\n' + '* trace_log\n' + '* user_directories\n' + '* zookeeper\n' + '* macros\n' + '\n' + ), + link=None, + level=3, + num='5.16.2') + +RQ_SRS_006_RBAC_DistributedTable_Create = Requirement( + name='RQ.SRS-006.RBAC.DistributedTable.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully `CREATE` a distributed table if and only if\n' + 'the user has **create table** privilege on the table and **remote** privilege on *.*\n' + '\n' + ), + link=None, + level=3, + num='5.17.1') + +RQ_SRS_006_RBAC_DistributedTable_Select = Requirement( + name='RQ.SRS-006.RBAC.DistributedTable.Select', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully `SELECT` from a distributed table if and only if\n' + 'the user has **select** privilege on the table and on the remote table specified in the `CREATE` query of the distributed table.\n' + '\n' + 'Does not require **select** privilege for the remote table if the remote table does not exist on the same server as the user.\n' + '\n' + ), + link=None, + level=3, + num='5.17.2') + +RQ_SRS_006_RBAC_DistributedTable_Insert = Requirement( + name='RQ.SRS-006.RBAC.DistributedTable.Insert', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully `INSERT` into a distributed table if and only if\n' + 'the user has **insert** privilege on the table and on the remote table specified in the `CREATE` query of the distributed table.\n' + '\n' + 'Does not require **insert** privilege for the remote table if the remote table does not exist on the same server as the user,\n' + 'insert executes into the remote table on a different server.\n' + '\n' + ), + link=None, + level=3, + num='5.17.3') + +RQ_SRS_006_RBAC_DistributedTable_SpecialTables = Requirement( + name='RQ.SRS-006.RBAC.DistributedTable.SpecialTables', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute a query using a distributed table that uses one of the special tables if and only if\n' + 'the user has the necessary privileges to interact with that special table, either granted directly or through a role.\n' + 'Special tables include:\n' + '* materialized view\n' + '* distributed table\n' + '* source table of a materialized view\n' + '\n' + ), + link=None, + level=3, + num='5.17.4') + +RQ_SRS_006_RBAC_DistributedTable_LocalUser = Requirement( + name='RQ.SRS-006.RBAC.DistributedTable.LocalUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute a query using a distributed table from\n' + 'a user present locally, but not remotely.\n' + '\n' + ), + link=None, + level=3, + num='5.17.5') + +RQ_SRS_006_RBAC_DistributedTable_SameUserDifferentNodesDifferentPrivileges = Requirement( + name='RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute a query using a distributed table by a user that exists on multiple nodes\n' + 'if and only if the user has the required privileges on the node the query is being executed from.\n' + '\n' + ), + link=None, + level=3, + num='5.17.6') + +RQ_SRS_006_RBAC_View = Requirement( + name='RQ.SRS-006.RBAC.View', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to **create**, **select** and **drop**\n' + 'privileges for a view for users or roles.\n' + '\n' + ), + link=None, + level=4, + num='5.18.1.1') + +RQ_SRS_006_RBAC_View_Create = Requirement( + name='RQ.SRS-006.RBAC.View.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully execute a `CREATE VIEW` command if and only if\n' + 'the user has **create view** privilege either explicitly or through roles.\n' + '\n' + 'If the stored query includes one or more source tables, the user must have **select** privilege\n' + 'on all the source tables either explicitly or through a role.\n' + 'For example,\n' + '```sql\n' + 'CREATE VIEW view AS SELECT * FROM source_table\n' + 'CREATE VIEW view AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' + 'CREATE VIEW view AS SELECT * FROM table0 JOIN table1 USING column\n' + 'CREATE VIEW view AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' + 'CREATE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' + 'CREATE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.18.1.2') + +RQ_SRS_006_RBAC_View_Select = Requirement( + name='RQ.SRS-006.RBAC.View.Select', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully `SELECT` from a view if and only if\n' + 'the user has **select** privilege for that view either explicitly or through a role.\n' + '\n' + 'If the stored query includes one or more source tables, the user must have **select** privilege\n' + 'on all the source tables either explicitly or through a role.\n' + 'For example,\n' + '```sql\n' + 'CREATE VIEW view AS SELECT * FROM source_table\n' + 'CREATE VIEW view AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' + 'CREATE VIEW view AS SELECT * FROM table0 JOIN table1 USING column\n' + 'CREATE VIEW view AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' + 'CREATE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' + 'CREATE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' + '\n' + 'SELECT * FROM view\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.18.1.3') + +RQ_SRS_006_RBAC_View_Drop = Requirement( + name='RQ.SRS-006.RBAC.View.Drop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if\n' + 'the user has **drop view** privilege on that view either explicitly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.18.1.4') + +RQ_SRS_006_RBAC_MaterializedView = Requirement( + name='RQ.SRS-006.RBAC.MaterializedView', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to **create**, **select**, **alter** and **drop**\n' + 'privileges for a materialized view for users or roles.\n' + '\n' + ), + link=None, + level=4, + num='5.18.2.1') + +RQ_SRS_006_RBAC_MaterializedView_Create = Requirement( + name='RQ.SRS-006.RBAC.MaterializedView.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully execute a `CREATE MATERIALIZED VIEW` command if and only if\n' + 'the user has **create view** privilege either explicitly or through roles.\n' + '\n' + 'If `POPULATE` is specified, the user must have `INSERT` privilege on the view,\n' + 'either explicitly or through roles.\n' + 'For example,\n' + '```sql\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory POPULATE AS SELECT * FROM source_table\n' + '```\n' + '\n' + 'If the stored query includes one or more source tables, the user must have **select** privilege\n' + 'on all the source tables either explicitly or through a role.\n' + 'For example,\n' + '```sql\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM source_table\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 JOIN table1 USING column\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' + 'CREATE MATERIALIZED VIEW view0 ENGINE = Memory AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' + '```\n' + '\n' + 'If the materialized view has a target table explicitly declared in the `TO` clause, the user must have\n' + '**insert** and **select** privilege on the target table.\n' + 'For example,\n' + '```sql\n' + 'CREATE MATERIALIZED VIEW view TO target_table AS SELECT * FROM source_table\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.18.2.2') + +RQ_SRS_006_RBAC_MaterializedView_Select = Requirement( + name='RQ.SRS-006.RBAC.MaterializedView.Select', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully `SELECT` from a materialized view if and only if\n' + 'the user has **select** privilege for that view either explicitly or through a role.\n' + '\n' + 'If the stored query includes one or more source tables, the user must have **select** privilege\n' + 'on all the source tables either explicitly or through a role.\n' + 'For example,\n' + '```sql\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM source_table\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 JOIN table1 USING column\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' + 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' + 'CREATE MATERIALIZED VIEW view0 ENGINE = Memory AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' + '\n' + 'SELECT * FROM view\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.18.2.3') + +RQ_SRS_006_RBAC_MaterializedView_Select_TargetTable = Requirement( + name='RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully `SELECT` from the target table, implicit or explicit, of a materialized view if and only if\n' + 'the user has `SELECT` privilege for the table, either explicitly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.18.2.4') + +RQ_SRS_006_RBAC_MaterializedView_Select_SourceTable = Requirement( + name='RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully `SELECT` from the source table of a materialized view if and only if\n' + 'the user has `SELECT` privilege for the table, either explicitly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.18.2.5') + +RQ_SRS_006_RBAC_MaterializedView_Drop = Requirement( + name='RQ.SRS-006.RBAC.MaterializedView.Drop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if\n' + 'the user has **drop view** privilege on that view either explicitly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.18.2.6') + +RQ_SRS_006_RBAC_MaterializedView_ModifyQuery = Requirement( + name='RQ.SRS-006.RBAC.MaterializedView.ModifyQuery', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully execute a `MODIFY QUERY` command if and only if\n' + 'the user has **modify query** privilege on that view either explicitly or through a role.\n' + '\n' + 'If the new query includes one or more source tables, the user must have **select** privilege\n' + 'on all the source tables either explicitly or through a role.\n' + 'For example,\n' + '```sql\n' + 'ALTER TABLE view MODIFY QUERY SELECT * FROM source_table\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.18.2.7') + +RQ_SRS_006_RBAC_MaterializedView_Insert = Requirement( + name='RQ.SRS-006.RBAC.MaterializedView.Insert', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only succesfully `INSERT` into a materialized view if and only if\n' + 'the user has `INSERT` privilege on the view, either explicitly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.18.2.8') + +RQ_SRS_006_RBAC_MaterializedView_Insert_SourceTable = Requirement( + name='RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only succesfully `INSERT` into a source table of a materialized view if and only if\n' + 'the user has `INSERT` privilege on the source table, either explicitly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.18.2.9') + +RQ_SRS_006_RBAC_MaterializedView_Insert_TargetTable = Requirement( + name='RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only succesfully `INSERT` into a target table of a materialized view if and only if\n' + 'the user has `INSERT` privelege on the target table, either explicitly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.18.2.10') + +RQ_SRS_006_RBAC_LiveView = Requirement( + name='RQ.SRS-006.RBAC.LiveView', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to **create**, **select**, **alter** and **drop**\n' + 'privileges for a live view for users or roles.\n' + '\n' + ), + link=None, + level=4, + num='5.18.3.1') + +RQ_SRS_006_RBAC_LiveView_Create = Requirement( + name='RQ.SRS-006.RBAC.LiveView.Create', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully execute a `CREATE LIVE VIEW` command if and only if\n' + 'the user has **create view** privilege either explicitly or through roles.\n' + '\n' + 'If the stored query includes one or more source tables, the user must have **select** privilege\n' + 'on all the source tables either explicitly or through a role.\n' + 'For example,\n' + '```sql\n' + 'CREATE LIVE VIEW view AS SELECT * FROM source_table\n' + 'CREATE LIVE VIEW view AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' + 'CREATE LIVE VIEW view AS SELECT * FROM table0 JOIN table1 USING column\n' + 'CREATE LIVE VIEW view AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' + 'CREATE LIVE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' + 'CREATE LIVE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.18.3.2') + +RQ_SRS_006_RBAC_LiveView_Select = Requirement( + name='RQ.SRS-006.RBAC.LiveView.Select', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully `SELECT` from a live view if and only if\n' + 'the user has **select** privilege for that view either explicitly or through a role.\n' + '\n' + 'If the stored query includes one or more source tables, the user must have **select** privilege\n' + 'on all the source tables either explicitly or through a role.\n' + 'For example,\n' + '```sql\n' + 'CREATE LIVE VIEW view AS SELECT * FROM source_table\n' + 'CREATE LIVE VIEW view AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' + 'CREATE LIVE VIEW view AS SELECT * FROM table0 JOIN table1 USING column\n' + 'CREATE LIVE VIEW view AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' + 'CREATE LIVE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' + 'CREATE LIVE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' + '\n' + 'SELECT * FROM view\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.18.3.3') + +RQ_SRS_006_RBAC_LiveView_Drop = Requirement( + name='RQ.SRS-006.RBAC.LiveView.Drop', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if\n' + 'the user has **drop view** privilege on that view either explicitly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.18.3.4') + +RQ_SRS_006_RBAC_LiveView_Refresh = Requirement( + name='RQ.SRS-006.RBAC.LiveView.Refresh', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully execute an `ALTER LIVE VIEW REFRESH` command if and only if\n' + 'the user has **refresh** privilege on that view either explicitly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.18.3.5') + +RQ_SRS_006_RBAC_Select = Requirement( + name='RQ.SRS-006.RBAC.Select', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL execute `SELECT` if and only if the user\n' + 'has the **select** privilege for the destination table\n' + 'either because of the explicit grant or through one of the roles assigned to the user.\n' + '\n' + ), + link=None, + level=3, + num='5.19.1') + +RQ_SRS_006_RBAC_Select_Column = Requirement( + name='RQ.SRS-006.RBAC.Select.Column', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking **select** privilege\n' + 'for one or more specified columns in a table to one or more **users** or **roles**.\n' + 'Any `SELECT` statements SHALL not to be executed, unless the user\n' + 'has the **select** privilege for the destination column\n' + 'either because of the explicit grant or through one of the roles assigned to the user.\n' + '\n' + ), + link=None, + level=3, + num='5.19.2') + +RQ_SRS_006_RBAC_Select_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Select.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking **select** privilege\n' + 'on a specified cluster to one or more **users** or **roles**.\n' + 'Any `SELECT` statements SHALL succeed only on nodes where\n' + 'the table exists and privilege was granted.\n' + '\n' + ), + link=None, + level=3, + num='5.19.3') + +RQ_SRS_006_RBAC_Select_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Select.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **select** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '* ReplacingMergeTree\n' + '* SummingMergeTree\n' + '* AggregatingMergeTree\n' + '* CollapsingMergeTree\n' + '* VersionedCollapsingMergeTree\n' + '* GraphiteMergeTree\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=3, + num='5.19.4') + +RQ_SRS_006_RBAC_Insert = Requirement( + name='RQ.SRS-006.RBAC.Insert', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL execute `INSERT INTO` if and only if the user\n' + 'has the **insert** privilege for the destination table\n' + 'either because of the explicit grant or through one of the roles assigned to the user.\n' + '\n' + ), + link=None, + level=3, + num='5.20.1') + +RQ_SRS_006_RBAC_Insert_Column = Requirement( + name='RQ.SRS-006.RBAC.Insert.Column', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking **insert** privilege\n' + 'for one or more specified columns in a table to one or more **users** or **roles**.\n' + 'Any `INSERT INTO` statements SHALL not to be executed, unless the user\n' + 'has the **insert** privilege for the destination column\n' + 'either because of the explicit grant or through one of the roles assigned to the user.\n' + '\n' + ), + link=None, + level=3, + num='5.20.2') + +RQ_SRS_006_RBAC_Insert_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Insert.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking **insert** privilege\n' + 'on a specified cluster to one or more **users** or **roles**.\n' + 'Any `INSERT INTO` statements SHALL succeed only on nodes where\n' + 'the table exists and privilege was granted.\n' + '\n' + ), + link=None, + level=3, + num='5.20.3') + +RQ_SRS_006_RBAC_Insert_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Insert.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **insert** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '* ReplacingMergeTree\n' + '* SummingMergeTree\n' + '* AggregatingMergeTree\n' + '* CollapsingMergeTree\n' + '* VersionedCollapsingMergeTree\n' + '* GraphiteMergeTree\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=3, + num='5.20.4') + +RQ_SRS_006_RBAC_Privileges_AlterColumn = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterColumn', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter column** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN` statements SHALL\n' + 'return an error, unless the user has the **alter column** privilege for\n' + 'the destination table either because of the explicit grant or through one of\n' + 'the roles assigned to the user.\n' + '\n' + ), + link=None, + level=4, + num='5.21.1.1') + +RQ_SRS_006_RBAC_Privileges_AlterColumn_Grant = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting **alter column** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.1.2') + +RQ_SRS_006_RBAC_Privileges_AlterColumn_Revoke = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **alter column** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**\n' + '\n' + ), + link=None, + level=4, + num='5.21.1.3') + +RQ_SRS_006_RBAC_Privileges_AlterColumn_Column = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Column', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking **alter column** privilege\n' + 'for one or more specified columns in a table to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN` statements SHALL return an error,\n' + 'unless the user has the **alter column** privilege for the destination column\n' + 'either because of the explicit grant or through one of the roles assigned to the user.\n' + '\n' + ), + link=None, + level=4, + num='5.21.1.4') + +RQ_SRS_006_RBAC_Privileges_AlterColumn_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking **alter column** privilege\n' + 'on a specified cluster to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN`\n' + 'statements SHALL succeed only on nodes where the table exists and privilege was granted.\n' + '\n' + ), + link=None, + level=4, + num='5.21.1.5') + +RQ_SRS_006_RBAC_Privileges_AlterColumn_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter column** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '* ReplacingMergeTree\n' + '* SummingMergeTree\n' + '* AggregatingMergeTree\n' + '* CollapsingMergeTree\n' + '* VersionedCollapsingMergeTree\n' + '* GraphiteMergeTree\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=4, + num='5.21.1.6') + +RQ_SRS_006_RBAC_Privileges_AlterIndex = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterIndex', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter index** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... ORDER BY | ADD|DROP|MATERIALIZE|CLEAR INDEX` statements SHALL\n' + 'return an error, unless the user has the **alter index** privilege for\n' + 'the destination table either because of the explicit grant or through one of\n' + 'the roles assigned to the user.\n' + '\n' + ), + link=None, + level=4, + num='5.21.2.1') + +RQ_SRS_006_RBAC_Privileges_AlterIndex_Grant = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting **alter index** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.2.2') + +RQ_SRS_006_RBAC_Privileges_AlterIndex_Revoke = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **alter index** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**\n' + '\n' + ), + link=None, + level=4, + num='5.21.2.3') + +RQ_SRS_006_RBAC_Privileges_AlterIndex_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking **alter index** privilege\n' + 'on a specified cluster to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... ORDER BY | ADD|DROP|MATERIALIZE|CLEAR INDEX`\n' + 'statements SHALL succeed only on nodes where the table exists and privilege was granted.\n' + '\n' + ), + link=None, + level=4, + num='5.21.2.4') + +RQ_SRS_006_RBAC_Privileges_AlterIndex_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter index** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '* ReplacingMergeTree\n' + '* SummingMergeTree\n' + '* AggregatingMergeTree\n' + '* CollapsingMergeTree\n' + '* VersionedCollapsingMergeTree\n' + '* GraphiteMergeTree\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=4, + num='5.21.2.5') + +RQ_SRS_006_RBAC_Privileges_AlterConstraint = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterConstraint', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter constraint** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... ADD|CREATE CONSTRAINT` statements SHALL\n' + 'return an error, unless the user has the **alter constraint** privilege for\n' + 'the destination table either because of the explicit grant or through one of\n' + 'the roles assigned to the user.\n' + '\n' + ), + link=None, + level=4, + num='5.21.3.1') + +RQ_SRS_006_RBAC_Privileges_AlterConstraint_Grant = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting **alter constraint** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.3.2') + +RQ_SRS_006_RBAC_Privileges_AlterConstraint_Revoke = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **alter constraint** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**\n' + '\n' + ), + link=None, + level=4, + num='5.21.3.3') + +RQ_SRS_006_RBAC_Privileges_AlterConstraint_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking **alter constraint** privilege\n' + 'on a specified cluster to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... ADD|DROP CONSTRAINT`\n' + 'statements SHALL succeed only on nodes where the table exists and privilege was granted.\n' + '\n' + ), + link=None, + level=4, + num='5.21.3.4') + +RQ_SRS_006_RBAC_Privileges_AlterConstraint_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter constraint** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '* ReplacingMergeTree\n' + '* SummingMergeTree\n' + '* AggregatingMergeTree\n' + '* CollapsingMergeTree\n' + '* VersionedCollapsingMergeTree\n' + '* GraphiteMergeTree\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=4, + num='5.21.3.5') + +RQ_SRS_006_RBAC_Privileges_AlterTTL = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterTTL', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter ttl** or **alter materialize ttl** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... ALTER TTL | ALTER MATERIALIZE TTL` statements SHALL\n' + 'return an error, unless the user has the **alter ttl** or **alter materialize ttl** privilege for\n' + 'the destination table either because of the explicit grant or through one of\n' + 'the roles assigned to the user.\n' + '\n' + ), + link=None, + level=4, + num='5.21.4.1') + +RQ_SRS_006_RBAC_Privileges_AlterTTL_Grant = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting **alter ttl** or **alter materialize ttl** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.4.2') + +RQ_SRS_006_RBAC_Privileges_AlterTTL_Revoke = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **alter ttl** or **alter materialize ttl** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**\n' + '\n' + ), + link=None, + level=4, + num='5.21.4.3') + +RQ_SRS_006_RBAC_Privileges_AlterTTL_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking **alter ttl** or **alter materialize ttl** privilege\n' + 'on a specified cluster to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... ALTER TTL | ALTER MATERIALIZE TTL`\n' + 'statements SHALL succeed only on nodes where the table exists and privilege was granted.\n' + '\n' + ), + link=None, + level=4, + num='5.21.4.4') + +RQ_SRS_006_RBAC_Privileges_AlterTTL_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter ttl** or **alter materialize ttl** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '\n' + ), + link=None, + level=4, + num='5.21.4.5') + +RQ_SRS_006_RBAC_Privileges_AlterSettings = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterSettings', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter settings** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... MODIFY SETTING setting` statements SHALL\n' + 'return an error, unless the user has the **alter settings** privilege for\n' + 'the destination table either because of the explicit grant or through one of\n' + 'the roles assigned to the user. The **alter settings** privilege allows\n' + 'modifying table engine settings. It doesn’t affect settings or server configuration parameters.\n' + '\n' + ), + link=None, + level=4, + num='5.21.5.1') + +RQ_SRS_006_RBAC_Privileges_AlterSettings_Grant = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting **alter settings** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.5.2') + +RQ_SRS_006_RBAC_Privileges_AlterSettings_Revoke = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **alter settings** privilege\n' + 'for a database or a specific table to one or more **users** or **roles**\n' + '\n' + ), + link=None, + level=4, + num='5.21.5.3') + +RQ_SRS_006_RBAC_Privileges_AlterSettings_Cluster = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking **alter settings** privilege\n' + 'on a specified cluster to one or more **users** or **roles**.\n' + 'Any `ALTER TABLE ... MODIFY SETTING setting`\n' + 'statements SHALL succeed only on nodes where the table exists and privilege was granted.\n' + '\n' + ), + link=None, + level=4, + num='5.21.5.4') + +RQ_SRS_006_RBAC_Privileges_AlterSettings_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter settings** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '* ReplacingMergeTree\n' + '* SummingMergeTree\n' + '* AggregatingMergeTree\n' + '* CollapsingMergeTree\n' + '* VersionedCollapsingMergeTree\n' + '* GraphiteMergeTree\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=4, + num='5.21.5.5') + +RQ_SRS_006_RBAC_Privileges_AlterUpdate = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterUpdate', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ALTER UPDATE` statement if and only if the user has **alter update** privilege for that column,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.21.6.1') + +RQ_SRS_006_RBAC_Privileges_AlterUpdate_Grant = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting **alter update** privilege on a column level\n' + 'to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.6.2') + +RQ_SRS_006_RBAC_Privileges_AlterUpdate_Revoke = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **alter update** privilege on a column level\n' + 'from one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.6.3') + +RQ_SRS_006_RBAC_Privileges_AlterUpdate_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter update** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '* ReplacingMergeTree\n' + '* SummingMergeTree\n' + '* AggregatingMergeTree\n' + '* CollapsingMergeTree\n' + '* VersionedCollapsingMergeTree\n' + '* GraphiteMergeTree\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=4, + num='5.21.6.4') + +RQ_SRS_006_RBAC_Privileges_AlterDelete = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterDelete', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ALTER DELETE` statement if and only if the user has **alter delete** privilege for that table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.21.7.1') + +RQ_SRS_006_RBAC_Privileges_AlterDelete_Grant = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting **alter delete** privilege on a column level\n' + 'to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.7.2') + +RQ_SRS_006_RBAC_Privileges_AlterDelete_Revoke = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **alter delete** privilege on a column level\n' + 'from one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.7.3') + +RQ_SRS_006_RBAC_Privileges_AlterDelete_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter delete** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '* ReplacingMergeTree\n' + '* SummingMergeTree\n' + '* AggregatingMergeTree\n' + '* CollapsingMergeTree\n' + '* VersionedCollapsingMergeTree\n' + '* GraphiteMergeTree\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=4, + num='5.21.7.4') + +RQ_SRS_006_RBAC_Privileges_AlterFreeze = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterFreeze', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ALTER FREEZE` statement if and only if the user has **alter freeze** privilege for that table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.21.8.1') + +RQ_SRS_006_RBAC_Privileges_AlterFreeze_Grant = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting **alter freeze** privilege on a column level\n' + 'to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.8.2') + +RQ_SRS_006_RBAC_Privileges_AlterFreeze_Revoke = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **alter freeze** privilege on a column level\n' + 'from one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.8.3') + +RQ_SRS_006_RBAC_Privileges_AlterFreeze_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter freeze** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '* ReplacingMergeTree\n' + '* SummingMergeTree\n' + '* AggregatingMergeTree\n' + '* CollapsingMergeTree\n' + '* VersionedCollapsingMergeTree\n' + '* GraphiteMergeTree\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=4, + num='5.21.8.4') + +RQ_SRS_006_RBAC_Privileges_AlterFetch = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterFetch', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ALTER FETCH` statement if and only if the user has **alter fetch** privilege for that table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.21.9.1') + +RQ_SRS_006_RBAC_Privileges_AlterFetch_Grant = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting **alter fetch** privilege on a column level\n' + 'to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.9.2') + +RQ_SRS_006_RBAC_Privileges_AlterFetch_Revoke = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **alter fetch** privilege on a column level\n' + 'from one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.9.3') + +RQ_SRS_006_RBAC_Privileges_AlterFetch_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter fetch** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=4, + num='5.21.9.4') + +RQ_SRS_006_RBAC_Privileges_AlterMove = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterMove', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ALTER MOVE` statement if and only if the user has **alter move**, **select**, and **alter delete** privilege on the source table\n' + 'and **insert** privilege on the target table, either directly or through a role.\n' + 'For example,\n' + '```sql\n' + 'ALTER TABLE source_table MOVE PARTITION 1 TO target_table\n' + '```\n' + '\n' + ), + link=None, + level=4, + num='5.21.10.1') + +RQ_SRS_006_RBAC_Privileges_AlterMove_Grant = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterMove.Grant', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting **alter move** privilege on a column level\n' + 'to one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.10.2') + +RQ_SRS_006_RBAC_Privileges_AlterMove_Revoke = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support revoking **alter move** privilege on a column level\n' + 'from one or more **users** or **roles**.\n' + '\n' + ), + link=None, + level=4, + num='5.21.10.3') + +RQ_SRS_006_RBAC_Privileges_AlterMove_TableEngines = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support controlling access to the **alter move** privilege\n' + 'on tables created using the following engines\n' + '\n' + '* MergeTree\n' + '* ReplacingMergeTree\n' + '* SummingMergeTree\n' + '* AggregatingMergeTree\n' + '* CollapsingMergeTree\n' + '* VersionedCollapsingMergeTree\n' + '* GraphiteMergeTree\n' + '* ReplicatedMergeTree\n' + '* ReplicatedSummingMergeTree\n' + '* ReplicatedReplacingMergeTree\n' + '* ReplicatedAggregatingMergeTree\n' + '* ReplicatedCollapsingMergeTree\n' + '* ReplicatedVersionedCollapsingMergeTree\n' + '* ReplicatedGraphiteMergeTree\n' + '\n' + ), + link=None, + level=4, + num='5.21.10.4') + +RQ_SRS_006_RBAC_Privileges_CreateTable = Requirement( + name='RQ.SRS-006.RBAC.Privileges.CreateTable', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only successfully execute a `CREATE TABLE` command if and only if\n' + 'the user has **create table** privilege either explicitly or through roles.\n' + '\n' + 'If the stored query includes one or more source tables, the user must have **select** privilege\n' + "on all the source tables and **insert** for the table they're trying to create either explicitly or through a role.\n" + 'For example,\n' + '```sql\n' + 'CREATE TABLE table AS SELECT * FROM source_table\n' + 'CREATE TABLE table AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' + 'CREATE TABLE table AS SELECT * FROM table0 JOIN table1 USING column\n' + 'CREATE TABLE table AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' + 'CREATE TABLE table AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' + 'CREATE TABLE table0 AS SELECT column FROM table1 UNION ALL SELECT column FROM table2\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='5.22.1') + +RQ_SRS_006_RBAC_Privileges_CreateDatabase = Requirement( + name='RQ.SRS-006.RBAC.Privileges.CreateDatabase', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `CREATE DATABASE` statement if and only if the user has **create database** privilege on the database,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.22.2') + +RQ_SRS_006_RBAC_Privileges_CreateDictionary = Requirement( + name='RQ.SRS-006.RBAC.Privileges.CreateDictionary', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `CREATE DICTIONARY` statement if and only if the user has **create dictionary** privilege on the dictionary,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.22.3') + +RQ_SRS_006_RBAC_Privileges_CreateTemporaryTable = Requirement( + name='RQ.SRS-006.RBAC.Privileges.CreateTemporaryTable', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `CREATE TEMPORARY TABLE` statement if and only if the user has **create temporary table** privilege on the table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.22.4') + +RQ_SRS_006_RBAC_Privileges_AttachDatabase = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AttachDatabase', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ATTACH DATABASE` statement if and only if the user has **create database** privilege on the database,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.23.1') + +RQ_SRS_006_RBAC_Privileges_AttachDictionary = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AttachDictionary', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ATTACH DICTIONARY` statement if and only if the user has **create dictionary** privilege on the dictionary,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.23.2') + +RQ_SRS_006_RBAC_Privileges_AttachTemporaryTable = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AttachTemporaryTable', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ATTACH TEMPORARY TABLE` statement if and only if the user has **create temporary table** privilege on the table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.23.3') + +RQ_SRS_006_RBAC_Privileges_AttachTable = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AttachTable', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ATTACH TABLE` statement if and only if the user has **create table** privilege on the table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.23.4') + +RQ_SRS_006_RBAC_Privileges_DropTable = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DropTable', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DROP TABLE` statement if and only if the user has **drop table** privilege on the table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.24.1') + +RQ_SRS_006_RBAC_Privileges_DropDatabase = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DropDatabase', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DROP DATABASE` statement if and only if the user has **drop database** privilege on the database,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.24.2') + +RQ_SRS_006_RBAC_Privileges_DropDictionary = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DropDictionary', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DROP DICTIONARY` statement if and only if the user has **drop dictionary** privilege on the dictionary,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.24.3') + +RQ_SRS_006_RBAC_Privileges_DetachTable = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DetachTable', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DETACH TABLE` statement if and only if the user has **drop table** privilege on the table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.25.1') + +RQ_SRS_006_RBAC_Privileges_DetachView = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DetachView', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DETACH VIEW` statement if and only if the user has **drop view** privilege on the view,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.25.2') + +RQ_SRS_006_RBAC_Privileges_DetachDatabase = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DetachDatabase', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DETACH DATABASE` statement if and only if the user has **drop database** privilege on the database,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.25.3') + +RQ_SRS_006_RBAC_Privileges_DetachDictionary = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DetachDictionary', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DETACH DICTIONARY` statement if and only if the user has **drop dictionary** privilege on the dictionary,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.25.4') + +RQ_SRS_006_RBAC_Privileges_Truncate = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Truncate', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `TRUNCATE TABLE` statement if and only if the user has **truncate table** privilege on the table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.26.1') + +RQ_SRS_006_RBAC_Privileges_Optimize = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Optimize', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `OPTIMIZE TABLE` statement if and only if the user has **optimize table** privilege on the table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.27.1') + +RQ_SRS_006_RBAC_Privileges_KillQuery = Requirement( + name='RQ.SRS-006.RBAC.Privileges.KillQuery', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `KILL QUERY` statement if and only if the user has **kill query** privilege,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.28.1') + +RQ_SRS_006_RBAC_Privileges_KillMutation = Requirement( + name='RQ.SRS-006.RBAC.Privileges.KillMutation', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `KILL MUTATION` statement if and only if\n' + 'the user has the privilege that created the mutation, either directly or through a role.\n' + 'For example, to `KILL MUTATION` after `ALTER UPDATE` query, the user needs `ALTER UPDATE` privilege.\n' + '\n' + ), + link=None, + level=3, + num='5.29.1') + +RQ_SRS_006_RBAC_Privileges_KillMutation_AlterUpdate = Requirement( + name='RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER UPDATE` mutation if and only if\n' + 'the user has `ALTER UPDATE` privilege on the table where the mutation was created, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.29.2') + +RQ_SRS_006_RBAC_Privileges_KillMutation_AlterDelete = Requirement( + name='RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER DELETE` mutation if and only if\n' + 'the user has `ALTER DELETE` privilege on the table where the mutation was created, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.29.3') + +RQ_SRS_006_RBAC_Privileges_KillMutation_AlterDropColumn = Requirement( + name='RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER DROP COLUMN` mutation if and only if\n' + 'the user has `ALTER DROP COLUMN` privilege on the table where the mutation was created, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.29.4') + +RQ_SRS_006_RBAC_ShowTables_Privilege = Requirement( + name='RQ.SRS-006.RBAC.ShowTables.Privilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL grant **show tables** privilege on a table to a user if that user has recieved any grant,\n' + 'including `SHOW TABLES`, on that table, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.1') + +RQ_SRS_006_RBAC_ShowTables_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW TABLES` statement if and only if the user has **show tables** privilege,\n' + 'or any privilege on the table either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.2') + +RQ_SRS_006_RBAC_ExistsTable_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `EXISTS table` statement if and only if the user has **show tables** privilege,\n' + 'or any privilege on the table either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.3') + +RQ_SRS_006_RBAC_CheckTable_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `CHECK table` statement if and only if the user has **show tables** privilege,\n' + 'or any privilege on the table either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.4') + +RQ_SRS_006_RBAC_ShowDatabases_Privilege = Requirement( + name='RQ.SRS-006.RBAC.ShowDatabases.Privilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL grant **show databases** privilege on a database to a user if that user has recieved any grant,\n' + 'including `SHOW DATABASES`, on that table, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.5') + +RQ_SRS_006_RBAC_ShowDatabases_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW DATABASES` statement if and only if the user has **show databases** privilege,\n' + 'or any privilege on the database either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.6') + +RQ_SRS_006_RBAC_ShowCreateDatabase_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW CREATE DATABASE` statement if and only if the user has **show databases** privilege,\n' + 'or any privilege on the database either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.7') + +RQ_SRS_006_RBAC_UseDatabase_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `USE database` statement if and only if the user has **show databases** privilege,\n' + 'or any privilege on the database either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.8') + +RQ_SRS_006_RBAC_ShowColumns_Privilege = Requirement( + name='RQ.SRS-006.RBAC.ShowColumns.Privilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking the `SHOW COLUMNS` privilege.\n' + '\n' + ), + link=None, + level=3, + num='5.30.9') + +RQ_SRS_006_RBAC_ShowCreateTable_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW CREATE TABLE` statement if and only if the user has **show columns** privilege on that table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.10') + +RQ_SRS_006_RBAC_DescribeTable_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DESCRIBE table` statement if and only if the user has **show columns** privilege on that table,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.11') + +RQ_SRS_006_RBAC_ShowDictionaries_Privilege = Requirement( + name='RQ.SRS-006.RBAC.ShowDictionaries.Privilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL grant **show dictionaries** privilege on a dictionary to a user if that user has recieved any grant,\n' + 'including `SHOW DICTIONARIES`, on that dictionary, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.12') + +RQ_SRS_006_RBAC_ShowDictionaries_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW DICTIONARIES` statement if and only if the user has **show dictionaries** privilege,\n' + 'or any privilege on the dictionary either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.13') + +RQ_SRS_006_RBAC_ShowCreateDictionary_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW CREATE DICTIONARY` statement if and only if the user has **show dictionaries** privilege,\n' + 'or any privilege on the dictionary either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.14') + +RQ_SRS_006_RBAC_ExistsDictionary_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `EXISTS dictionary` statement if and only if the user has **show dictionaries** privilege,\n' + 'or any privilege on the dictionary either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.30.15') + +RQ_SRS_006_RBAC_Privileges_CreateUser = Requirement( + name='RQ.SRS-006.RBAC.Privileges.CreateUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `CREATE USER` statement if and only if the user has **create user** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.1') + +RQ_SRS_006_RBAC_Privileges_CreateUser_DefaultRole = Requirement( + name='RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `CREATE USER` statement with `DEFAULT ROLE ` clause if and only if\n' + 'the user has **create user** privilege and the role with **admin option**, or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.2') + +RQ_SRS_006_RBAC_Privileges_AlterUser = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ALTER USER` statement if and only if the user has **alter user** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.3') + +RQ_SRS_006_RBAC_Privileges_DropUser = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DropUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DROP USER` statement if and only if the user has **drop user** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.4') + +RQ_SRS_006_RBAC_Privileges_CreateRole = Requirement( + name='RQ.SRS-006.RBAC.Privileges.CreateRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `CREATE ROLE` statement if and only if the user has **create role** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.5') + +RQ_SRS_006_RBAC_Privileges_AlterRole = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ALTER ROLE` statement if and only if the user has **alter role** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.6') + +RQ_SRS_006_RBAC_Privileges_DropRole = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DropRole', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DROP ROLE` statement if and only if the user has **drop role** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.7') + +RQ_SRS_006_RBAC_Privileges_CreateRowPolicy = Requirement( + name='RQ.SRS-006.RBAC.Privileges.CreateRowPolicy', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `CREATE ROW POLICY` statement if and only if the user has **create row policy** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.8') + +RQ_SRS_006_RBAC_Privileges_AlterRowPolicy = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterRowPolicy', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ALTER ROW POLICY` statement if and only if the user has **alter row policy** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.9') + +RQ_SRS_006_RBAC_Privileges_DropRowPolicy = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DropRowPolicy', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DROP ROW POLICY` statement if and only if the user has **drop row policy** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.10') + +RQ_SRS_006_RBAC_Privileges_CreateQuota = Requirement( + name='RQ.SRS-006.RBAC.Privileges.CreateQuota', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `CREATE QUOTA` statement if and only if the user has **create quota** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.11') + +RQ_SRS_006_RBAC_Privileges_AlterQuota = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterQuota', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ALTER QUOTA` statement if and only if the user has **alter quota** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.12') + +RQ_SRS_006_RBAC_Privileges_DropQuota = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DropQuota', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DROP QUOTA` statement if and only if the user has **drop quota** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.13') + +RQ_SRS_006_RBAC_Privileges_CreateSettingsProfile = Requirement( + name='RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `CREATE SETTINGS PROFILE` statement if and only if the user has **create settings profile** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.14') + +RQ_SRS_006_RBAC_Privileges_AlterSettingsProfile = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `ALTER SETTINGS PROFILE` statement if and only if the user has **alter settings profile** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.15') + +RQ_SRS_006_RBAC_Privileges_DropSettingsProfile = Requirement( + name='RQ.SRS-006.RBAC.Privileges.DropSettingsProfile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `DROP SETTINGS PROFILE` statement if and only if the user has **drop settings profile** privilege,\n' + 'or either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.31.16') + +RQ_SRS_006_RBAC_Privileges_RoleAdmin = Requirement( + name='RQ.SRS-006.RBAC.Privileges.RoleAdmin', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute any role grant or revoke by a user with `ROLE ADMIN` privilege.\n' + '\n' + ), + link=None, + level=3, + num='5.31.17') + +RQ_SRS_006_RBAC_ShowUsers_Privilege = Requirement( + name='RQ.SRS-006.RBAC.ShowUsers.Privilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SHOW USERS` privilege when\n' + 'the user is granted `SHOW USERS`, `SHOW CREATE USER`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.1') + +RQ_SRS_006_RBAC_ShowUsers_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW USERS` statement if and only if the user has **show users** privilege,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.2') + +RQ_SRS_006_RBAC_ShowCreateUser_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW CREATE USER` statement if and only if the user has **show users** privilege,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.3') + +RQ_SRS_006_RBAC_ShowRoles_Privilege = Requirement( + name='RQ.SRS-006.RBAC.ShowRoles.Privilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SHOW ROLES` privilege when\n' + 'the user is granted `SHOW ROLES`, `SHOW CREATE ROLE`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.4') + +RQ_SRS_006_RBAC_ShowRoles_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW ROLES` statement if and only if the user has **show roles** privilege,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.5') + +RQ_SRS_006_RBAC_ShowCreateRole_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW CREATE ROLE` statement if and only if the user has **show roles** privilege,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.6') + +RQ_SRS_006_RBAC_ShowRowPolicies_Privilege = Requirement( + name='RQ.SRS-006.RBAC.ShowRowPolicies.Privilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SHOW ROW POLICIES` privilege when\n' + 'the user is granted `SHOW ROW POLICIES`, `SHOW POLICIES`, `SHOW CREATE ROW POLICY`,\n' + '`SHOW CREATE POLICY`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.7') + +RQ_SRS_006_RBAC_ShowRowPolicies_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW ROW POLICIES` or `SHOW POLICIES` statement if and only if\n' + 'the user has **show row policies** privilege, either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.8') + +RQ_SRS_006_RBAC_ShowCreateRowPolicy_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW CREATE ROW POLICY` or `SHOW CREATE POLICY` statement\n' + 'if and only if the user has **show row policies** privilege,either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.9') + +RQ_SRS_006_RBAC_ShowQuotas_Privilege = Requirement( + name='RQ.SRS-006.RBAC.ShowQuotas.Privilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SHOW QUOTAS` privilege when\n' + 'the user is granted `SHOW QUOTAS`, `SHOW CREATE QUOTA`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.10') + +RQ_SRS_006_RBAC_ShowQuotas_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW QUOTAS` statement if and only if the user has **show quotas** privilege,\n' + 'either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.11') + +RQ_SRS_006_RBAC_ShowCreateQuota_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW CREATE QUOTA` statement if and only if\n' + 'the user has **show quotas** privilege, either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.12') + +RQ_SRS_006_RBAC_ShowSettingsProfiles_Privilege = Requirement( + name='RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SHOW SETTINGS PROFILES` privilege when\n' + 'the user is granted `SHOW SETTINGS PROFILES`, `SHOW PROFILES`, `SHOW CREATE SETTINGS PROFILE`,\n' + '`SHOW SETTINGS PROFILE`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.13') + +RQ_SRS_006_RBAC_ShowSettingsProfiles_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW SETTINGS PROFILES` or `SHOW PROFILES` statement\n' + 'if and only if the user has **show settings profiles** privilege, either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.14') + +RQ_SRS_006_RBAC_ShowCreateSettingsProfile_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `SHOW CREATE SETTINGS PROFILE` or `SHOW CREATE PROFILE` statement\n' + 'if and only if the user has **show settings profiles** privilege, either directly or through a role.\n' + '\n' + ), + link=None, + level=4, + num='5.31.18.15') + +RQ_SRS_006_RBAC_dictGet_Privilege = Requirement( + name='RQ.SRS-006.RBAC.dictGet.Privilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `dictGet` privilege when\n' + 'the user is granted `dictGet`, `dictHas`, `dictGetHierarchy`, or `dictIsIn`.\n' + '\n' + ), + link=None, + level=3, + num='5.32.1') + +RQ_SRS_006_RBAC_dictGet_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.dictGet.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `dictGet` statement\n' + 'if and only if the user has **dictGet** privilege on that dictionary, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.32.2') + +RQ_SRS_006_RBAC_dictGet_Type_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `dictGet[TYPE]` statement\n' + 'if and only if the user has **dictGet** privilege on that dictionary, either directly or through a role.\n' + 'Available types:\n' + '\n' + '* Int8\n' + '* Int16\n' + '* Int32\n' + '* Int64\n' + '* UInt8\n' + '* UInt16\n' + '* UInt32\n' + '* UInt64\n' + '* Float32\n' + '* Float64\n' + '* Date\n' + '* DateTime\n' + '* UUID\n' + '* String\n' + '\n' + ), + link=None, + level=3, + num='5.32.3') + +RQ_SRS_006_RBAC_dictGet_OrDefault_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `dictGetOrDefault` statement\n' + 'if and only if the user has **dictGet** privilege on that dictionary, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.32.4') + +RQ_SRS_006_RBAC_dictHas_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.dictHas.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `dictHas` statement\n' + 'if and only if the user has **dictGet** privilege, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.32.5') + +RQ_SRS_006_RBAC_dictGetHierarchy_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `dictGetHierarchy` statement\n' + 'if and only if the user has **dictGet** privilege, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.32.6') + +RQ_SRS_006_RBAC_dictIsIn_RequiredPrivilege = Requirement( + name='RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `dictIsIn` statement\n' + 'if and only if the user has **dictGet** privilege, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.32.7') + +RQ_SRS_006_RBAC_Privileges_Introspection = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Introspection', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `INTROSPECTION` privilege when\n' + 'the user is granted `INTROSPECTION` or `INTROSPECTION FUNCTIONS`.\n' + '\n' + ), + link=None, + level=3, + num='5.33.1') + +RQ_SRS_006_RBAC_Privileges_Introspection_addressToLine = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `addressToLine` statement if and only if\n' + 'the user has **introspection** privilege, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.33.2') + +RQ_SRS_006_RBAC_Privileges_Introspection_addressToSymbol = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `addressToSymbol` statement if and only if\n' + 'the user has **introspection** privilege, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.33.3') + +RQ_SRS_006_RBAC_Privileges_Introspection_demangle = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Introspection.demangle', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `demangle` statement if and only if\n' + 'the user has **introspection** privilege, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.33.4') + +RQ_SRS_006_RBAC_Privileges_System_Shutdown = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Shutdown', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM SHUTDOWN` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM SHUTDOWN`, `SHUTDOWN`,or `SYSTEM KILL`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.1') + +RQ_SRS_006_RBAC_Privileges_System_DropCache = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.DropCache', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM DROP CACHE` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, or `DROP CACHE`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.2') + +RQ_SRS_006_RBAC_Privileges_System_DropCache_DNS = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM DROP DNS CACHE` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP DNS CACHE`,\n' + '`SYSTEM DROP DNS`, `DROP DNS CACHE`, or `DROP DNS`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.3') + +RQ_SRS_006_RBAC_Privileges_System_DropCache_Mark = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM DROP MARK CACHE` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP MARK CACHE`,\n' + '`SYSTEM DROP MARK`, `DROP MARK CACHE`, or `DROP MARKS`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.4') + +RQ_SRS_006_RBAC_Privileges_System_DropCache_Uncompressed = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM DROP UNCOMPRESSED CACHE` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP UNCOMPRESSED CACHE`,\n' + '`SYSTEM DROP UNCOMPRESSED`, `DROP UNCOMPRESSED CACHE`, or `DROP UNCOMPRESSED`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.5') + +RQ_SRS_006_RBAC_Privileges_System_Reload = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Reload', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM RELOAD` privilege when\n' + 'the user is granted `SYSTEM` or `SYSTEM RELOAD`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.6') + +RQ_SRS_006_RBAC_Privileges_System_Reload_Config = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Reload.Config', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM RELOAD CONFIG` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD CONFIG`, or `RELOAD CONFIG`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.7') + +RQ_SRS_006_RBAC_Privileges_System_Reload_Dictionary = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM RELOAD DICTIONARY` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARIES`, `RELOAD DICTIONARIES`, or `RELOAD DICTIONARY`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.8') + +RQ_SRS_006_RBAC_Privileges_System_Reload_Dictionaries = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM RELOAD DICTIONARIES` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARIES`, `RELOAD DICTIONARIES`, or `RELOAD DICTIONARY`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.9') + +RQ_SRS_006_RBAC_Privileges_System_Reload_EmbeddedDictionaries = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM RELOAD EMBEDDED DICTIONARIES` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARY ON *.*`, or `SYSTEM RELOAD EMBEDDED DICTIONARIES`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.10') + +RQ_SRS_006_RBAC_Privileges_System_Merges = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Merges', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM MERGES` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM MERGES`, `SYSTEM STOP MERGES`, `SYSTEM START MERGES`, `STOP MERGES`, or `START MERGES`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.11') + +RQ_SRS_006_RBAC_Privileges_System_TTLMerges = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.TTLMerges', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM TTL MERGES` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM TTL MERGES`, `SYSTEM STOP TTL MERGES`, `SYSTEM START TTL MERGES`, `STOP TTL MERGES`, or `START TTL MERGES`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.12') + +RQ_SRS_006_RBAC_Privileges_System_Fetches = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Fetches', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM FETCHES` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM FETCHES`, `SYSTEM STOP FETCHES`, `SYSTEM START FETCHES`, `STOP FETCHES`, or `START FETCHES`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.13') + +RQ_SRS_006_RBAC_Privileges_System_Moves = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Moves', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM MOVES` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM MOVES`, `SYSTEM STOP MOVES`, `SYSTEM START MOVES`, `STOP MOVES`, or `START MOVES`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.14') + +RQ_SRS_006_RBAC_Privileges_System_Sends = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Sends', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM SENDS` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM SENDS`, `SYSTEM STOP SENDS`, `SYSTEM START SENDS`, `STOP SENDS`, or `START SENDS`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.15') + +RQ_SRS_006_RBAC_Privileges_System_Sends_Distributed = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM DISTRIBUTED SENDS` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM DISTRIBUTED SENDS`, `SYSTEM STOP DISTRIBUTED SENDS`,\n' + '`SYSTEM START DISTRIBUTED SENDS`, `STOP DISTRIBUTED SENDS`, or `START DISTRIBUTED SENDS`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.16') + +RQ_SRS_006_RBAC_Privileges_System_Sends_Replicated = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM REPLICATED SENDS` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM REPLICATED SENDS`, `SYSTEM STOP REPLICATED SENDS`,\n' + '`SYSTEM START REPLICATED SENDS`, `STOP REPLICATED SENDS`, or `START REPLICATED SENDS`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.17') + +RQ_SRS_006_RBAC_Privileges_System_ReplicationQueues = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM REPLICATION QUEUES` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM REPLICATION QUEUES`, `SYSTEM STOP REPLICATION QUEUES`,\n' + '`SYSTEM START REPLICATION QUEUES`, `STOP REPLICATION QUEUES`, or `START REPLICATION QUEUES`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.18') + +RQ_SRS_006_RBAC_Privileges_System_SyncReplica = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.SyncReplica', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM SYNC REPLICA` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM SYNC REPLICA`, or `SYNC REPLICA`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.19') + +RQ_SRS_006_RBAC_Privileges_System_RestartReplica = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.RestartReplica', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM RESTART REPLICA` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM RESTART REPLICA`, or `RESTART REPLICA`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.20') + +RQ_SRS_006_RBAC_Privileges_System_Flush = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Flush', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM FLUSH` privilege when\n' + 'the user is granted `SYSTEM` or `SYSTEM FLUSH`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.21') + +RQ_SRS_006_RBAC_Privileges_System_Flush_Distributed = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM FLUSH DISTRIBUTED` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM FLUSH DISTRIBUTED`, or `FLUSH DISTRIBUTED`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.22') + +RQ_SRS_006_RBAC_Privileges_System_Flush_Logs = Requirement( + name='RQ.SRS-006.RBAC.Privileges.System.Flush.Logs', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully grant `SYSTEM FLUSH LOGS` privilege when\n' + 'the user is granted `SYSTEM`, `SYSTEM FLUSH LOGS`, or `FLUSH LOGS`.\n' + '\n' + ), + link=None, + level=3, + num='5.34.23') + +RQ_SRS_006_RBAC_Privileges_Sources = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Sources', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking `SOURCES` privilege from\n' + 'the user, either directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.35.1') + +RQ_SRS_006_RBAC_Privileges_Sources_File = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Sources.File', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the use of `FILE` source by a user if and only if\n' + 'the user has `FILE` or `SOURCES` privileges granted to them directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.35.2') + +RQ_SRS_006_RBAC_Privileges_Sources_URL = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Sources.URL', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the use of `URL` source by a user if and only if\n' + 'the user has `URL` or `SOURCES` privileges granted to them directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.35.3') + +RQ_SRS_006_RBAC_Privileges_Sources_Remote = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Sources.Remote', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the use of `REMOTE` source by a user if and only if\n' + 'the user has `REMOTE` or `SOURCES` privileges granted to them directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.35.4') + +RQ_SRS_006_RBAC_Privileges_Sources_MySQL = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Sources.MySQL', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the use of `MySQL` source by a user if and only if\n' + 'the user has `MySQL` or `SOURCES` privileges granted to them directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.35.5') + +RQ_SRS_006_RBAC_Privileges_Sources_ODBC = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Sources.ODBC', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the use of `ODBC` source by a user if and only if\n' + 'the user has `ODBC` or `SOURCES` privileges granted to them directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.35.6') + +RQ_SRS_006_RBAC_Privileges_Sources_JDBC = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Sources.JDBC', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the use of `JDBC` source by a user if and only if\n' + 'the user has `JDBC` or `SOURCES` privileges granted to them directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.35.7') + +RQ_SRS_006_RBAC_Privileges_Sources_HDFS = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Sources.HDFS', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the use of `HDFS` source by a user if and only if\n' + 'the user has `HDFS` or `SOURCES` privileges granted to them directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.35.8') + +RQ_SRS_006_RBAC_Privileges_Sources_S3 = Requirement( + name='RQ.SRS-006.RBAC.Privileges.Sources.S3', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the use of `S3` source by a user if and only if\n' + 'the user has `S3` or `SOURCES` privileges granted to them directly or through a role.\n' + '\n' + ), + link=None, + level=3, + num='5.35.9') + +RQ_SRS_006_RBAC_Privileges_GrantOption = Requirement( + name='RQ.SRS-006.RBAC.Privileges.GrantOption', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL successfully execute `GRANT` or `REVOKE` privilege statements by a user if and only if\n' + 'the user has that privilege with `GRANT OPTION`, either directly or through a role.\n' + '\n' + ), + link=None, + level=2, + num='5.36') + +RQ_SRS_006_RBAC_Privileges_All = Requirement( + name='RQ.SRS-006.RBAC.Privileges.All', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking `ALL` privilege\n' + 'using `GRANT ALL ON *.* TO user`.\n' + '\n' + ), + link=None, + level=2, + num='5.37') + +RQ_SRS_006_RBAC_Privileges_RoleAll = Requirement( + name='RQ.SRS-006.RBAC.Privileges.RoleAll', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting a role named `ALL` using `GRANT ALL TO user`.\n' + 'This shall only grant the user the privileges that have been granted to the role.\n' + '\n' + ), + link=None, + level=2, + num='5.38') + +RQ_SRS_006_RBAC_Privileges_None = Requirement( + name='RQ.SRS-006.RBAC.Privileges.None', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support granting or revoking `NONE` privilege\n' + 'using `GRANT NONE TO user` or `GRANT USAGE ON *.* TO user`.\n' + '\n' + ), + link=None, + level=2, + num='5.39') + +RQ_SRS_006_RBAC_Privileges_AdminOption = Requirement( + name='RQ.SRS-006.RBAC.Privileges.AdminOption', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support a user granting or revoking a role if and only if\n' + 'the user has that role with `ADMIN OPTION` privilege.\n' + '\n' + ), + link=None, + level=2, + num='5.40') + SRS_006_ClickHouse_Role_Based_Access_Control = Specification( - name='SRS-006 ClickHouse Role Based Access Control', - description=None, - author=None, - date=None, - status=None, - approved_by=None, - approved_date=None, - approved_version=None, - version=None, - group=None, - type=None, - link=None, - uid=None, - parent=None, - children=None, - content=''' + name='SRS-006 ClickHouse Role Based Access Control', + description=None, + author=None, + date=None, + status=None, + approved_by=None, + approved_date=None, + approved_version=None, + version=None, + group=None, + type=None, + link=None, + uid=None, + parent=None, + children=None, + headings=( + Heading(name='Revision History', level=1, num='1'), + Heading(name='Introduction', level=1, num='2'), + Heading(name='Terminology', level=1, num='3'), + Heading(name='Privilege Definitions', level=1, num='4'), + Heading(name='Requirements', level=1, num='5'), + Heading(name='Generic', level=2, num='5.1'), + Heading(name='RQ.SRS-006.RBAC', level=3, num='5.1.1'), + Heading(name='Login', level=2, num='5.2'), + Heading(name='RQ.SRS-006.RBAC.Login', level=3, num='5.2.1'), + Heading(name='RQ.SRS-006.RBAC.Login.DefaultUser', level=3, num='5.2.2'), + Heading(name='User', level=2, num='5.3'), + Heading(name='RQ.SRS-006.RBAC.User', level=3, num='5.3.1'), + Heading(name='RQ.SRS-006.RBAC.User.Roles', level=3, num='5.3.2'), + Heading(name='RQ.SRS-006.RBAC.User.Privileges', level=3, num='5.3.3'), + Heading(name='RQ.SRS-006.RBAC.User.Variables', level=3, num='5.3.4'), + Heading(name='RQ.SRS-006.RBAC.User.Variables.Constraints', level=3, num='5.3.5'), + Heading(name='RQ.SRS-006.RBAC.User.SettingsProfile', level=3, num='5.3.6'), + Heading(name='RQ.SRS-006.RBAC.User.Quotas', level=3, num='5.3.7'), + Heading(name='RQ.SRS-006.RBAC.User.RowPolicies', level=3, num='5.3.8'), + Heading(name='RQ.SRS-006.RBAC.User.DefaultRole', level=3, num='5.3.9'), + Heading(name='RQ.SRS-006.RBAC.User.RoleSelection', level=3, num='5.3.10'), + Heading(name='RQ.SRS-006.RBAC.User.ShowCreate', level=3, num='5.3.11'), + Heading(name='RQ.SRS-006.RBAC.User.ShowPrivileges', level=3, num='5.3.12'), + Heading(name='RQ.SRS-006.RBAC.User.Use.DefaultRole', level=3, num='5.3.13'), + Heading(name='RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole', level=3, num='5.3.14'), + Heading(name='Create User', level=3, num='5.3.15'), + Heading(name='RQ.SRS-006.RBAC.User.Create', level=4, num='5.3.15.1'), + Heading(name='RQ.SRS-006.RBAC.User.Create.IfNotExists', level=4, num='5.3.15.2'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Replace', level=4, num='5.3.15.3'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.NoPassword', level=4, num='5.3.15.4'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.NoPassword.Login', level=4, num='5.3.15.5'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.PlainText', level=4, num='5.3.15.6'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.PlainText.Login', level=4, num='5.3.15.7'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Password', level=4, num='5.3.15.8'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Password.Login', level=4, num='5.3.15.9'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash', level=4, num='5.3.15.10'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash.Login', level=4, num='5.3.15.11'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password', level=4, num='5.3.15.12'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password.Login', level=4, num='5.3.15.13'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash', level=4, num='5.3.15.14'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash.Login', level=4, num='5.3.15.15'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Host.Name', level=4, num='5.3.15.16'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Host.Regexp', level=4, num='5.3.15.17'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Host.IP', level=4, num='5.3.15.18'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Host.Any', level=4, num='5.3.15.19'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Host.None', level=4, num='5.3.15.20'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Host.Local', level=4, num='5.3.15.21'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Host.Like', level=4, num='5.3.15.22'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Host.Default', level=4, num='5.3.15.23'), + Heading(name='RQ.SRS-006.RBAC.User.Create.DefaultRole', level=4, num='5.3.15.24'), + Heading(name='RQ.SRS-006.RBAC.User.Create.DefaultRole.None', level=4, num='5.3.15.25'), + Heading(name='RQ.SRS-006.RBAC.User.Create.DefaultRole.All', level=4, num='5.3.15.26'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Settings', level=4, num='5.3.15.27'), + Heading(name='RQ.SRS-006.RBAC.User.Create.OnCluster', level=4, num='5.3.15.28'), + Heading(name='RQ.SRS-006.RBAC.User.Create.Syntax', level=4, num='5.3.15.29'), + Heading(name='Alter User', level=3, num='5.3.16'), + Heading(name='RQ.SRS-006.RBAC.User.Alter', level=4, num='5.3.16.1'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.OrderOfEvaluation', level=4, num='5.3.16.2'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.IfExists', level=4, num='5.3.16.3'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Cluster', level=4, num='5.3.16.4'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Rename', level=4, num='5.3.16.5'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Password.PlainText', level=4, num='5.3.16.6'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Password.Sha256Password', level=4, num='5.3.16.7'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Password.DoubleSha1Password', level=4, num='5.3.16.8'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Host.AddDrop', level=4, num='5.3.16.9'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Host.Local', level=4, num='5.3.16.10'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Host.Name', level=4, num='5.3.16.11'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Host.Regexp', level=4, num='5.3.16.12'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Host.IP', level=4, num='5.3.16.13'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Host.Like', level=4, num='5.3.16.14'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Host.Any', level=4, num='5.3.16.15'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Host.None', level=4, num='5.3.16.16'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.DefaultRole', level=4, num='5.3.16.17'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.DefaultRole.All', level=4, num='5.3.16.18'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.DefaultRole.AllExcept', level=4, num='5.3.16.19'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Settings', level=4, num='5.3.16.20'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Settings.Min', level=4, num='5.3.16.21'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Settings.Max', level=4, num='5.3.16.22'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Settings.Profile', level=4, num='5.3.16.23'), + Heading(name='RQ.SRS-006.RBAC.User.Alter.Syntax', level=4, num='5.3.16.24'), + Heading(name='Show Create User', level=3, num='5.3.17'), + Heading(name='RQ.SRS-006.RBAC.User.ShowCreateUser', level=4, num='5.3.17.1'), + Heading(name='RQ.SRS-006.RBAC.User.ShowCreateUser.For', level=4, num='5.3.17.2'), + Heading(name='RQ.SRS-006.RBAC.User.ShowCreateUser.Syntax', level=4, num='5.3.17.3'), + Heading(name='Drop User', level=3, num='5.3.18'), + Heading(name='RQ.SRS-006.RBAC.User.Drop', level=4, num='5.3.18.1'), + Heading(name='RQ.SRS-006.RBAC.User.Drop.IfExists', level=4, num='5.3.18.2'), + Heading(name='RQ.SRS-006.RBAC.User.Drop.OnCluster', level=4, num='5.3.18.3'), + Heading(name='RQ.SRS-006.RBAC.User.Drop.Syntax', level=4, num='5.3.18.4'), + Heading(name='Role', level=2, num='5.4'), + Heading(name='RQ.SRS-006.RBAC.Role', level=3, num='5.4.1'), + Heading(name='RQ.SRS-006.RBAC.Role.Privileges', level=3, num='5.4.2'), + Heading(name='RQ.SRS-006.RBAC.Role.Variables', level=3, num='5.4.3'), + Heading(name='RQ.SRS-006.RBAC.Role.SettingsProfile', level=3, num='5.4.4'), + Heading(name='RQ.SRS-006.RBAC.Role.Quotas', level=3, num='5.4.5'), + Heading(name='RQ.SRS-006.RBAC.Role.RowPolicies', level=3, num='5.4.6'), + Heading(name='Create Role', level=3, num='5.4.7'), + Heading(name='RQ.SRS-006.RBAC.Role.Create', level=4, num='5.4.7.1'), + Heading(name='RQ.SRS-006.RBAC.Role.Create.IfNotExists', level=4, num='5.4.7.2'), + Heading(name='RQ.SRS-006.RBAC.Role.Create.Replace', level=4, num='5.4.7.3'), + Heading(name='RQ.SRS-006.RBAC.Role.Create.Settings', level=4, num='5.4.7.4'), + Heading(name='RQ.SRS-006.RBAC.Role.Create.Syntax', level=4, num='5.4.7.5'), + Heading(name='Alter Role', level=3, num='5.4.8'), + Heading(name='RQ.SRS-006.RBAC.Role.Alter', level=4, num='5.4.8.1'), + Heading(name='RQ.SRS-006.RBAC.Role.Alter.IfExists', level=4, num='5.4.8.2'), + Heading(name='RQ.SRS-006.RBAC.Role.Alter.Cluster', level=4, num='5.4.8.3'), + Heading(name='RQ.SRS-006.RBAC.Role.Alter.Rename', level=4, num='5.4.8.4'), + Heading(name='RQ.SRS-006.RBAC.Role.Alter.Settings', level=4, num='5.4.8.5'), + Heading(name='RQ.SRS-006.RBAC.Role.Alter.Syntax', level=4, num='5.4.8.6'), + Heading(name='Drop Role', level=3, num='5.4.9'), + Heading(name='RQ.SRS-006.RBAC.Role.Drop', level=4, num='5.4.9.1'), + Heading(name='RQ.SRS-006.RBAC.Role.Drop.IfExists', level=4, num='5.4.9.2'), + Heading(name='RQ.SRS-006.RBAC.Role.Drop.Cluster', level=4, num='5.4.9.3'), + Heading(name='RQ.SRS-006.RBAC.Role.Drop.Syntax', level=4, num='5.4.9.4'), + Heading(name='Show Create Role', level=3, num='5.4.10'), + Heading(name='RQ.SRS-006.RBAC.Role.ShowCreate', level=4, num='5.4.10.1'), + Heading(name='RQ.SRS-006.RBAC.Role.ShowCreate.Syntax', level=4, num='5.4.10.2'), + Heading(name='Partial Revokes', level=2, num='5.5'), + Heading(name='RQ.SRS-006.RBAC.PartialRevokes', level=3, num='5.5.1'), + Heading(name='RQ.SRS-006.RBAC.PartialRevoke.Syntax', level=3, num='5.5.2'), + Heading(name='Settings Profile', level=2, num='5.6'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile', level=3, num='5.6.1'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Constraints', level=3, num='5.6.2'), + Heading(name='Create Settings Profile', level=3, num='5.6.3'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create', level=4, num='5.6.3.1'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.IfNotExists', level=4, num='5.6.3.2'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.Replace', level=4, num='5.6.3.3'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.Variables', level=4, num='5.6.3.4'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Value', level=4, num='5.6.3.5'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Constraints', level=4, num='5.6.3.6'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment', level=4, num='5.6.3.7'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.None', level=4, num='5.6.3.8'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.All', level=4, num='5.6.3.9'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.AllExcept', level=4, num='5.6.3.10'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.Inherit', level=4, num='5.6.3.11'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.OnCluster', level=4, num='5.6.3.12'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Create.Syntax', level=4, num='5.6.3.13'), + Heading(name='Alter Settings Profile', level=3, num='5.6.4'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter', level=4, num='5.6.4.1'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.IfExists', level=4, num='5.6.4.2'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Rename', level=4, num='5.6.4.3'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables', level=4, num='5.6.4.4'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Value', level=4, num='5.6.4.5'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Constraints', level=4, num='5.6.4.6'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment', level=4, num='5.6.4.7'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.None', level=4, num='5.6.4.8'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.All', level=4, num='5.6.4.9'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.AllExcept', level=4, num='5.6.4.10'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.Inherit', level=4, num='5.6.4.11'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.OnCluster', level=4, num='5.6.4.12'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Syntax', level=4, num='5.6.4.13'), + Heading(name='Drop Settings Profile', level=3, num='5.6.5'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Drop', level=4, num='5.6.5.1'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Drop.IfExists', level=4, num='5.6.5.2'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Drop.OnCluster', level=4, num='5.6.5.3'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.Drop.Syntax', level=4, num='5.6.5.4'), + Heading(name='Show Create Settings Profile', level=3, num='5.6.6'), + Heading(name='RQ.SRS-006.RBAC.SettingsProfile.ShowCreateSettingsProfile', level=4, num='5.6.6.1'), + Heading(name='Quotas', level=2, num='5.7'), + Heading(name='RQ.SRS-006.RBAC.Quotas', level=3, num='5.7.1'), + Heading(name='RQ.SRS-006.RBAC.Quotas.Keyed', level=3, num='5.7.2'), + Heading(name='RQ.SRS-006.RBAC.Quotas.Queries', level=3, num='5.7.3'), + Heading(name='RQ.SRS-006.RBAC.Quotas.Errors', level=3, num='5.7.4'), + Heading(name='RQ.SRS-006.RBAC.Quotas.ResultRows', level=3, num='5.7.5'), + Heading(name='RQ.SRS-006.RBAC.Quotas.ReadRows', level=3, num='5.7.6'), + Heading(name='RQ.SRS-006.RBAC.Quotas.ResultBytes', level=3, num='5.7.7'), + Heading(name='RQ.SRS-006.RBAC.Quotas.ReadBytes', level=3, num='5.7.8'), + Heading(name='RQ.SRS-006.RBAC.Quotas.ExecutionTime', level=3, num='5.7.9'), + Heading(name='Create Quotas', level=3, num='5.7.10'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create', level=4, num='5.7.10.1'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.IfNotExists', level=4, num='5.7.10.2'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Replace', level=4, num='5.7.10.3'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Cluster', level=4, num='5.7.10.4'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Interval', level=4, num='5.7.10.5'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Interval.Randomized', level=4, num='5.7.10.6'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Queries', level=4, num='5.7.10.7'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Errors', level=4, num='5.7.10.8'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.ResultRows', level=4, num='5.7.10.9'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.ReadRows', level=4, num='5.7.10.10'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.ResultBytes', level=4, num='5.7.10.11'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.ReadBytes', level=4, num='5.7.10.12'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.ExecutionTime', level=4, num='5.7.10.13'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.NoLimits', level=4, num='5.7.10.14'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.TrackingOnly', level=4, num='5.7.10.15'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.KeyedBy', level=4, num='5.7.10.16'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.KeyedByOptions', level=4, num='5.7.10.17'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Assignment', level=4, num='5.7.10.18'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Assignment.None', level=4, num='5.7.10.19'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Assignment.All', level=4, num='5.7.10.20'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Assignment.Except', level=4, num='5.7.10.21'), + Heading(name='RQ.SRS-006.RBAC.Quota.Create.Syntax', level=4, num='5.7.10.22'), + Heading(name='Alter Quota', level=3, num='5.7.11'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter', level=4, num='5.7.11.1'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.IfExists', level=4, num='5.7.11.2'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Rename', level=4, num='5.7.11.3'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Cluster', level=4, num='5.7.11.4'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Interval', level=4, num='5.7.11.5'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Interval.Randomized', level=4, num='5.7.11.6'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Queries', level=4, num='5.7.11.7'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Errors', level=4, num='5.7.11.8'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.ResultRows', level=4, num='5.7.11.9'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.ReadRows', level=4, num='5.7.11.10'), + Heading(name='RQ.SRS-006.RBAC.Quota.ALter.ResultBytes', level=4, num='5.7.11.11'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.ReadBytes', level=4, num='5.7.11.12'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.ExecutionTime', level=4, num='5.7.11.13'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.NoLimits', level=4, num='5.7.11.14'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.TrackingOnly', level=4, num='5.7.11.15'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.KeyedBy', level=4, num='5.7.11.16'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.KeyedByOptions', level=4, num='5.7.11.17'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Assignment', level=4, num='5.7.11.18'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Assignment.None', level=4, num='5.7.11.19'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Assignment.All', level=4, num='5.7.11.20'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Assignment.Except', level=4, num='5.7.11.21'), + Heading(name='RQ.SRS-006.RBAC.Quota.Alter.Syntax', level=4, num='5.7.11.22'), + Heading(name='Drop Quota', level=3, num='5.7.12'), + Heading(name='RQ.SRS-006.RBAC.Quota.Drop', level=4, num='5.7.12.1'), + Heading(name='RQ.SRS-006.RBAC.Quota.Drop.IfExists', level=4, num='5.7.12.2'), + Heading(name='RQ.SRS-006.RBAC.Quota.Drop.Cluster', level=4, num='5.7.12.3'), + Heading(name='RQ.SRS-006.RBAC.Quota.Drop.Syntax', level=4, num='5.7.12.4'), + Heading(name='Show Quotas', level=3, num='5.7.13'), + Heading(name='RQ.SRS-006.RBAC.Quota.ShowQuotas', level=4, num='5.7.13.1'), + Heading(name='RQ.SRS-006.RBAC.Quota.ShowQuotas.IntoOutfile', level=4, num='5.7.13.2'), + Heading(name='RQ.SRS-006.RBAC.Quota.ShowQuotas.Format', level=4, num='5.7.13.3'), + Heading(name='RQ.SRS-006.RBAC.Quota.ShowQuotas.Settings', level=4, num='5.7.13.4'), + Heading(name='RQ.SRS-006.RBAC.Quota.ShowQuotas.Syntax', level=4, num='5.7.13.5'), + Heading(name='Show Create Quota', level=3, num='5.7.14'), + Heading(name='RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Name', level=4, num='5.7.14.1'), + Heading(name='RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Current', level=4, num='5.7.14.2'), + Heading(name='RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Syntax', level=4, num='5.7.14.3'), + Heading(name='Row Policy', level=2, num='5.8'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy', level=3, num='5.8.1'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Condition', level=3, num='5.8.2'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Restriction', level=3, num='5.8.3'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Nesting', level=3, num='5.8.4'), + Heading(name='Create Row Policy', level=3, num='5.8.5'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create', level=4, num='5.8.5.1'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.IfNotExists', level=4, num='5.8.5.2'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.Replace', level=4, num='5.8.5.3'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.OnCluster', level=4, num='5.8.5.4'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.On', level=4, num='5.8.5.5'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.Access', level=4, num='5.8.5.6'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.Access.Permissive', level=4, num='5.8.5.7'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.Access.Restrictive', level=4, num='5.8.5.8'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.ForSelect', level=4, num='5.8.5.9'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.Condition', level=4, num='5.8.5.10'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment', level=4, num='5.8.5.11'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.None', level=4, num='5.8.5.12'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.All', level=4, num='5.8.5.13'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.AllExcept', level=4, num='5.8.5.14'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Create.Syntax', level=4, num='5.8.5.15'), + Heading(name='Alter Row Policy', level=3, num='5.8.6'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter', level=4, num='5.8.6.1'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.IfExists', level=4, num='5.8.6.2'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.ForSelect', level=4, num='5.8.6.3'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.OnCluster', level=4, num='5.8.6.4'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.On', level=4, num='5.8.6.5'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Rename', level=4, num='5.8.6.6'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Access', level=4, num='5.8.6.7'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Permissive', level=4, num='5.8.6.8'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Restrictive', level=4, num='5.8.6.9'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Condition', level=4, num='5.8.6.10'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Condition.None', level=4, num='5.8.6.11'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment', level=4, num='5.8.6.12'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.None', level=4, num='5.8.6.13'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.All', level=4, num='5.8.6.14'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.AllExcept', level=4, num='5.8.6.15'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Alter.Syntax', level=4, num='5.8.6.16'), + Heading(name='Drop Row Policy', level=3, num='5.8.7'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Drop', level=4, num='5.8.7.1'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Drop.IfExists', level=4, num='5.8.7.2'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Drop.On', level=4, num='5.8.7.3'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Drop.OnCluster', level=4, num='5.8.7.4'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.Drop.Syntax', level=4, num='5.8.7.5'), + Heading(name='Show Create Row Policy', level=3, num='5.8.8'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy', level=4, num='5.8.8.1'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.On', level=4, num='5.8.8.2'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.Syntax', level=4, num='5.8.8.3'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies', level=4, num='5.8.8.4'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.On', level=4, num='5.8.8.5'), + Heading(name='RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.Syntax', level=4, num='5.8.8.6'), + Heading(name='Set Default Role', level=2, num='5.9'), + Heading(name='RQ.SRS-006.RBAC.SetDefaultRole', level=3, num='5.9.1'), + Heading(name='RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser', level=3, num='5.9.2'), + Heading(name='RQ.SRS-006.RBAC.SetDefaultRole.All', level=3, num='5.9.3'), + Heading(name='RQ.SRS-006.RBAC.SetDefaultRole.AllExcept', level=3, num='5.9.4'), + Heading(name='RQ.SRS-006.RBAC.SetDefaultRole.None', level=3, num='5.9.5'), + Heading(name='RQ.SRS-006.RBAC.SetDefaultRole.Syntax', level=3, num='5.9.6'), + Heading(name='Set Role', level=2, num='5.10'), + Heading(name='RQ.SRS-006.RBAC.SetRole', level=3, num='5.10.1'), + Heading(name='RQ.SRS-006.RBAC.SetRole.Default', level=3, num='5.10.2'), + Heading(name='RQ.SRS-006.RBAC.SetRole.None', level=3, num='5.10.3'), + Heading(name='RQ.SRS-006.RBAC.SetRole.All', level=3, num='5.10.4'), + Heading(name='RQ.SRS-006.RBAC.SetRole.AllExcept', level=3, num='5.10.5'), + Heading(name='RQ.SRS-006.RBAC.SetRole.Syntax', level=3, num='5.10.6'), + Heading(name='Grant', level=2, num='5.11'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.To', level=3, num='5.11.1'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser', level=3, num='5.11.2'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Select', level=3, num='5.11.3'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Insert', level=3, num='5.11.4'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Alter', level=3, num='5.11.5'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Create', level=3, num='5.11.6'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Drop', level=3, num='5.11.7'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Truncate', level=3, num='5.11.8'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Optimize', level=3, num='5.11.9'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Show', level=3, num='5.11.10'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.KillQuery', level=3, num='5.11.11'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement', level=3, num='5.11.12'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.System', level=3, num='5.11.13'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Introspection', level=3, num='5.11.14'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Sources', level=3, num='5.11.15'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.DictGet', level=3, num='5.11.16'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.None', level=3, num='5.11.17'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.All', level=3, num='5.11.18'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.GrantOption', level=3, num='5.11.19'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.On', level=3, num='5.11.20'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns', level=3, num='5.11.21'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.OnCluster', level=3, num='5.11.22'), + Heading(name='RQ.SRS-006.RBAC.Grant.Privilege.Syntax', level=3, num='5.11.23'), + Heading(name='Revoke', level=2, num='5.12'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Cluster', level=3, num='5.12.1'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Select', level=3, num='5.12.2'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Insert', level=3, num='5.12.3'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Alter', level=3, num='5.12.4'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Create', level=3, num='5.12.5'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Drop', level=3, num='5.12.6'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Truncate', level=3, num='5.12.7'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Optimize', level=3, num='5.12.8'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Show', level=3, num='5.12.9'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery', level=3, num='5.12.10'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement', level=3, num='5.12.11'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.System', level=3, num='5.12.12'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Introspection', level=3, num='5.12.13'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Sources', level=3, num='5.12.14'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.DictGet', level=3, num='5.12.15'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.PrivilegeColumns', level=3, num='5.12.16'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Multiple', level=3, num='5.12.17'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.All', level=3, num='5.12.18'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.None', level=3, num='5.12.19'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.On', level=3, num='5.12.20'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.From', level=3, num='5.12.21'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Privilege.Syntax', level=3, num='5.12.22'), + Heading(name='Grant Role', level=2, num='5.13'), + Heading(name='RQ.SRS-006.RBAC.Grant.Role', level=3, num='5.13.1'), + Heading(name='RQ.SRS-006.RBAC.Grant.Role.CurrentUser', level=3, num='5.13.2'), + Heading(name='RQ.SRS-006.RBAC.Grant.Role.AdminOption', level=3, num='5.13.3'), + Heading(name='RQ.SRS-006.RBAC.Grant.Role.OnCluster', level=3, num='5.13.4'), + Heading(name='RQ.SRS-006.RBAC.Grant.Role.Syntax', level=3, num='5.13.5'), + Heading(name='Revoke Role', level=2, num='5.14'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Role', level=3, num='5.14.1'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Role.Keywords', level=3, num='5.14.2'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Role.Cluster', level=3, num='5.14.3'), + Heading(name='RQ.SRS-006.RBAC.Revoke.AdminOption', level=3, num='5.14.4'), + Heading(name='RQ.SRS-006.RBAC.Revoke.Role.Syntax', level=3, num='5.14.5'), + Heading(name='Show Grants', level=2, num='5.15'), + Heading(name='RQ.SRS-006.RBAC.Show.Grants', level=3, num='5.15.1'), + Heading(name='RQ.SRS-006.RBAC.Show.Grants.For', level=3, num='5.15.2'), + Heading(name='RQ.SRS-006.RBAC.Show.Grants.Syntax', level=3, num='5.15.3'), + Heading(name='Table Privileges', level=2, num='5.16'), + Heading(name='RQ.SRS-006.RBAC.Table.PublicTables', level=3, num='5.16.1'), + Heading(name='RQ.SRS-006.RBAC.Table.SensitiveTables', level=3, num='5.16.2'), + Heading(name='Distributed Tables', level=2, num='5.17'), + Heading(name='RQ.SRS-006.RBAC.DistributedTable.Create', level=3, num='5.17.1'), + Heading(name='RQ.SRS-006.RBAC.DistributedTable.Select', level=3, num='5.17.2'), + Heading(name='RQ.SRS-006.RBAC.DistributedTable.Insert', level=3, num='5.17.3'), + Heading(name='RQ.SRS-006.RBAC.DistributedTable.SpecialTables', level=3, num='5.17.4'), + Heading(name='RQ.SRS-006.RBAC.DistributedTable.LocalUser', level=3, num='5.17.5'), + Heading(name='RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges', level=3, num='5.17.6'), + Heading(name='Views', level=2, num='5.18'), + Heading(name='View', level=3, num='5.18.1'), + Heading(name='RQ.SRS-006.RBAC.View', level=4, num='5.18.1.1'), + Heading(name='RQ.SRS-006.RBAC.View.Create', level=4, num='5.18.1.2'), + Heading(name='RQ.SRS-006.RBAC.View.Select', level=4, num='5.18.1.3'), + Heading(name='RQ.SRS-006.RBAC.View.Drop', level=4, num='5.18.1.4'), + Heading(name='Materialized View', level=3, num='5.18.2'), + Heading(name='RQ.SRS-006.RBAC.MaterializedView', level=4, num='5.18.2.1'), + Heading(name='RQ.SRS-006.RBAC.MaterializedView.Create', level=4, num='5.18.2.2'), + Heading(name='RQ.SRS-006.RBAC.MaterializedView.Select', level=4, num='5.18.2.3'), + Heading(name='RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable', level=4, num='5.18.2.4'), + Heading(name='RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable', level=4, num='5.18.2.5'), + Heading(name='RQ.SRS-006.RBAC.MaterializedView.Drop', level=4, num='5.18.2.6'), + Heading(name='RQ.SRS-006.RBAC.MaterializedView.ModifyQuery', level=4, num='5.18.2.7'), + Heading(name='RQ.SRS-006.RBAC.MaterializedView.Insert', level=4, num='5.18.2.8'), + Heading(name='RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable', level=4, num='5.18.2.9'), + Heading(name='RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable', level=4, num='5.18.2.10'), + Heading(name='Live View', level=3, num='5.18.3'), + Heading(name='RQ.SRS-006.RBAC.LiveView', level=4, num='5.18.3.1'), + Heading(name='RQ.SRS-006.RBAC.LiveView.Create', level=4, num='5.18.3.2'), + Heading(name='RQ.SRS-006.RBAC.LiveView.Select', level=4, num='5.18.3.3'), + Heading(name='RQ.SRS-006.RBAC.LiveView.Drop', level=4, num='5.18.3.4'), + Heading(name='RQ.SRS-006.RBAC.LiveView.Refresh', level=4, num='5.18.3.5'), + Heading(name='Select', level=2, num='5.19'), + Heading(name='RQ.SRS-006.RBAC.Select', level=3, num='5.19.1'), + Heading(name='RQ.SRS-006.RBAC.Select.Column', level=3, num='5.19.2'), + Heading(name='RQ.SRS-006.RBAC.Select.Cluster', level=3, num='5.19.3'), + Heading(name='RQ.SRS-006.RBAC.Select.TableEngines', level=3, num='5.19.4'), + Heading(name='Insert', level=2, num='5.20'), + Heading(name='RQ.SRS-006.RBAC.Insert', level=3, num='5.20.1'), + Heading(name='RQ.SRS-006.RBAC.Insert.Column', level=3, num='5.20.2'), + Heading(name='RQ.SRS-006.RBAC.Insert.Cluster', level=3, num='5.20.3'), + Heading(name='RQ.SRS-006.RBAC.Insert.TableEngines', level=3, num='5.20.4'), + Heading(name='Alter', level=2, num='5.21'), + Heading(name='Alter Column', level=3, num='5.21.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterColumn', level=4, num='5.21.1.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant', level=4, num='5.21.1.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke', level=4, num='5.21.1.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Column', level=4, num='5.21.1.4'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster', level=4, num='5.21.1.5'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines', level=4, num='5.21.1.6'), + Heading(name='Alter Index', level=3, num='5.21.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterIndex', level=4, num='5.21.2.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant', level=4, num='5.21.2.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke', level=4, num='5.21.2.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster', level=4, num='5.21.2.4'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines', level=4, num='5.21.2.5'), + Heading(name='Alter Constraint', level=3, num='5.21.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterConstraint', level=4, num='5.21.3.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant', level=4, num='5.21.3.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke', level=4, num='5.21.3.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster', level=4, num='5.21.3.4'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines', level=4, num='5.21.3.5'), + Heading(name='Alter TTL', level=3, num='5.21.4'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterTTL', level=4, num='5.21.4.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant', level=4, num='5.21.4.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke', level=4, num='5.21.4.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster', level=4, num='5.21.4.4'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines', level=4, num='5.21.4.5'), + Heading(name='Alter Settings', level=3, num='5.21.5'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterSettings', level=4, num='5.21.5.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant', level=4, num='5.21.5.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke', level=4, num='5.21.5.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster', level=4, num='5.21.5.4'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines', level=4, num='5.21.5.5'), + Heading(name='Alter Update', level=3, num='5.21.6'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterUpdate', level=4, num='5.21.6.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant', level=4, num='5.21.6.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke', level=4, num='5.21.6.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines', level=4, num='5.21.6.4'), + Heading(name='Alter Delete', level=3, num='5.21.7'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterDelete', level=4, num='5.21.7.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant', level=4, num='5.21.7.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke', level=4, num='5.21.7.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines', level=4, num='5.21.7.4'), + Heading(name='Alter Freeze Partition', level=3, num='5.21.8'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterFreeze', level=4, num='5.21.8.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant', level=4, num='5.21.8.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke', level=4, num='5.21.8.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines', level=4, num='5.21.8.4'), + Heading(name='Alter Fetch Partition', level=3, num='5.21.9'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterFetch', level=4, num='5.21.9.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant', level=4, num='5.21.9.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke', level=4, num='5.21.9.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines', level=4, num='5.21.9.4'), + Heading(name='Alter Move Partition', level=3, num='5.21.10'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterMove', level=4, num='5.21.10.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterMove.Grant', level=4, num='5.21.10.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke', level=4, num='5.21.10.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines', level=4, num='5.21.10.4'), + Heading(name='Create', level=2, num='5.22'), + Heading(name='RQ.SRS-006.RBAC.Privileges.CreateTable', level=3, num='5.22.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.CreateDatabase', level=3, num='5.22.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.CreateDictionary', level=3, num='5.22.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.CreateTemporaryTable', level=3, num='5.22.4'), + Heading(name='Attach', level=2, num='5.23'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AttachDatabase', level=3, num='5.23.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AttachDictionary', level=3, num='5.23.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AttachTemporaryTable', level=3, num='5.23.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AttachTable', level=3, num='5.23.4'), + Heading(name='Drop', level=2, num='5.24'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DropTable', level=3, num='5.24.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DropDatabase', level=3, num='5.24.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DropDictionary', level=3, num='5.24.3'), + Heading(name='Detach', level=2, num='5.25'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DetachTable', level=3, num='5.25.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DetachView', level=3, num='5.25.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DetachDatabase', level=3, num='5.25.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DetachDictionary', level=3, num='5.25.4'), + Heading(name='Truncate', level=2, num='5.26'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Truncate', level=3, num='5.26.1'), + Heading(name='Optimize', level=2, num='5.27'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Optimize', level=3, num='5.27.1'), + Heading(name='Kill Query', level=2, num='5.28'), + Heading(name='RQ.SRS-006.RBAC.Privileges.KillQuery', level=3, num='5.28.1'), + Heading(name='Kill Mutation', level=2, num='5.29'), + Heading(name='RQ.SRS-006.RBAC.Privileges.KillMutation', level=3, num='5.29.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate', level=3, num='5.29.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete', level=3, num='5.29.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn', level=3, num='5.29.4'), + Heading(name='Show', level=2, num='5.30'), + Heading(name='RQ.SRS-006.RBAC.ShowTables.Privilege', level=3, num='5.30.1'), + Heading(name='RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege', level=3, num='5.30.2'), + Heading(name='RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege', level=3, num='5.30.3'), + Heading(name='RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege', level=3, num='5.30.4'), + Heading(name='RQ.SRS-006.RBAC.ShowDatabases.Privilege', level=3, num='5.30.5'), + Heading(name='RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege', level=3, num='5.30.6'), + Heading(name='RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege', level=3, num='5.30.7'), + Heading(name='RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege', level=3, num='5.30.8'), + Heading(name='RQ.SRS-006.RBAC.ShowColumns.Privilege', level=3, num='5.30.9'), + Heading(name='RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege', level=3, num='5.30.10'), + Heading(name='RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege', level=3, num='5.30.11'), + Heading(name='RQ.SRS-006.RBAC.ShowDictionaries.Privilege', level=3, num='5.30.12'), + Heading(name='RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege', level=3, num='5.30.13'), + Heading(name='RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege', level=3, num='5.30.14'), + Heading(name='RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege', level=3, num='5.30.15'), + Heading(name='Access Management', level=2, num='5.31'), + Heading(name='RQ.SRS-006.RBAC.Privileges.CreateUser', level=3, num='5.31.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole', level=3, num='5.31.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterUser', level=3, num='5.31.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DropUser', level=3, num='5.31.4'), + Heading(name='RQ.SRS-006.RBAC.Privileges.CreateRole', level=3, num='5.31.5'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterRole', level=3, num='5.31.6'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DropRole', level=3, num='5.31.7'), + Heading(name='RQ.SRS-006.RBAC.Privileges.CreateRowPolicy', level=3, num='5.31.8'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterRowPolicy', level=3, num='5.31.9'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DropRowPolicy', level=3, num='5.31.10'), + Heading(name='RQ.SRS-006.RBAC.Privileges.CreateQuota', level=3, num='5.31.11'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterQuota', level=3, num='5.31.12'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DropQuota', level=3, num='5.31.13'), + Heading(name='RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile', level=3, num='5.31.14'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile', level=3, num='5.31.15'), + Heading(name='RQ.SRS-006.RBAC.Privileges.DropSettingsProfile', level=3, num='5.31.16'), + Heading(name='RQ.SRS-006.RBAC.Privileges.RoleAdmin', level=3, num='5.31.17'), + Heading(name='Show Access', level=3, num='5.31.18'), + Heading(name='RQ.SRS-006.RBAC.ShowUsers.Privilege', level=4, num='5.31.18.1'), + Heading(name='RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege', level=4, num='5.31.18.2'), + Heading(name='RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege', level=4, num='5.31.18.3'), + Heading(name='RQ.SRS-006.RBAC.ShowRoles.Privilege', level=4, num='5.31.18.4'), + Heading(name='RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege', level=4, num='5.31.18.5'), + Heading(name='RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege', level=4, num='5.31.18.6'), + Heading(name='RQ.SRS-006.RBAC.ShowRowPolicies.Privilege', level=4, num='5.31.18.7'), + Heading(name='RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege', level=4, num='5.31.18.8'), + Heading(name='RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege', level=4, num='5.31.18.9'), + Heading(name='RQ.SRS-006.RBAC.ShowQuotas.Privilege', level=4, num='5.31.18.10'), + Heading(name='RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege', level=4, num='5.31.18.11'), + Heading(name='RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege', level=4, num='5.31.18.12'), + Heading(name='RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege', level=4, num='5.31.18.13'), + Heading(name='RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege', level=4, num='5.31.18.14'), + Heading(name='RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege', level=4, num='5.31.18.15'), + Heading(name='dictGet', level=2, num='5.32'), + Heading(name='RQ.SRS-006.RBAC.dictGet.Privilege', level=3, num='5.32.1'), + Heading(name='RQ.SRS-006.RBAC.dictGet.RequiredPrivilege', level=3, num='5.32.2'), + Heading(name='RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege', level=3, num='5.32.3'), + Heading(name='RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege', level=3, num='5.32.4'), + Heading(name='RQ.SRS-006.RBAC.dictHas.RequiredPrivilege', level=3, num='5.32.5'), + Heading(name='RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege', level=3, num='5.32.6'), + Heading(name='RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege', level=3, num='5.32.7'), + Heading(name='Introspection', level=2, num='5.33'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Introspection', level=3, num='5.33.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine', level=3, num='5.33.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol', level=3, num='5.33.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Introspection.demangle', level=3, num='5.33.4'), + Heading(name='System', level=2, num='5.34'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Shutdown', level=3, num='5.34.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.DropCache', level=3, num='5.34.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS', level=3, num='5.34.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark', level=3, num='5.34.4'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed', level=3, num='5.34.5'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Reload', level=3, num='5.34.6'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Reload.Config', level=3, num='5.34.7'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary', level=3, num='5.34.8'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries', level=3, num='5.34.9'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries', level=3, num='5.34.10'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Merges', level=3, num='5.34.11'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.TTLMerges', level=3, num='5.34.12'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Fetches', level=3, num='5.34.13'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Moves', level=3, num='5.34.14'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Sends', level=3, num='5.34.15'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed', level=3, num='5.34.16'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated', level=3, num='5.34.17'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues', level=3, num='5.34.18'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.SyncReplica', level=3, num='5.34.19'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.RestartReplica', level=3, num='5.34.20'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Flush', level=3, num='5.34.21'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed', level=3, num='5.34.22'), + Heading(name='RQ.SRS-006.RBAC.Privileges.System.Flush.Logs', level=3, num='5.34.23'), + Heading(name='Sources', level=2, num='5.35'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Sources', level=3, num='5.35.1'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Sources.File', level=3, num='5.35.2'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Sources.URL', level=3, num='5.35.3'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Sources.Remote', level=3, num='5.35.4'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Sources.MySQL', level=3, num='5.35.5'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Sources.ODBC', level=3, num='5.35.6'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Sources.JDBC', level=3, num='5.35.7'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Sources.HDFS', level=3, num='5.35.8'), + Heading(name='RQ.SRS-006.RBAC.Privileges.Sources.S3', level=3, num='5.35.9'), + Heading(name='RQ.SRS-006.RBAC.Privileges.GrantOption', level=2, num='5.36'), + Heading(name='RQ.SRS-006.RBAC.Privileges.All', level=2, num='5.37'), + Heading(name='RQ.SRS-006.RBAC.Privileges.RoleAll', level=2, num='5.38'), + Heading(name='RQ.SRS-006.RBAC.Privileges.None', level=2, num='5.39'), + Heading(name='RQ.SRS-006.RBAC.Privileges.AdminOption', level=2, num='5.40'), + Heading(name='References', level=1, num='6'), + ), + requirements=( + RQ_SRS_006_RBAC, + RQ_SRS_006_RBAC_Login, + RQ_SRS_006_RBAC_Login_DefaultUser, + RQ_SRS_006_RBAC_User, + RQ_SRS_006_RBAC_User_Roles, + RQ_SRS_006_RBAC_User_Privileges, + RQ_SRS_006_RBAC_User_Variables, + RQ_SRS_006_RBAC_User_Variables_Constraints, + RQ_SRS_006_RBAC_User_SettingsProfile, + RQ_SRS_006_RBAC_User_Quotas, + RQ_SRS_006_RBAC_User_RowPolicies, + RQ_SRS_006_RBAC_User_DefaultRole, + RQ_SRS_006_RBAC_User_RoleSelection, + RQ_SRS_006_RBAC_User_ShowCreate, + RQ_SRS_006_RBAC_User_ShowPrivileges, + RQ_SRS_006_RBAC_User_Use_DefaultRole, + RQ_SRS_006_RBAC_User_Use_AllRolesWhenNoDefaultRole, + RQ_SRS_006_RBAC_User_Create, + RQ_SRS_006_RBAC_User_Create_IfNotExists, + RQ_SRS_006_RBAC_User_Create_Replace, + RQ_SRS_006_RBAC_User_Create_Password_NoPassword, + RQ_SRS_006_RBAC_User_Create_Password_NoPassword_Login, + RQ_SRS_006_RBAC_User_Create_Password_PlainText, + RQ_SRS_006_RBAC_User_Create_Password_PlainText_Login, + RQ_SRS_006_RBAC_User_Create_Password_Sha256Password, + RQ_SRS_006_RBAC_User_Create_Password_Sha256Password_Login, + RQ_SRS_006_RBAC_User_Create_Password_Sha256Hash, + RQ_SRS_006_RBAC_User_Create_Password_Sha256Hash_Login, + RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Password, + RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Password_Login, + RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Hash, + RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Hash_Login, + RQ_SRS_006_RBAC_User_Create_Host_Name, + RQ_SRS_006_RBAC_User_Create_Host_Regexp, + RQ_SRS_006_RBAC_User_Create_Host_IP, + RQ_SRS_006_RBAC_User_Create_Host_Any, + RQ_SRS_006_RBAC_User_Create_Host_None, + RQ_SRS_006_RBAC_User_Create_Host_Local, + RQ_SRS_006_RBAC_User_Create_Host_Like, + RQ_SRS_006_RBAC_User_Create_Host_Default, + RQ_SRS_006_RBAC_User_Create_DefaultRole, + RQ_SRS_006_RBAC_User_Create_DefaultRole_None, + RQ_SRS_006_RBAC_User_Create_DefaultRole_All, + RQ_SRS_006_RBAC_User_Create_Settings, + RQ_SRS_006_RBAC_User_Create_OnCluster, + RQ_SRS_006_RBAC_User_Create_Syntax, + RQ_SRS_006_RBAC_User_Alter, + RQ_SRS_006_RBAC_User_Alter_OrderOfEvaluation, + RQ_SRS_006_RBAC_User_Alter_IfExists, + RQ_SRS_006_RBAC_User_Alter_Cluster, + RQ_SRS_006_RBAC_User_Alter_Rename, + RQ_SRS_006_RBAC_User_Alter_Password_PlainText, + RQ_SRS_006_RBAC_User_Alter_Password_Sha256Password, + RQ_SRS_006_RBAC_User_Alter_Password_DoubleSha1Password, + RQ_SRS_006_RBAC_User_Alter_Host_AddDrop, + RQ_SRS_006_RBAC_User_Alter_Host_Local, + RQ_SRS_006_RBAC_User_Alter_Host_Name, + RQ_SRS_006_RBAC_User_Alter_Host_Regexp, + RQ_SRS_006_RBAC_User_Alter_Host_IP, + RQ_SRS_006_RBAC_User_Alter_Host_Like, + RQ_SRS_006_RBAC_User_Alter_Host_Any, + RQ_SRS_006_RBAC_User_Alter_Host_None, + RQ_SRS_006_RBAC_User_Alter_DefaultRole, + RQ_SRS_006_RBAC_User_Alter_DefaultRole_All, + RQ_SRS_006_RBAC_User_Alter_DefaultRole_AllExcept, + RQ_SRS_006_RBAC_User_Alter_Settings, + RQ_SRS_006_RBAC_User_Alter_Settings_Min, + RQ_SRS_006_RBAC_User_Alter_Settings_Max, + RQ_SRS_006_RBAC_User_Alter_Settings_Profile, + RQ_SRS_006_RBAC_User_Alter_Syntax, + RQ_SRS_006_RBAC_User_ShowCreateUser, + RQ_SRS_006_RBAC_User_ShowCreateUser_For, + RQ_SRS_006_RBAC_User_ShowCreateUser_Syntax, + RQ_SRS_006_RBAC_User_Drop, + RQ_SRS_006_RBAC_User_Drop_IfExists, + RQ_SRS_006_RBAC_User_Drop_OnCluster, + RQ_SRS_006_RBAC_User_Drop_Syntax, + RQ_SRS_006_RBAC_Role, + RQ_SRS_006_RBAC_Role_Privileges, + RQ_SRS_006_RBAC_Role_Variables, + RQ_SRS_006_RBAC_Role_SettingsProfile, + RQ_SRS_006_RBAC_Role_Quotas, + RQ_SRS_006_RBAC_Role_RowPolicies, + RQ_SRS_006_RBAC_Role_Create, + RQ_SRS_006_RBAC_Role_Create_IfNotExists, + RQ_SRS_006_RBAC_Role_Create_Replace, + RQ_SRS_006_RBAC_Role_Create_Settings, + RQ_SRS_006_RBAC_Role_Create_Syntax, + RQ_SRS_006_RBAC_Role_Alter, + RQ_SRS_006_RBAC_Role_Alter_IfExists, + RQ_SRS_006_RBAC_Role_Alter_Cluster, + RQ_SRS_006_RBAC_Role_Alter_Rename, + RQ_SRS_006_RBAC_Role_Alter_Settings, + RQ_SRS_006_RBAC_Role_Alter_Syntax, + RQ_SRS_006_RBAC_Role_Drop, + RQ_SRS_006_RBAC_Role_Drop_IfExists, + RQ_SRS_006_RBAC_Role_Drop_Cluster, + RQ_SRS_006_RBAC_Role_Drop_Syntax, + RQ_SRS_006_RBAC_Role_ShowCreate, + RQ_SRS_006_RBAC_Role_ShowCreate_Syntax, + RQ_SRS_006_RBAC_PartialRevokes, + RQ_SRS_006_RBAC_PartialRevoke_Syntax, + RQ_SRS_006_RBAC_SettingsProfile, + RQ_SRS_006_RBAC_SettingsProfile_Constraints, + RQ_SRS_006_RBAC_SettingsProfile_Create, + RQ_SRS_006_RBAC_SettingsProfile_Create_IfNotExists, + RQ_SRS_006_RBAC_SettingsProfile_Create_Replace, + RQ_SRS_006_RBAC_SettingsProfile_Create_Variables, + RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Value, + RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints, + RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment, + RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_None, + RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_All, + RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_AllExcept, + RQ_SRS_006_RBAC_SettingsProfile_Create_Inherit, + RQ_SRS_006_RBAC_SettingsProfile_Create_OnCluster, + RQ_SRS_006_RBAC_SettingsProfile_Create_Syntax, + RQ_SRS_006_RBAC_SettingsProfile_Alter, + RQ_SRS_006_RBAC_SettingsProfile_Alter_IfExists, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Rename, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_None, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_All, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_AllExcept, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_Inherit, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_OnCluster, + RQ_SRS_006_RBAC_SettingsProfile_Alter_Syntax, + RQ_SRS_006_RBAC_SettingsProfile_Drop, + RQ_SRS_006_RBAC_SettingsProfile_Drop_IfExists, + RQ_SRS_006_RBAC_SettingsProfile_Drop_OnCluster, + RQ_SRS_006_RBAC_SettingsProfile_Drop_Syntax, + RQ_SRS_006_RBAC_SettingsProfile_ShowCreateSettingsProfile, + RQ_SRS_006_RBAC_Quotas, + RQ_SRS_006_RBAC_Quotas_Keyed, + RQ_SRS_006_RBAC_Quotas_Queries, + RQ_SRS_006_RBAC_Quotas_Errors, + RQ_SRS_006_RBAC_Quotas_ResultRows, + RQ_SRS_006_RBAC_Quotas_ReadRows, + RQ_SRS_006_RBAC_Quotas_ResultBytes, + RQ_SRS_006_RBAC_Quotas_ReadBytes, + RQ_SRS_006_RBAC_Quotas_ExecutionTime, + RQ_SRS_006_RBAC_Quota_Create, + RQ_SRS_006_RBAC_Quota_Create_IfNotExists, + RQ_SRS_006_RBAC_Quota_Create_Replace, + RQ_SRS_006_RBAC_Quota_Create_Cluster, + RQ_SRS_006_RBAC_Quota_Create_Interval, + RQ_SRS_006_RBAC_Quota_Create_Interval_Randomized, + RQ_SRS_006_RBAC_Quota_Create_Queries, + RQ_SRS_006_RBAC_Quota_Create_Errors, + RQ_SRS_006_RBAC_Quota_Create_ResultRows, + RQ_SRS_006_RBAC_Quota_Create_ReadRows, + RQ_SRS_006_RBAC_Quota_Create_ResultBytes, + RQ_SRS_006_RBAC_Quota_Create_ReadBytes, + RQ_SRS_006_RBAC_Quota_Create_ExecutionTime, + RQ_SRS_006_RBAC_Quota_Create_NoLimits, + RQ_SRS_006_RBAC_Quota_Create_TrackingOnly, + RQ_SRS_006_RBAC_Quota_Create_KeyedBy, + RQ_SRS_006_RBAC_Quota_Create_KeyedByOptions, + RQ_SRS_006_RBAC_Quota_Create_Assignment, + RQ_SRS_006_RBAC_Quota_Create_Assignment_None, + RQ_SRS_006_RBAC_Quota_Create_Assignment_All, + RQ_SRS_006_RBAC_Quota_Create_Assignment_Except, + RQ_SRS_006_RBAC_Quota_Create_Syntax, + RQ_SRS_006_RBAC_Quota_Alter, + RQ_SRS_006_RBAC_Quota_Alter_IfExists, + RQ_SRS_006_RBAC_Quota_Alter_Rename, + RQ_SRS_006_RBAC_Quota_Alter_Cluster, + RQ_SRS_006_RBAC_Quota_Alter_Interval, + RQ_SRS_006_RBAC_Quota_Alter_Interval_Randomized, + RQ_SRS_006_RBAC_Quota_Alter_Queries, + RQ_SRS_006_RBAC_Quota_Alter_Errors, + RQ_SRS_006_RBAC_Quota_Alter_ResultRows, + RQ_SRS_006_RBAC_Quota_Alter_ReadRows, + RQ_SRS_006_RBAC_Quota_ALter_ResultBytes, + RQ_SRS_006_RBAC_Quota_Alter_ReadBytes, + RQ_SRS_006_RBAC_Quota_Alter_ExecutionTime, + RQ_SRS_006_RBAC_Quota_Alter_NoLimits, + RQ_SRS_006_RBAC_Quota_Alter_TrackingOnly, + RQ_SRS_006_RBAC_Quota_Alter_KeyedBy, + RQ_SRS_006_RBAC_Quota_Alter_KeyedByOptions, + RQ_SRS_006_RBAC_Quota_Alter_Assignment, + RQ_SRS_006_RBAC_Quota_Alter_Assignment_None, + RQ_SRS_006_RBAC_Quota_Alter_Assignment_All, + RQ_SRS_006_RBAC_Quota_Alter_Assignment_Except, + RQ_SRS_006_RBAC_Quota_Alter_Syntax, + RQ_SRS_006_RBAC_Quota_Drop, + RQ_SRS_006_RBAC_Quota_Drop_IfExists, + RQ_SRS_006_RBAC_Quota_Drop_Cluster, + RQ_SRS_006_RBAC_Quota_Drop_Syntax, + RQ_SRS_006_RBAC_Quota_ShowQuotas, + RQ_SRS_006_RBAC_Quota_ShowQuotas_IntoOutfile, + RQ_SRS_006_RBAC_Quota_ShowQuotas_Format, + RQ_SRS_006_RBAC_Quota_ShowQuotas_Settings, + RQ_SRS_006_RBAC_Quota_ShowQuotas_Syntax, + RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Name, + RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Current, + RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Syntax, + RQ_SRS_006_RBAC_RowPolicy, + RQ_SRS_006_RBAC_RowPolicy_Condition, + RQ_SRS_006_RBAC_RowPolicy_Restriction, + RQ_SRS_006_RBAC_RowPolicy_Nesting, + RQ_SRS_006_RBAC_RowPolicy_Create, + RQ_SRS_006_RBAC_RowPolicy_Create_IfNotExists, + RQ_SRS_006_RBAC_RowPolicy_Create_Replace, + RQ_SRS_006_RBAC_RowPolicy_Create_OnCluster, + RQ_SRS_006_RBAC_RowPolicy_Create_On, + RQ_SRS_006_RBAC_RowPolicy_Create_Access, + RQ_SRS_006_RBAC_RowPolicy_Create_Access_Permissive, + RQ_SRS_006_RBAC_RowPolicy_Create_Access_Restrictive, + RQ_SRS_006_RBAC_RowPolicy_Create_ForSelect, + RQ_SRS_006_RBAC_RowPolicy_Create_Condition, + RQ_SRS_006_RBAC_RowPolicy_Create_Assignment, + RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_None, + RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_All, + RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_AllExcept, + RQ_SRS_006_RBAC_RowPolicy_Create_Syntax, + RQ_SRS_006_RBAC_RowPolicy_Alter, + RQ_SRS_006_RBAC_RowPolicy_Alter_IfExists, + RQ_SRS_006_RBAC_RowPolicy_Alter_ForSelect, + RQ_SRS_006_RBAC_RowPolicy_Alter_OnCluster, + RQ_SRS_006_RBAC_RowPolicy_Alter_On, + RQ_SRS_006_RBAC_RowPolicy_Alter_Rename, + RQ_SRS_006_RBAC_RowPolicy_Alter_Access, + RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Permissive, + RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Restrictive, + RQ_SRS_006_RBAC_RowPolicy_Alter_Condition, + RQ_SRS_006_RBAC_RowPolicy_Alter_Condition_None, + RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment, + RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_None, + RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_All, + RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_AllExcept, + RQ_SRS_006_RBAC_RowPolicy_Alter_Syntax, + RQ_SRS_006_RBAC_RowPolicy_Drop, + RQ_SRS_006_RBAC_RowPolicy_Drop_IfExists, + RQ_SRS_006_RBAC_RowPolicy_Drop_On, + RQ_SRS_006_RBAC_RowPolicy_Drop_OnCluster, + RQ_SRS_006_RBAC_RowPolicy_Drop_Syntax, + RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy, + RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy_On, + RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy_Syntax, + RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies, + RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_On, + RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_Syntax, + RQ_SRS_006_RBAC_SetDefaultRole, + RQ_SRS_006_RBAC_SetDefaultRole_CurrentUser, + RQ_SRS_006_RBAC_SetDefaultRole_All, + RQ_SRS_006_RBAC_SetDefaultRole_AllExcept, + RQ_SRS_006_RBAC_SetDefaultRole_None, + RQ_SRS_006_RBAC_SetDefaultRole_Syntax, + RQ_SRS_006_RBAC_SetRole, + RQ_SRS_006_RBAC_SetRole_Default, + RQ_SRS_006_RBAC_SetRole_None, + RQ_SRS_006_RBAC_SetRole_All, + RQ_SRS_006_RBAC_SetRole_AllExcept, + RQ_SRS_006_RBAC_SetRole_Syntax, + RQ_SRS_006_RBAC_Grant_Privilege_To, + RQ_SRS_006_RBAC_Grant_Privilege_ToCurrentUser, + RQ_SRS_006_RBAC_Grant_Privilege_Select, + RQ_SRS_006_RBAC_Grant_Privilege_Insert, + RQ_SRS_006_RBAC_Grant_Privilege_Alter, + RQ_SRS_006_RBAC_Grant_Privilege_Create, + RQ_SRS_006_RBAC_Grant_Privilege_Drop, + RQ_SRS_006_RBAC_Grant_Privilege_Truncate, + RQ_SRS_006_RBAC_Grant_Privilege_Optimize, + RQ_SRS_006_RBAC_Grant_Privilege_Show, + RQ_SRS_006_RBAC_Grant_Privilege_KillQuery, + RQ_SRS_006_RBAC_Grant_Privilege_AccessManagement, + RQ_SRS_006_RBAC_Grant_Privilege_System, + RQ_SRS_006_RBAC_Grant_Privilege_Introspection, + RQ_SRS_006_RBAC_Grant_Privilege_Sources, + RQ_SRS_006_RBAC_Grant_Privilege_DictGet, + RQ_SRS_006_RBAC_Grant_Privilege_None, + RQ_SRS_006_RBAC_Grant_Privilege_All, + RQ_SRS_006_RBAC_Grant_Privilege_GrantOption, + RQ_SRS_006_RBAC_Grant_Privilege_On, + RQ_SRS_006_RBAC_Grant_Privilege_PrivilegeColumns, + RQ_SRS_006_RBAC_Grant_Privilege_OnCluster, + RQ_SRS_006_RBAC_Grant_Privilege_Syntax, + RQ_SRS_006_RBAC_Revoke_Privilege_Cluster, + RQ_SRS_006_RBAC_Revoke_Privilege_Select, + RQ_SRS_006_RBAC_Revoke_Privilege_Insert, + RQ_SRS_006_RBAC_Revoke_Privilege_Alter, + RQ_SRS_006_RBAC_Revoke_Privilege_Create, + RQ_SRS_006_RBAC_Revoke_Privilege_Drop, + RQ_SRS_006_RBAC_Revoke_Privilege_Truncate, + RQ_SRS_006_RBAC_Revoke_Privilege_Optimize, + RQ_SRS_006_RBAC_Revoke_Privilege_Show, + RQ_SRS_006_RBAC_Revoke_Privilege_KillQuery, + RQ_SRS_006_RBAC_Revoke_Privilege_AccessManagement, + RQ_SRS_006_RBAC_Revoke_Privilege_System, + RQ_SRS_006_RBAC_Revoke_Privilege_Introspection, + RQ_SRS_006_RBAC_Revoke_Privilege_Sources, + RQ_SRS_006_RBAC_Revoke_Privilege_DictGet, + RQ_SRS_006_RBAC_Revoke_Privilege_PrivilegeColumns, + RQ_SRS_006_RBAC_Revoke_Privilege_Multiple, + RQ_SRS_006_RBAC_Revoke_Privilege_All, + RQ_SRS_006_RBAC_Revoke_Privilege_None, + RQ_SRS_006_RBAC_Revoke_Privilege_On, + RQ_SRS_006_RBAC_Revoke_Privilege_From, + RQ_SRS_006_RBAC_Revoke_Privilege_Syntax, + RQ_SRS_006_RBAC_Grant_Role, + RQ_SRS_006_RBAC_Grant_Role_CurrentUser, + RQ_SRS_006_RBAC_Grant_Role_AdminOption, + RQ_SRS_006_RBAC_Grant_Role_OnCluster, + RQ_SRS_006_RBAC_Grant_Role_Syntax, + RQ_SRS_006_RBAC_Revoke_Role, + RQ_SRS_006_RBAC_Revoke_Role_Keywords, + RQ_SRS_006_RBAC_Revoke_Role_Cluster, + RQ_SRS_006_RBAC_Revoke_AdminOption, + RQ_SRS_006_RBAC_Revoke_Role_Syntax, + RQ_SRS_006_RBAC_Show_Grants, + RQ_SRS_006_RBAC_Show_Grants_For, + RQ_SRS_006_RBAC_Show_Grants_Syntax, + RQ_SRS_006_RBAC_Table_PublicTables, + RQ_SRS_006_RBAC_Table_SensitiveTables, + RQ_SRS_006_RBAC_DistributedTable_Create, + RQ_SRS_006_RBAC_DistributedTable_Select, + RQ_SRS_006_RBAC_DistributedTable_Insert, + RQ_SRS_006_RBAC_DistributedTable_SpecialTables, + RQ_SRS_006_RBAC_DistributedTable_LocalUser, + RQ_SRS_006_RBAC_DistributedTable_SameUserDifferentNodesDifferentPrivileges, + RQ_SRS_006_RBAC_View, + RQ_SRS_006_RBAC_View_Create, + RQ_SRS_006_RBAC_View_Select, + RQ_SRS_006_RBAC_View_Drop, + RQ_SRS_006_RBAC_MaterializedView, + RQ_SRS_006_RBAC_MaterializedView_Create, + RQ_SRS_006_RBAC_MaterializedView_Select, + RQ_SRS_006_RBAC_MaterializedView_Select_TargetTable, + RQ_SRS_006_RBAC_MaterializedView_Select_SourceTable, + RQ_SRS_006_RBAC_MaterializedView_Drop, + RQ_SRS_006_RBAC_MaterializedView_ModifyQuery, + RQ_SRS_006_RBAC_MaterializedView_Insert, + RQ_SRS_006_RBAC_MaterializedView_Insert_SourceTable, + RQ_SRS_006_RBAC_MaterializedView_Insert_TargetTable, + RQ_SRS_006_RBAC_LiveView, + RQ_SRS_006_RBAC_LiveView_Create, + RQ_SRS_006_RBAC_LiveView_Select, + RQ_SRS_006_RBAC_LiveView_Drop, + RQ_SRS_006_RBAC_LiveView_Refresh, + RQ_SRS_006_RBAC_Select, + RQ_SRS_006_RBAC_Select_Column, + RQ_SRS_006_RBAC_Select_Cluster, + RQ_SRS_006_RBAC_Select_TableEngines, + RQ_SRS_006_RBAC_Insert, + RQ_SRS_006_RBAC_Insert_Column, + RQ_SRS_006_RBAC_Insert_Cluster, + RQ_SRS_006_RBAC_Insert_TableEngines, + RQ_SRS_006_RBAC_Privileges_AlterColumn, + RQ_SRS_006_RBAC_Privileges_AlterColumn_Grant, + RQ_SRS_006_RBAC_Privileges_AlterColumn_Revoke, + RQ_SRS_006_RBAC_Privileges_AlterColumn_Column, + RQ_SRS_006_RBAC_Privileges_AlterColumn_Cluster, + RQ_SRS_006_RBAC_Privileges_AlterColumn_TableEngines, + RQ_SRS_006_RBAC_Privileges_AlterIndex, + RQ_SRS_006_RBAC_Privileges_AlterIndex_Grant, + RQ_SRS_006_RBAC_Privileges_AlterIndex_Revoke, + RQ_SRS_006_RBAC_Privileges_AlterIndex_Cluster, + RQ_SRS_006_RBAC_Privileges_AlterIndex_TableEngines, + RQ_SRS_006_RBAC_Privileges_AlterConstraint, + RQ_SRS_006_RBAC_Privileges_AlterConstraint_Grant, + RQ_SRS_006_RBAC_Privileges_AlterConstraint_Revoke, + RQ_SRS_006_RBAC_Privileges_AlterConstraint_Cluster, + RQ_SRS_006_RBAC_Privileges_AlterConstraint_TableEngines, + RQ_SRS_006_RBAC_Privileges_AlterTTL, + RQ_SRS_006_RBAC_Privileges_AlterTTL_Grant, + RQ_SRS_006_RBAC_Privileges_AlterTTL_Revoke, + RQ_SRS_006_RBAC_Privileges_AlterTTL_Cluster, + RQ_SRS_006_RBAC_Privileges_AlterTTL_TableEngines, + RQ_SRS_006_RBAC_Privileges_AlterSettings, + RQ_SRS_006_RBAC_Privileges_AlterSettings_Grant, + RQ_SRS_006_RBAC_Privileges_AlterSettings_Revoke, + RQ_SRS_006_RBAC_Privileges_AlterSettings_Cluster, + RQ_SRS_006_RBAC_Privileges_AlterSettings_TableEngines, + RQ_SRS_006_RBAC_Privileges_AlterUpdate, + RQ_SRS_006_RBAC_Privileges_AlterUpdate_Grant, + RQ_SRS_006_RBAC_Privileges_AlterUpdate_Revoke, + RQ_SRS_006_RBAC_Privileges_AlterUpdate_TableEngines, + RQ_SRS_006_RBAC_Privileges_AlterDelete, + RQ_SRS_006_RBAC_Privileges_AlterDelete_Grant, + RQ_SRS_006_RBAC_Privileges_AlterDelete_Revoke, + RQ_SRS_006_RBAC_Privileges_AlterDelete_TableEngines, + RQ_SRS_006_RBAC_Privileges_AlterFreeze, + RQ_SRS_006_RBAC_Privileges_AlterFreeze_Grant, + RQ_SRS_006_RBAC_Privileges_AlterFreeze_Revoke, + RQ_SRS_006_RBAC_Privileges_AlterFreeze_TableEngines, + RQ_SRS_006_RBAC_Privileges_AlterFetch, + RQ_SRS_006_RBAC_Privileges_AlterFetch_Grant, + RQ_SRS_006_RBAC_Privileges_AlterFetch_Revoke, + RQ_SRS_006_RBAC_Privileges_AlterFetch_TableEngines, + RQ_SRS_006_RBAC_Privileges_AlterMove, + RQ_SRS_006_RBAC_Privileges_AlterMove_Grant, + RQ_SRS_006_RBAC_Privileges_AlterMove_Revoke, + RQ_SRS_006_RBAC_Privileges_AlterMove_TableEngines, + RQ_SRS_006_RBAC_Privileges_CreateTable, + RQ_SRS_006_RBAC_Privileges_CreateDatabase, + RQ_SRS_006_RBAC_Privileges_CreateDictionary, + RQ_SRS_006_RBAC_Privileges_CreateTemporaryTable, + RQ_SRS_006_RBAC_Privileges_AttachDatabase, + RQ_SRS_006_RBAC_Privileges_AttachDictionary, + RQ_SRS_006_RBAC_Privileges_AttachTemporaryTable, + RQ_SRS_006_RBAC_Privileges_AttachTable, + RQ_SRS_006_RBAC_Privileges_DropTable, + RQ_SRS_006_RBAC_Privileges_DropDatabase, + RQ_SRS_006_RBAC_Privileges_DropDictionary, + RQ_SRS_006_RBAC_Privileges_DetachTable, + RQ_SRS_006_RBAC_Privileges_DetachView, + RQ_SRS_006_RBAC_Privileges_DetachDatabase, + RQ_SRS_006_RBAC_Privileges_DetachDictionary, + RQ_SRS_006_RBAC_Privileges_Truncate, + RQ_SRS_006_RBAC_Privileges_Optimize, + RQ_SRS_006_RBAC_Privileges_KillQuery, + RQ_SRS_006_RBAC_Privileges_KillMutation, + RQ_SRS_006_RBAC_Privileges_KillMutation_AlterUpdate, + RQ_SRS_006_RBAC_Privileges_KillMutation_AlterDelete, + RQ_SRS_006_RBAC_Privileges_KillMutation_AlterDropColumn, + RQ_SRS_006_RBAC_ShowTables_Privilege, + RQ_SRS_006_RBAC_ShowTables_RequiredPrivilege, + RQ_SRS_006_RBAC_ExistsTable_RequiredPrivilege, + RQ_SRS_006_RBAC_CheckTable_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowDatabases_Privilege, + RQ_SRS_006_RBAC_ShowDatabases_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowCreateDatabase_RequiredPrivilege, + RQ_SRS_006_RBAC_UseDatabase_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowColumns_Privilege, + RQ_SRS_006_RBAC_ShowCreateTable_RequiredPrivilege, + RQ_SRS_006_RBAC_DescribeTable_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowDictionaries_Privilege, + RQ_SRS_006_RBAC_ShowDictionaries_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowCreateDictionary_RequiredPrivilege, + RQ_SRS_006_RBAC_ExistsDictionary_RequiredPrivilege, + RQ_SRS_006_RBAC_Privileges_CreateUser, + RQ_SRS_006_RBAC_Privileges_CreateUser_DefaultRole, + RQ_SRS_006_RBAC_Privileges_AlterUser, + RQ_SRS_006_RBAC_Privileges_DropUser, + RQ_SRS_006_RBAC_Privileges_CreateRole, + RQ_SRS_006_RBAC_Privileges_AlterRole, + RQ_SRS_006_RBAC_Privileges_DropRole, + RQ_SRS_006_RBAC_Privileges_CreateRowPolicy, + RQ_SRS_006_RBAC_Privileges_AlterRowPolicy, + RQ_SRS_006_RBAC_Privileges_DropRowPolicy, + RQ_SRS_006_RBAC_Privileges_CreateQuota, + RQ_SRS_006_RBAC_Privileges_AlterQuota, + RQ_SRS_006_RBAC_Privileges_DropQuota, + RQ_SRS_006_RBAC_Privileges_CreateSettingsProfile, + RQ_SRS_006_RBAC_Privileges_AlterSettingsProfile, + RQ_SRS_006_RBAC_Privileges_DropSettingsProfile, + RQ_SRS_006_RBAC_Privileges_RoleAdmin, + RQ_SRS_006_RBAC_ShowUsers_Privilege, + RQ_SRS_006_RBAC_ShowUsers_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowCreateUser_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowRoles_Privilege, + RQ_SRS_006_RBAC_ShowRoles_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowCreateRole_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowRowPolicies_Privilege, + RQ_SRS_006_RBAC_ShowRowPolicies_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowCreateRowPolicy_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowQuotas_Privilege, + RQ_SRS_006_RBAC_ShowQuotas_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowCreateQuota_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowSettingsProfiles_Privilege, + RQ_SRS_006_RBAC_ShowSettingsProfiles_RequiredPrivilege, + RQ_SRS_006_RBAC_ShowCreateSettingsProfile_RequiredPrivilege, + RQ_SRS_006_RBAC_dictGet_Privilege, + RQ_SRS_006_RBAC_dictGet_RequiredPrivilege, + RQ_SRS_006_RBAC_dictGet_Type_RequiredPrivilege, + RQ_SRS_006_RBAC_dictGet_OrDefault_RequiredPrivilege, + RQ_SRS_006_RBAC_dictHas_RequiredPrivilege, + RQ_SRS_006_RBAC_dictGetHierarchy_RequiredPrivilege, + RQ_SRS_006_RBAC_dictIsIn_RequiredPrivilege, + RQ_SRS_006_RBAC_Privileges_Introspection, + RQ_SRS_006_RBAC_Privileges_Introspection_addressToLine, + RQ_SRS_006_RBAC_Privileges_Introspection_addressToSymbol, + RQ_SRS_006_RBAC_Privileges_Introspection_demangle, + RQ_SRS_006_RBAC_Privileges_System_Shutdown, + RQ_SRS_006_RBAC_Privileges_System_DropCache, + RQ_SRS_006_RBAC_Privileges_System_DropCache_DNS, + RQ_SRS_006_RBAC_Privileges_System_DropCache_Mark, + RQ_SRS_006_RBAC_Privileges_System_DropCache_Uncompressed, + RQ_SRS_006_RBAC_Privileges_System_Reload, + RQ_SRS_006_RBAC_Privileges_System_Reload_Config, + RQ_SRS_006_RBAC_Privileges_System_Reload_Dictionary, + RQ_SRS_006_RBAC_Privileges_System_Reload_Dictionaries, + RQ_SRS_006_RBAC_Privileges_System_Reload_EmbeddedDictionaries, + RQ_SRS_006_RBAC_Privileges_System_Merges, + RQ_SRS_006_RBAC_Privileges_System_TTLMerges, + RQ_SRS_006_RBAC_Privileges_System_Fetches, + RQ_SRS_006_RBAC_Privileges_System_Moves, + RQ_SRS_006_RBAC_Privileges_System_Sends, + RQ_SRS_006_RBAC_Privileges_System_Sends_Distributed, + RQ_SRS_006_RBAC_Privileges_System_Sends_Replicated, + RQ_SRS_006_RBAC_Privileges_System_ReplicationQueues, + RQ_SRS_006_RBAC_Privileges_System_SyncReplica, + RQ_SRS_006_RBAC_Privileges_System_RestartReplica, + RQ_SRS_006_RBAC_Privileges_System_Flush, + RQ_SRS_006_RBAC_Privileges_System_Flush_Distributed, + RQ_SRS_006_RBAC_Privileges_System_Flush_Logs, + RQ_SRS_006_RBAC_Privileges_Sources, + RQ_SRS_006_RBAC_Privileges_Sources_File, + RQ_SRS_006_RBAC_Privileges_Sources_URL, + RQ_SRS_006_RBAC_Privileges_Sources_Remote, + RQ_SRS_006_RBAC_Privileges_Sources_MySQL, + RQ_SRS_006_RBAC_Privileges_Sources_ODBC, + RQ_SRS_006_RBAC_Privileges_Sources_JDBC, + RQ_SRS_006_RBAC_Privileges_Sources_HDFS, + RQ_SRS_006_RBAC_Privileges_Sources_S3, + RQ_SRS_006_RBAC_Privileges_GrantOption, + RQ_SRS_006_RBAC_Privileges_All, + RQ_SRS_006_RBAC_Privileges_RoleAll, + RQ_SRS_006_RBAC_Privileges_None, + RQ_SRS_006_RBAC_Privileges_AdminOption, + ), + content=''' # SRS-006 ClickHouse Role Based Access Control # Software Requirements Specification @@ -34,556 +9989,588 @@ SRS_006_ClickHouse_Role_Based_Access_Control = Specification( * 5 [Requirements](#requirements) * 5.1 [Generic](#generic) * 5.1.1 [RQ.SRS-006.RBAC](#rqsrs-006rbac) - * 5.1.2 [Login](#login) - * 5.1.2.1 [RQ.SRS-006.RBAC.Login](#rqsrs-006rbaclogin) - * 5.1.2.2 [RQ.SRS-006.RBAC.Login.DefaultUser](#rqsrs-006rbaclogindefaultuser) - * 5.1.3 [User](#user) - * 5.1.3.1 [RQ.SRS-006.RBAC.User](#rqsrs-006rbacuser) - * 5.1.3.2 [RQ.SRS-006.RBAC.User.Roles](#rqsrs-006rbacuserroles) - * 5.1.3.3 [RQ.SRS-006.RBAC.User.Privileges](#rqsrs-006rbacuserprivileges) - * 5.1.3.4 [RQ.SRS-006.RBAC.User.Variables](#rqsrs-006rbacuservariables) - * 5.1.3.5 [RQ.SRS-006.RBAC.User.Variables.Constraints](#rqsrs-006rbacuservariablesconstraints) - * 5.1.3.6 [RQ.SRS-006.RBAC.User.SettingsProfile](#rqsrs-006rbacusersettingsprofile) - * 5.1.3.7 [RQ.SRS-006.RBAC.User.Quotas](#rqsrs-006rbacuserquotas) - * 5.1.3.8 [RQ.SRS-006.RBAC.User.RowPolicies](#rqsrs-006rbacuserrowpolicies) - * 5.1.3.9 [RQ.SRS-006.RBAC.User.AccountLock](#rqsrs-006rbacuseraccountlock) - * 5.1.3.10 [RQ.SRS-006.RBAC.User.AccountLock.DenyAccess](#rqsrs-006rbacuseraccountlockdenyaccess) - * 5.1.3.11 [RQ.SRS-006.RBAC.User.DefaultRole](#rqsrs-006rbacuserdefaultrole) - * 5.1.3.12 [RQ.SRS-006.RBAC.User.RoleSelection](#rqsrs-006rbacuserroleselection) - * 5.1.3.13 [RQ.SRS-006.RBAC.User.ShowCreate](#rqsrs-006rbacusershowcreate) - * 5.1.3.14 [RQ.SRS-006.RBAC.User.ShowPrivileges](#rqsrs-006rbacusershowprivileges) - * 5.1.4 [Role](#role) - * 5.1.4.1 [RQ.SRS-006.RBAC.Role](#rqsrs-006rbacrole) - * 5.1.4.2 [RQ.SRS-006.RBAC.Role.Privileges](#rqsrs-006rbacroleprivileges) - * 5.1.4.3 [RQ.SRS-006.RBAC.Role.Variables](#rqsrs-006rbacrolevariables) - * 5.1.4.4 [RQ.SRS-006.RBAC.Role.SettingsProfile](#rqsrs-006rbacrolesettingsprofile) - * 5.1.4.5 [RQ.SRS-006.RBAC.Role.Quotas](#rqsrs-006rbacrolequotas) - * 5.1.4.6 [RQ.SRS-006.RBAC.Role.RowPolicies](#rqsrs-006rbacrolerowpolicies) - * 5.1.5 [Partial Revokes](#partial-revokes) - * 5.1.5.1 [RQ.SRS-006.RBAC.PartialRevokes](#rqsrs-006rbacpartialrevokes) - * 5.1.6 [Settings Profile](#settings-profile) - * 5.1.6.1 [RQ.SRS-006.RBAC.SettingsProfile](#rqsrs-006rbacsettingsprofile) - * 5.1.6.2 [RQ.SRS-006.RBAC.SettingsProfile.Constraints](#rqsrs-006rbacsettingsprofileconstraints) - * 5.1.6.3 [RQ.SRS-006.RBAC.SettingsProfile.ShowCreate](#rqsrs-006rbacsettingsprofileshowcreate) - * 5.1.7 [Quotas](#quotas) - * 5.1.7.1 [RQ.SRS-006.RBAC.Quotas](#rqsrs-006rbacquotas) - * 5.1.7.2 [RQ.SRS-006.RBAC.Quotas.Keyed](#rqsrs-006rbacquotaskeyed) - * 5.1.7.3 [RQ.SRS-006.RBAC.Quotas.Queries](#rqsrs-006rbacquotasqueries) - * 5.1.7.4 [RQ.SRS-006.RBAC.Quotas.Errors](#rqsrs-006rbacquotaserrors) - * 5.1.7.5 [RQ.SRS-006.RBAC.Quotas.ResultRows](#rqsrs-006rbacquotasresultrows) - * 5.1.7.6 [RQ.SRS-006.RBAC.Quotas.ReadRows](#rqsrs-006rbacquotasreadrows) - * 5.1.7.7 [RQ.SRS-006.RBAC.Quotas.ResultBytes](#rqsrs-006rbacquotasresultbytes) - * 5.1.7.8 [RQ.SRS-006.RBAC.Quotas.ReadBytes](#rqsrs-006rbacquotasreadbytes) - * 5.1.7.9 [RQ.SRS-006.RBAC.Quotas.ExecutionTime](#rqsrs-006rbacquotasexecutiontime) - * 5.1.7.10 [RQ.SRS-006.RBAC.Quotas.ShowCreate](#rqsrs-006rbacquotasshowcreate) - * 5.1.8 [Row Policy](#row-policy) - * 5.1.8.1 [RQ.SRS-006.RBAC.RowPolicy](#rqsrs-006rbacrowpolicy) - * 5.1.8.2 [RQ.SRS-006.RBAC.RowPolicy.Condition](#rqsrs-006rbacrowpolicycondition) - * 5.1.8.3 [RQ.SRS-006.RBAC.RowPolicy.ShowCreate](#rqsrs-006rbacrowpolicyshowcreate) - * 5.2 [Specific](#specific) - * 5.2.8.1 [RQ.SRS-006.RBAC.User.Use.DefaultRole](#rqsrs-006rbacuserusedefaultrole) - * 5.2.8.2 [RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole](#rqsrs-006rbacuseruseallroleswhennodefaultrole) - * 5.2.8.3 [RQ.SRS-006.RBAC.User.Create](#rqsrs-006rbacusercreate) - * 5.2.8.4 [RQ.SRS-006.RBAC.User.Create.IfNotExists](#rqsrs-006rbacusercreateifnotexists) - * 5.2.8.5 [RQ.SRS-006.RBAC.User.Create.Replace](#rqsrs-006rbacusercreatereplace) - * 5.2.8.6 [RQ.SRS-006.RBAC.User.Create.Password.NoPassword](#rqsrs-006rbacusercreatepasswordnopassword) - * 5.2.8.7 [RQ.SRS-006.RBAC.User.Create.Password.NoPassword.Login](#rqsrs-006rbacusercreatepasswordnopasswordlogin) - * 5.2.8.8 [RQ.SRS-006.RBAC.User.Create.Password.PlainText](#rqsrs-006rbacusercreatepasswordplaintext) - * 5.2.8.9 [RQ.SRS-006.RBAC.User.Create.Password.PlainText.Login](#rqsrs-006rbacusercreatepasswordplaintextlogin) - * 5.2.8.10 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Password](#rqsrs-006rbacusercreatepasswordsha256password) - * 5.2.8.11 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Password.Login](#rqsrs-006rbacusercreatepasswordsha256passwordlogin) - * 5.2.8.12 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash](#rqsrs-006rbacusercreatepasswordsha256hash) - * 5.2.8.13 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash.Login](#rqsrs-006rbacusercreatepasswordsha256hashlogin) - * 5.2.8.14 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password](#rqsrs-006rbacusercreatepassworddoublesha1password) - * 5.2.8.15 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password.Login](#rqsrs-006rbacusercreatepassworddoublesha1passwordlogin) - * 5.2.8.16 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash](#rqsrs-006rbacusercreatepassworddoublesha1hash) - * 5.2.8.17 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash.Login](#rqsrs-006rbacusercreatepassworddoublesha1hashlogin) - * 5.2.8.18 [RQ.SRS-006.RBAC.User.Create.Host.Name](#rqsrs-006rbacusercreatehostname) - * 5.2.8.19 [RQ.SRS-006.RBAC.User.Create.Host.Regexp](#rqsrs-006rbacusercreatehostregexp) - * 5.2.8.20 [RQ.SRS-006.RBAC.User.Create.Host.IP](#rqsrs-006rbacusercreatehostip) - * 5.2.8.21 [RQ.SRS-006.RBAC.User.Create.Host.Any](#rqsrs-006rbacusercreatehostany) - * 5.2.8.22 [RQ.SRS-006.RBAC.User.Create.Host.None](#rqsrs-006rbacusercreatehostnone) - * 5.2.8.23 [RQ.SRS-006.RBAC.User.Create.Host.Local](#rqsrs-006rbacusercreatehostlocal) - * 5.2.8.24 [RQ.SRS-006.RBAC.User.Create.Host.Like](#rqsrs-006rbacusercreatehostlike) - * 5.2.8.25 [RQ.SRS-006.RBAC.User.Create.Host.Default](#rqsrs-006rbacusercreatehostdefault) - * 5.2.8.26 [RQ.SRS-006.RBAC.User.Create.DefaultRole](#rqsrs-006rbacusercreatedefaultrole) - * 5.2.8.27 [RQ.SRS-006.RBAC.User.Create.DefaultRole.None](#rqsrs-006rbacusercreatedefaultrolenone) - * 5.2.8.28 [RQ.SRS-006.RBAC.User.Create.DefaultRole.All](#rqsrs-006rbacusercreatedefaultroleall) - * 5.2.8.29 [RQ.SRS-006.RBAC.User.Create.Settings](#rqsrs-006rbacusercreatesettings) - * 5.2.8.30 [RQ.SRS-006.RBAC.User.Create.OnCluster](#rqsrs-006rbacusercreateoncluster) - * 5.2.8.31 [RQ.SRS-006.RBAC.User.Create.Syntax](#rqsrs-006rbacusercreatesyntax) - * 5.2.8.32 [RQ.SRS-006.RBAC.User.Alter](#rqsrs-006rbacuseralter) - * 5.2.8.33 [RQ.SRS-006.RBAC.User.Alter.OrderOfEvaluation](#rqsrs-006rbacuseralterorderofevaluation) - * 5.2.8.34 [RQ.SRS-006.RBAC.User.Alter.IfExists](#rqsrs-006rbacuseralterifexists) - * 5.2.8.35 [RQ.SRS-006.RBAC.User.Alter.Cluster](#rqsrs-006rbacuseraltercluster) - * 5.2.8.36 [RQ.SRS-006.RBAC.User.Alter.Rename](#rqsrs-006rbacuseralterrename) - * 5.2.8.37 [RQ.SRS-006.RBAC.User.Alter.Password.PlainText](#rqsrs-006rbacuseralterpasswordplaintext) - * 5.2.8.38 [RQ.SRS-006.RBAC.User.Alter.Password.Sha256Password](#rqsrs-006rbacuseralterpasswordsha256password) - * 5.2.8.39 [RQ.SRS-006.RBAC.User.Alter.Password.DoubleSha1Password](#rqsrs-006rbacuseralterpassworddoublesha1password) - * 5.2.8.40 [RQ.SRS-006.RBAC.User.Alter.Host.AddDrop](#rqsrs-006rbacuseralterhostadddrop) - * 5.2.8.41 [RQ.SRS-006.RBAC.User.Alter.Host.Local](#rqsrs-006rbacuseralterhostlocal) - * 5.2.8.42 [RQ.SRS-006.RBAC.User.Alter.Host.Name](#rqsrs-006rbacuseralterhostname) - * 5.2.8.43 [RQ.SRS-006.RBAC.User.Alter.Host.Regexp](#rqsrs-006rbacuseralterhostregexp) - * 5.2.8.44 [RQ.SRS-006.RBAC.User.Alter.Host.IP](#rqsrs-006rbacuseralterhostip) - * 5.2.8.45 [RQ.SRS-006.RBAC.User.Alter.Host.Like](#rqsrs-006rbacuseralterhostlike) - * 5.2.8.46 [RQ.SRS-006.RBAC.User.Alter.Host.Any](#rqsrs-006rbacuseralterhostany) - * 5.2.8.47 [RQ.SRS-006.RBAC.User.Alter.Host.None](#rqsrs-006rbacuseralterhostnone) - * 5.2.8.48 [RQ.SRS-006.RBAC.User.Alter.DefaultRole](#rqsrs-006rbacuseralterdefaultrole) - * 5.2.8.49 [RQ.SRS-006.RBAC.User.Alter.DefaultRole.All](#rqsrs-006rbacuseralterdefaultroleall) - * 5.2.8.50 [RQ.SRS-006.RBAC.User.Alter.DefaultRole.AllExcept](#rqsrs-006rbacuseralterdefaultroleallexcept) - * 5.2.8.51 [RQ.SRS-006.RBAC.User.Alter.Settings](#rqsrs-006rbacuseraltersettings) - * 5.2.8.52 [RQ.SRS-006.RBAC.User.Alter.Settings.Min](#rqsrs-006rbacuseraltersettingsmin) - * 5.2.8.53 [RQ.SRS-006.RBAC.User.Alter.Settings.Max](#rqsrs-006rbacuseraltersettingsmax) - * 5.2.8.54 [RQ.SRS-006.RBAC.User.Alter.Settings.Profile](#rqsrs-006rbacuseraltersettingsprofile) - * 5.2.8.55 [RQ.SRS-006.RBAC.User.Alter.Syntax](#rqsrs-006rbacuseraltersyntax) - * 5.2.8.56 [RQ.SRS-006.RBAC.SetDefaultRole](#rqsrs-006rbacsetdefaultrole) - * 5.2.8.57 [RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser](#rqsrs-006rbacsetdefaultrolecurrentuser) - * 5.2.8.58 [RQ.SRS-006.RBAC.SetDefaultRole.All](#rqsrs-006rbacsetdefaultroleall) - * 5.2.8.59 [RQ.SRS-006.RBAC.SetDefaultRole.AllExcept](#rqsrs-006rbacsetdefaultroleallexcept) - * 5.2.8.60 [RQ.SRS-006.RBAC.SetDefaultRole.None](#rqsrs-006rbacsetdefaultrolenone) - * 5.2.8.61 [RQ.SRS-006.RBAC.SetDefaultRole.Syntax](#rqsrs-006rbacsetdefaultrolesyntax) - * 5.2.8.62 [RQ.SRS-006.RBAC.SetRole](#rqsrs-006rbacsetrole) - * 5.2.8.63 [RQ.SRS-006.RBAC.SetRole.Default](#rqsrs-006rbacsetroledefault) - * 5.2.8.64 [RQ.SRS-006.RBAC.SetRole.None](#rqsrs-006rbacsetrolenone) - * 5.2.8.65 [RQ.SRS-006.RBAC.SetRole.All](#rqsrs-006rbacsetroleall) - * 5.2.8.66 [RQ.SRS-006.RBAC.SetRole.AllExcept](#rqsrs-006rbacsetroleallexcept) - * 5.2.8.67 [RQ.SRS-006.RBAC.SetRole.Syntax](#rqsrs-006rbacsetrolesyntax) - * 5.2.8.68 [RQ.SRS-006.RBAC.User.ShowCreateUser](#rqsrs-006rbacusershowcreateuser) - * 5.2.8.69 [RQ.SRS-006.RBAC.User.ShowCreateUser.For](#rqsrs-006rbacusershowcreateuserfor) - * 5.2.8.70 [RQ.SRS-006.RBAC.User.ShowCreateUser.Syntax](#rqsrs-006rbacusershowcreateusersyntax) - * 5.2.8.71 [RQ.SRS-006.RBAC.User.Drop](#rqsrs-006rbacuserdrop) - * 5.2.8.72 [RQ.SRS-006.RBAC.User.Drop.IfExists](#rqsrs-006rbacuserdropifexists) - * 5.2.8.73 [RQ.SRS-006.RBAC.User.Drop.OnCluster](#rqsrs-006rbacuserdroponcluster) - * 5.2.8.74 [RQ.SRS-006.RBAC.User.Drop.Syntax](#rqsrs-006rbacuserdropsyntax) - * 5.2.8.75 [RQ.SRS-006.RBAC.Role.Create](#rqsrs-006rbacrolecreate) - * 5.2.8.76 [RQ.SRS-006.RBAC.Role.Create.IfNotExists](#rqsrs-006rbacrolecreateifnotexists) - * 5.2.8.77 [RQ.SRS-006.RBAC.Role.Create.Replace](#rqsrs-006rbacrolecreatereplace) - * 5.2.8.78 [RQ.SRS-006.RBAC.Role.Create.Settings](#rqsrs-006rbacrolecreatesettings) - * 5.2.8.79 [RQ.SRS-006.RBAC.Role.Create.Syntax](#rqsrs-006rbacrolecreatesyntax) - * 5.2.8.80 [RQ.SRS-006.RBAC.Role.Alter](#rqsrs-006rbacrolealter) - * 5.2.8.81 [RQ.SRS-006.RBAC.Role.Alter.IfExists](#rqsrs-006rbacrolealterifexists) - * 5.2.8.82 [RQ.SRS-006.RBAC.Role.Alter.Cluster](#rqsrs-006rbacrolealtercluster) - * 5.2.8.83 [RQ.SRS-006.RBAC.Role.Alter.Rename](#rqsrs-006rbacrolealterrename) - * 5.2.8.84 [RQ.SRS-006.RBAC.Role.Alter.Settings](#rqsrs-006rbacrolealtersettings) - * 5.2.8.85 [RQ.SRS-006.RBAC.Role.Alter.Syntax](#rqsrs-006rbacrolealtersyntax) - * 5.2.8.86 [RQ.SRS-006.RBAC.Role.Drop](#rqsrs-006rbacroledrop) - * 5.2.8.87 [RQ.SRS-006.RBAC.Role.Drop.IfExists](#rqsrs-006rbacroledropifexists) - * 5.2.8.88 [RQ.SRS-006.RBAC.Role.Drop.Cluster](#rqsrs-006rbacroledropcluster) - * 5.2.8.89 [RQ.SRS-006.RBAC.Role.Drop.Syntax](#rqsrs-006rbacroledropsyntax) - * 5.2.8.90 [RQ.SRS-006.RBAC.Role.ShowCreate](#rqsrs-006rbacroleshowcreate) - * 5.2.8.91 [RQ.SRS-006.RBAC.Role.ShowCreate.Syntax](#rqsrs-006rbacroleshowcreatesyntax) - * 5.2.8.92 [RQ.SRS-006.RBAC.Grant.Privilege.To](#rqsrs-006rbacgrantprivilegeto) - * 5.2.8.93 [RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser](#rqsrs-006rbacgrantprivilegetocurrentuser) - * 5.2.8.94 [RQ.SRS-006.RBAC.Grant.Privilege.Select](#rqsrs-006rbacgrantprivilegeselect) - * 5.2.8.95 [RQ.SRS-006.RBAC.Grant.Privilege.Insert](#rqsrs-006rbacgrantprivilegeinsert) - * 5.2.8.96 [RQ.SRS-006.RBAC.Grant.Privilege.Alter](#rqsrs-006rbacgrantprivilegealter) - * 5.2.8.97 [RQ.SRS-006.RBAC.Grant.Privilege.Create](#rqsrs-006rbacgrantprivilegecreate) - * 5.2.8.98 [RQ.SRS-006.RBAC.Grant.Privilege.Drop](#rqsrs-006rbacgrantprivilegedrop) - * 5.2.8.99 [RQ.SRS-006.RBAC.Grant.Privilege.Truncate](#rqsrs-006rbacgrantprivilegetruncate) - * 5.2.8.100 [RQ.SRS-006.RBAC.Grant.Privilege.Optimize](#rqsrs-006rbacgrantprivilegeoptimize) - * 5.2.8.101 [RQ.SRS-006.RBAC.Grant.Privilege.Show](#rqsrs-006rbacgrantprivilegeshow) - * 5.2.8.102 [RQ.SRS-006.RBAC.Grant.Privilege.KillQuery](#rqsrs-006rbacgrantprivilegekillquery) - * 5.2.8.103 [RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement](#rqsrs-006rbacgrantprivilegeaccessmanagement) - * 5.2.8.104 [RQ.SRS-006.RBAC.Grant.Privilege.System](#rqsrs-006rbacgrantprivilegesystem) - * 5.2.8.105 [RQ.SRS-006.RBAC.Grant.Privilege.Introspection](#rqsrs-006rbacgrantprivilegeintrospection) - * 5.2.8.106 [RQ.SRS-006.RBAC.Grant.Privilege.Sources](#rqsrs-006rbacgrantprivilegesources) - * 5.2.8.107 [RQ.SRS-006.RBAC.Grant.Privilege.DictGet](#rqsrs-006rbacgrantprivilegedictget) - * 5.2.8.108 [RQ.SRS-006.RBAC.Grant.Privilege.None](#rqsrs-006rbacgrantprivilegenone) - * 5.2.8.109 [RQ.SRS-006.RBAC.Grant.Privilege.All](#rqsrs-006rbacgrantprivilegeall) - * 5.2.8.110 [RQ.SRS-006.RBAC.Grant.Privilege.GrantOption](#rqsrs-006rbacgrantprivilegegrantoption) - * 5.2.8.111 [RQ.SRS-006.RBAC.Grant.Privilege.On](#rqsrs-006rbacgrantprivilegeon) - * 5.2.8.112 [RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns](#rqsrs-006rbacgrantprivilegeprivilegecolumns) - * 5.2.8.113 [RQ.SRS-006.RBAC.Grant.Privilege.OnCluster](#rqsrs-006rbacgrantprivilegeoncluster) - * 5.2.8.114 [RQ.SRS-006.RBAC.Grant.Privilege.Syntax](#rqsrs-006rbacgrantprivilegesyntax) - * 5.2.8.115 [RQ.SRS-006.RBAC.Revoke.Privilege.Cluster](#rqsrs-006rbacrevokeprivilegecluster) - * 5.2.8.116 [RQ.SRS-006.RBAC.Revoke.Privilege.Any](#rqsrs-006rbacrevokeprivilegeany) - * 5.2.8.117 [RQ.SRS-006.RBAC.Revoke.Privilege.Select](#rqsrs-006rbacrevokeprivilegeselect) - * 5.2.8.118 [RQ.SRS-006.RBAC.Revoke.Privilege.Insert](#rqsrs-006rbacrevokeprivilegeinsert) - * 5.2.8.119 [RQ.SRS-006.RBAC.Revoke.Privilege.Alter](#rqsrs-006rbacrevokeprivilegealter) - * 5.2.8.120 [RQ.SRS-006.RBAC.Revoke.Privilege.Create](#rqsrs-006rbacrevokeprivilegecreate) - * 5.2.8.121 [RQ.SRS-006.RBAC.Revoke.Privilege.Drop](#rqsrs-006rbacrevokeprivilegedrop) - * 5.2.8.122 [RQ.SRS-006.RBAC.Revoke.Privilege.Truncate](#rqsrs-006rbacrevokeprivilegetruncate) - * 5.2.8.123 [RQ.SRS-006.RBAC.Revoke.Privilege.Optimize](#rqsrs-006rbacrevokeprivilegeoptimize) - * 5.2.8.124 [RQ.SRS-006.RBAC.Revoke.Privilege.Show](#rqsrs-006rbacrevokeprivilegeshow) - * 5.2.8.125 [RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery](#rqsrs-006rbacrevokeprivilegekillquery) - * 5.2.8.126 [RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement](#rqsrs-006rbacrevokeprivilegeaccessmanagement) - * 5.2.8.127 [RQ.SRS-006.RBAC.Revoke.Privilege.System](#rqsrs-006rbacrevokeprivilegesystem) - * 5.2.8.128 [RQ.SRS-006.RBAC.Revoke.Privilege.Introspection](#rqsrs-006rbacrevokeprivilegeintrospection) - * 5.2.8.129 [RQ.SRS-006.RBAC.Revoke.Privilege.Sources](#rqsrs-006rbacrevokeprivilegesources) - * 5.2.8.130 [RQ.SRS-006.RBAC.Revoke.Privilege.DictGet](#rqsrs-006rbacrevokeprivilegedictget) - * 5.2.8.131 [RQ.SRS-006.RBAC.Revoke.Privilege.PrivelegeColumns](#rqsrs-006rbacrevokeprivilegeprivelegecolumns) - * 5.2.8.132 [RQ.SRS-006.RBAC.Revoke.Privilege.Multiple](#rqsrs-006rbacrevokeprivilegemultiple) - * 5.2.8.133 [RQ.SRS-006.RBAC.Revoke.Privilege.All](#rqsrs-006rbacrevokeprivilegeall) - * 5.2.8.134 [RQ.SRS-006.RBAC.Revoke.Privilege.None](#rqsrs-006rbacrevokeprivilegenone) - * 5.2.8.135 [RQ.SRS-006.RBAC.Revoke.Privilege.On](#rqsrs-006rbacrevokeprivilegeon) - * 5.2.8.136 [RQ.SRS-006.RBAC.Revoke.Privilege.From](#rqsrs-006rbacrevokeprivilegefrom) - * 5.2.8.137 [RQ.SRS-006.RBAC.Revoke.Privilege.Syntax](#rqsrs-006rbacrevokeprivilegesyntax) - * 5.2.8.138 [RQ.SRS-006.RBAC.PartialRevoke.Syntax](#rqsrs-006rbacpartialrevokesyntax) - * 5.2.8.139 [RQ.SRS-006.RBAC.Grant.Role](#rqsrs-006rbacgrantrole) - * 5.2.8.140 [RQ.SRS-006.RBAC.Grant.Role.CurrentUser](#rqsrs-006rbacgrantrolecurrentuser) - * 5.2.8.141 [RQ.SRS-006.RBAC.Grant.Role.AdminOption](#rqsrs-006rbacgrantroleadminoption) - * 5.2.8.142 [RQ.SRS-006.RBAC.Grant.Role.OnCluster](#rqsrs-006rbacgrantroleoncluster) - * 5.2.8.143 [RQ.SRS-006.RBAC.Grant.Role.Syntax](#rqsrs-006rbacgrantrolesyntax) - * 5.2.8.144 [RQ.SRS-006.RBAC.Revoke.Role](#rqsrs-006rbacrevokerole) - * 5.2.8.145 [RQ.SRS-006.RBAC.Revoke.Role.Keywords](#rqsrs-006rbacrevokerolekeywords) - * 5.2.8.146 [RQ.SRS-006.RBAC.Revoke.Role.Cluster](#rqsrs-006rbacrevokerolecluster) - * 5.2.8.147 [RQ.SRS-006.RBAC.Revoke.AdminOption](#rqsrs-006rbacrevokeadminoption) - * 5.2.8.148 [RQ.SRS-006.RBAC.Revoke.Role.Syntax](#rqsrs-006rbacrevokerolesyntax) - * 5.2.8.149 [RQ.SRS-006.RBAC.Show.Grants](#rqsrs-006rbacshowgrants) - * 5.2.8.150 [RQ.SRS-006.RBAC.Show.Grants.For](#rqsrs-006rbacshowgrantsfor) - * 5.2.8.151 [RQ.SRS-006.RBAC.Show.Grants.Syntax](#rqsrs-006rbacshowgrantssyntax) - * 5.2.8.152 [RQ.SRS-006.RBAC.SettingsProfile.Create](#rqsrs-006rbacsettingsprofilecreate) - * 5.2.8.153 [RQ.SRS-006.RBAC.SettingsProfile.Create.IfNotExists](#rqsrs-006rbacsettingsprofilecreateifnotexists) - * 5.2.8.154 [RQ.SRS-006.RBAC.SettingsProfile.Create.Replace](#rqsrs-006rbacsettingsprofilecreatereplace) - * 5.2.8.155 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables](#rqsrs-006rbacsettingsprofilecreatevariables) - * 5.2.8.156 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Value](#rqsrs-006rbacsettingsprofilecreatevariablesvalue) - * 5.2.8.157 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Constraints](#rqsrs-006rbacsettingsprofilecreatevariablesconstraints) - * 5.2.8.158 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment](#rqsrs-006rbacsettingsprofilecreateassignment) - * 5.2.8.159 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.None](#rqsrs-006rbacsettingsprofilecreateassignmentnone) - * 5.2.8.160 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.All](#rqsrs-006rbacsettingsprofilecreateassignmentall) - * 5.2.8.161 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.AllExcept](#rqsrs-006rbacsettingsprofilecreateassignmentallexcept) - * 5.2.8.162 [RQ.SRS-006.RBAC.SettingsProfile.Create.Inherit](#rqsrs-006rbacsettingsprofilecreateinherit) - * 5.2.8.163 [RQ.SRS-006.RBAC.SettingsProfile.Create.OnCluster](#rqsrs-006rbacsettingsprofilecreateoncluster) - * 5.2.8.164 [RQ.SRS-006.RBAC.SettingsProfile.Create.Syntax](#rqsrs-006rbacsettingsprofilecreatesyntax) - * 5.2.8.165 [RQ.SRS-006.RBAC.SettingsProfile.Alter](#rqsrs-006rbacsettingsprofilealter) - * 5.2.8.166 [RQ.SRS-006.RBAC.SettingsProfile.Alter.IfExists](#rqsrs-006rbacsettingsprofilealterifexists) - * 5.2.8.167 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Rename](#rqsrs-006rbacsettingsprofilealterrename) - * 5.2.8.168 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables](#rqsrs-006rbacsettingsprofilealtervariables) - * 5.2.8.169 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Value](#rqsrs-006rbacsettingsprofilealtervariablesvalue) - * 5.2.8.170 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Constraints](#rqsrs-006rbacsettingsprofilealtervariablesconstraints) - * 5.2.8.171 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment](#rqsrs-006rbacsettingsprofilealterassignment) - * 5.2.8.172 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.None](#rqsrs-006rbacsettingsprofilealterassignmentnone) - * 5.2.8.173 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.All](#rqsrs-006rbacsettingsprofilealterassignmentall) - * 5.2.8.174 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.AllExcept](#rqsrs-006rbacsettingsprofilealterassignmentallexcept) - * 5.2.8.175 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.Inherit](#rqsrs-006rbacsettingsprofilealterassignmentinherit) - * 5.2.8.176 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.OnCluster](#rqsrs-006rbacsettingsprofilealterassignmentoncluster) - * 5.2.8.177 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Syntax](#rqsrs-006rbacsettingsprofilealtersyntax) - * 5.2.8.178 [RQ.SRS-006.RBAC.SettingsProfile.Drop](#rqsrs-006rbacsettingsprofiledrop) - * 5.2.8.179 [RQ.SRS-006.RBAC.SettingsProfile.Drop.IfExists](#rqsrs-006rbacsettingsprofiledropifexists) - * 5.2.8.180 [RQ.SRS-006.RBAC.SettingsProfile.Drop.OnCluster](#rqsrs-006rbacsettingsprofiledroponcluster) - * 5.2.8.181 [RQ.SRS-006.RBAC.SettingsProfile.Drop.Syntax](#rqsrs-006rbacsettingsprofiledropsyntax) - * 5.2.8.182 [RQ.SRS-006.RBAC.SettingsProfile.ShowCreateSettingsProfile](#rqsrs-006rbacsettingsprofileshowcreatesettingsprofile) - * 5.2.8.183 [RQ.SRS-006.RBAC.Quota.Create](#rqsrs-006rbacquotacreate) - * 5.2.8.184 [RQ.SRS-006.RBAC.Quota.Create.IfNotExists](#rqsrs-006rbacquotacreateifnotexists) - * 5.2.8.185 [RQ.SRS-006.RBAC.Quota.Create.Replace](#rqsrs-006rbacquotacreatereplace) - * 5.2.8.186 [RQ.SRS-006.RBAC.Quota.Create.Cluster](#rqsrs-006rbacquotacreatecluster) - * 5.2.8.187 [RQ.SRS-006.RBAC.Quota.Create.Interval](#rqsrs-006rbacquotacreateinterval) - * 5.2.8.188 [RQ.SRS-006.RBAC.Quota.Create.Interval.Randomized](#rqsrs-006rbacquotacreateintervalrandomized) - * 5.2.8.189 [RQ.SRS-006.RBAC.Quota.Create.Queries](#rqsrs-006rbacquotacreatequeries) - * 5.2.8.190 [RQ.SRS-006.RBAC.Quota.Create.Errors](#rqsrs-006rbacquotacreateerrors) - * 5.2.8.191 [RQ.SRS-006.RBAC.Quota.Create.ResultRows](#rqsrs-006rbacquotacreateresultrows) - * 5.2.8.192 [RQ.SRS-006.RBAC.Quota.Create.ReadRows](#rqsrs-006rbacquotacreatereadrows) - * 5.2.8.193 [RQ.SRS-006.RBAC.Quota.Create.ResultBytes](#rqsrs-006rbacquotacreateresultbytes) - * 5.2.8.194 [RQ.SRS-006.RBAC.Quota.Create.ReadBytes](#rqsrs-006rbacquotacreatereadbytes) - * 5.2.8.195 [RQ.SRS-006.RBAC.Quota.Create.ExecutionTime](#rqsrs-006rbacquotacreateexecutiontime) - * 5.2.8.196 [RQ.SRS-006.RBAC.Quota.Create.NoLimits](#rqsrs-006rbacquotacreatenolimits) - * 5.2.8.197 [RQ.SRS-006.RBAC.Quota.Create.TrackingOnly](#rqsrs-006rbacquotacreatetrackingonly) - * 5.2.8.198 [RQ.SRS-006.RBAC.Quota.Create.KeyedBy](#rqsrs-006rbacquotacreatekeyedby) - * 5.2.8.199 [RQ.SRS-006.RBAC.Quota.Create.KeyedByOptions](#rqsrs-006rbacquotacreatekeyedbyoptions) - * 5.2.8.200 [RQ.SRS-006.RBAC.Quota.Create.Assignment](#rqsrs-006rbacquotacreateassignment) - * 5.2.8.201 [RQ.SRS-006.RBAC.Quota.Create.Assignment.None](#rqsrs-006rbacquotacreateassignmentnone) - * 5.2.8.202 [RQ.SRS-006.RBAC.Quota.Create.Assignment.All](#rqsrs-006rbacquotacreateassignmentall) - * 5.2.8.203 [RQ.SRS-006.RBAC.Quota.Create.Assignment.Except](#rqsrs-006rbacquotacreateassignmentexcept) - * 5.2.8.204 [RQ.SRS-006.RBAC.Quota.Create.Syntax](#rqsrs-006rbacquotacreatesyntax) - * 5.2.8.205 [RQ.SRS-006.RBAC.Quota.Alter](#rqsrs-006rbacquotaalter) - * 5.2.8.206 [RQ.SRS-006.RBAC.Quota.Alter.IfExists](#rqsrs-006rbacquotaalterifexists) - * 5.2.8.207 [RQ.SRS-006.RBAC.Quota.Alter.Rename](#rqsrs-006rbacquotaalterrename) - * 5.2.8.208 [RQ.SRS-006.RBAC.Quota.Alter.Cluster](#rqsrs-006rbacquotaaltercluster) - * 5.2.8.209 [RQ.SRS-006.RBAC.Quota.Alter.Interval](#rqsrs-006rbacquotaalterinterval) - * 5.2.8.210 [RQ.SRS-006.RBAC.Quota.Alter.Interval.Randomized](#rqsrs-006rbacquotaalterintervalrandomized) - * 5.2.8.211 [RQ.SRS-006.RBAC.Quota.Alter.Queries](#rqsrs-006rbacquotaalterqueries) - * 5.2.8.212 [RQ.SRS-006.RBAC.Quota.Alter.Errors](#rqsrs-006rbacquotaaltererrors) - * 5.2.8.213 [RQ.SRS-006.RBAC.Quota.Alter.ResultRows](#rqsrs-006rbacquotaalterresultrows) - * 5.2.8.214 [RQ.SRS-006.RBAC.Quota.Alter.ReadRows](#rqsrs-006rbacquotaalterreadrows) - * 5.2.8.215 [RQ.SRS-006.RBAC.Quota.ALter.ResultBytes](#rqsrs-006rbacquotaalterresultbytes) - * 5.2.8.216 [RQ.SRS-006.RBAC.Quota.Alter.ReadBytes](#rqsrs-006rbacquotaalterreadbytes) - * 5.2.8.217 [RQ.SRS-006.RBAC.Quota.Alter.ExecutionTime](#rqsrs-006rbacquotaalterexecutiontime) - * 5.2.8.218 [RQ.SRS-006.RBAC.Quota.Alter.NoLimits](#rqsrs-006rbacquotaalternolimits) - * 5.2.8.219 [RQ.SRS-006.RBAC.Quota.Alter.TrackingOnly](#rqsrs-006rbacquotaaltertrackingonly) - * 5.2.8.220 [RQ.SRS-006.RBAC.Quota.Alter.KeyedBy](#rqsrs-006rbacquotaalterkeyedby) - * 5.2.8.221 [RQ.SRS-006.RBAC.Quota.Alter.KeyedByOptions](#rqsrs-006rbacquotaalterkeyedbyoptions) - * 5.2.8.222 [RQ.SRS-006.RBAC.Quota.Alter.Assignment](#rqsrs-006rbacquotaalterassignment) - * 5.2.8.223 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.None](#rqsrs-006rbacquotaalterassignmentnone) - * 5.2.8.224 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.All](#rqsrs-006rbacquotaalterassignmentall) - * 5.2.8.225 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.Except](#rqsrs-006rbacquotaalterassignmentexcept) - * 5.2.8.226 [RQ.SRS-006.RBAC.Quota.Alter.Syntax](#rqsrs-006rbacquotaaltersyntax) - * 5.2.8.227 [RQ.SRS-006.RBAC.Quota.Drop](#rqsrs-006rbacquotadrop) - * 5.2.8.228 [RQ.SRS-006.RBAC.Quota.Drop.IfExists](#rqsrs-006rbacquotadropifexists) - * 5.2.8.229 [RQ.SRS-006.RBAC.Quota.Drop.Cluster](#rqsrs-006rbacquotadropcluster) - * 5.2.8.230 [RQ.SRS-006.RBAC.Quota.Drop.Syntax](#rqsrs-006rbacquotadropsyntax) - * 5.2.8.231 [RQ.SRS-006.RBAC.Quota.ShowQuotas](#rqsrs-006rbacquotashowquotas) - * 5.2.8.232 [RQ.SRS-006.RBAC.Quota.ShowQuotas.IntoOutfile](#rqsrs-006rbacquotashowquotasintooutfile) - * 5.2.8.233 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Format](#rqsrs-006rbacquotashowquotasformat) - * 5.2.8.234 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Settings](#rqsrs-006rbacquotashowquotassettings) - * 5.2.8.235 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Syntax](#rqsrs-006rbacquotashowquotassyntax) - * 5.2.8.236 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Name](#rqsrs-006rbacquotashowcreatequotaname) - * 5.2.8.237 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Current](#rqsrs-006rbacquotashowcreatequotacurrent) - * 5.2.8.238 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Syntax](#rqsrs-006rbacquotashowcreatequotasyntax) - * 5.2.8.239 [RQ.SRS-006.RBAC.RowPolicy.Create](#rqsrs-006rbacrowpolicycreate) - * 5.2.8.240 [RQ.SRS-006.RBAC.RowPolicy.Create.IfNotExists](#rqsrs-006rbacrowpolicycreateifnotexists) - * 5.2.8.241 [RQ.SRS-006.RBAC.RowPolicy.Create.Replace](#rqsrs-006rbacrowpolicycreatereplace) - * 5.2.8.242 [RQ.SRS-006.RBAC.RowPolicy.Create.OnCluster](#rqsrs-006rbacrowpolicycreateoncluster) - * 5.2.8.243 [RQ.SRS-006.RBAC.RowPolicy.Create.On](#rqsrs-006rbacrowpolicycreateon) - * 5.2.8.244 [RQ.SRS-006.RBAC.RowPolicy.Create.Access](#rqsrs-006rbacrowpolicycreateaccess) - * 5.2.8.245 [RQ.SRS-006.RBAC.RowPolicy.Create.Access.Permissive](#rqsrs-006rbacrowpolicycreateaccesspermissive) - * 5.2.8.246 [RQ.SRS-006.RBAC.RowPolicy.Create.Access.Restrictive](#rqsrs-006rbacrowpolicycreateaccessrestrictive) - * 5.2.8.247 [RQ.SRS-006.RBAC.RowPolicy.Create.ForSelect](#rqsrs-006rbacrowpolicycreateforselect) - * 5.2.8.248 [RQ.SRS-006.RBAC.RowPolicy.Create.Condition](#rqsrs-006rbacrowpolicycreatecondition) - * 5.2.8.249 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment](#rqsrs-006rbacrowpolicycreateassignment) - * 5.2.8.250 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.None](#rqsrs-006rbacrowpolicycreateassignmentnone) - * 5.2.8.251 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.All](#rqsrs-006rbacrowpolicycreateassignmentall) - * 5.2.8.252 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.AllExcept](#rqsrs-006rbacrowpolicycreateassignmentallexcept) - * 5.2.8.253 [RQ.SRS-006.RBAC.RowPolicy.Create.Syntax](#rqsrs-006rbacrowpolicycreatesyntax) - * 5.2.8.254 [RQ.SRS-006.RBAC.RowPolicy.Alter](#rqsrs-006rbacrowpolicyalter) - * 5.2.8.255 [RQ.SRS-006.RBAC.RowPolicy.Alter.IfExists](#rqsrs-006rbacrowpolicyalterifexists) - * 5.2.8.256 [RQ.SRS-006.RBAC.RowPolicy.Alter.ForSelect](#rqsrs-006rbacrowpolicyalterforselect) - * 5.2.8.257 [RQ.SRS-006.RBAC.RowPolicy.Alter.OnCluster](#rqsrs-006rbacrowpolicyalteroncluster) - * 5.2.8.258 [RQ.SRS-006.RBAC.RowPolicy.Alter.On](#rqsrs-006rbacrowpolicyalteron) - * 5.2.8.259 [RQ.SRS-006.RBAC.RowPolicy.Alter.Rename](#rqsrs-006rbacrowpolicyalterrename) - * 5.2.8.260 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access](#rqsrs-006rbacrowpolicyalteraccess) - * 5.2.8.261 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Permissive](#rqsrs-006rbacrowpolicyalteraccesspermissive) - * 5.2.8.262 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Restrictive](#rqsrs-006rbacrowpolicyalteraccessrestrictive) - * 5.2.8.263 [RQ.SRS-006.RBAC.RowPolicy.Alter.Condition](#rqsrs-006rbacrowpolicyaltercondition) - * 5.2.8.264 [RQ.SRS-006.RBAC.RowPolicy.Alter.Condition.None](#rqsrs-006rbacrowpolicyalterconditionnone) - * 5.2.8.265 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment](#rqsrs-006rbacrowpolicyalterassignment) - * 5.2.8.266 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.None](#rqsrs-006rbacrowpolicyalterassignmentnone) - * 5.2.8.267 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.All](#rqsrs-006rbacrowpolicyalterassignmentall) - * 5.2.8.268 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.AllExcept](#rqsrs-006rbacrowpolicyalterassignmentallexcept) - * 5.2.8.269 [RQ.SRS-006.RBAC.RowPolicy.Alter.Syntax](#rqsrs-006rbacrowpolicyaltersyntax) - * 5.2.8.270 [RQ.SRS-006.RBAC.RowPolicy.Drop](#rqsrs-006rbacrowpolicydrop) - * 5.2.8.271 [RQ.SRS-006.RBAC.RowPolicy.Drop.IfExists](#rqsrs-006rbacrowpolicydropifexists) - * 5.2.8.272 [RQ.SRS-006.RBAC.RowPolicy.Drop.On](#rqsrs-006rbacrowpolicydropon) - * 5.2.8.273 [RQ.SRS-006.RBAC.RowPolicy.Drop.OnCluster](#rqsrs-006rbacrowpolicydroponcluster) - * 5.2.8.274 [RQ.SRS-006.RBAC.RowPolicy.Drop.Syntax](#rqsrs-006rbacrowpolicydropsyntax) - * 5.2.8.275 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy](#rqsrs-006rbacrowpolicyshowcreaterowpolicy) - * 5.2.8.276 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.On](#rqsrs-006rbacrowpolicyshowcreaterowpolicyon) - * 5.2.8.277 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.Syntax](#rqsrs-006rbacrowpolicyshowcreaterowpolicysyntax) - * 5.2.8.278 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies](#rqsrs-006rbacrowpolicyshowrowpolicies) - * 5.2.8.279 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.On](#rqsrs-006rbacrowpolicyshowrowpolicieson) - * 5.2.8.280 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.Syntax](#rqsrs-006rbacrowpolicyshowrowpoliciessyntax) - * 5.2.9 [Table Privileges](#table-privileges) - * 5.2.9.1 [RQ.SRS-006.RBAC.Table.PublicTables](#rqsrs-006rbactablepublictables) - * 5.2.9.2 [RQ.SRS-006.RBAC.Table.SensitiveTables](#rqsrs-006rbactablesensitivetables) - * 5.2.10 [Distributed Tables](#distributed-tables) - * 5.2.10.1 [RQ.SRS-006.RBAC.DistributedTable.Create](#rqsrs-006rbacdistributedtablecreate) - * 5.2.10.2 [RQ.SRS-006.RBAC.DistributedTable.Select](#rqsrs-006rbacdistributedtableselect) - * 5.2.10.3 [RQ.SRS-006.RBAC.DistributedTable.Insert](#rqsrs-006rbacdistributedtableinsert) - * 5.2.10.4 [RQ.SRS-006.RBAC.DistributedTable.SpecialTables](#rqsrs-006rbacdistributedtablespecialtables) - * 5.2.10.5 [RQ.SRS-006.RBAC.DistributedTable.LocalUser](#rqsrs-006rbacdistributedtablelocaluser) - * 5.2.10.6 [RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges](#rqsrs-006rbacdistributedtablesameuserdifferentnodesdifferentprivileges) - * 5.2.11 [Views](#views) - * 5.2.11.1 [View](#view) - * 5.2.11.1.1 [RQ.SRS-006.RBAC.View](#rqsrs-006rbacview) - * 5.2.11.1.2 [RQ.SRS-006.RBAC.View.Create](#rqsrs-006rbacviewcreate) - * 5.2.11.1.3 [RQ.SRS-006.RBAC.View.Select](#rqsrs-006rbacviewselect) - * 5.2.11.1.4 [RQ.SRS-006.RBAC.View.Drop](#rqsrs-006rbacviewdrop) - * 5.2.11.2 [Materialized View](#materialized-view) - * 5.2.11.2.1 [RQ.SRS-006.RBAC.MaterializedView](#rqsrs-006rbacmaterializedview) - * 5.2.11.2.2 [RQ.SRS-006.RBAC.MaterializedView.Create](#rqsrs-006rbacmaterializedviewcreate) - * 5.2.11.2.3 [RQ.SRS-006.RBAC.MaterializedView.Select](#rqsrs-006rbacmaterializedviewselect) - * 5.2.11.2.4 [RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable](#rqsrs-006rbacmaterializedviewselecttargettable) - * 5.2.11.2.5 [RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable](#rqsrs-006rbacmaterializedviewselectsourcetable) - * 5.2.11.2.6 [RQ.SRS-006.RBAC.MaterializedView.Drop](#rqsrs-006rbacmaterializedviewdrop) - * 5.2.11.2.7 [RQ.SRS-006.RBAC.MaterializedView.ModifyQuery](#rqsrs-006rbacmaterializedviewmodifyquery) - * 5.2.11.2.8 [RQ.SRS-006.RBAC.MaterializedView.Insert](#rqsrs-006rbacmaterializedviewinsert) - * 5.2.11.2.9 [RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable](#rqsrs-006rbacmaterializedviewinsertsourcetable) - * 5.2.11.2.10 [RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable](#rqsrs-006rbacmaterializedviewinserttargettable) - * 5.2.11.3 [Live View](#live-view) - * 5.2.11.3.1 [RQ.SRS-006.RBAC.LiveView](#rqsrs-006rbacliveview) - * 5.2.11.3.2 [RQ.SRS-006.RBAC.LiveView.Create](#rqsrs-006rbacliveviewcreate) - * 5.2.11.3.3 [RQ.SRS-006.RBAC.LiveView.Select](#rqsrs-006rbacliveviewselect) - * 5.2.11.3.4 [RQ.SRS-006.RBAC.LiveView.Drop](#rqsrs-006rbacliveviewdrop) - * 5.2.11.3.5 [RQ.SRS-006.RBAC.LiveView.Refresh](#rqsrs-006rbacliveviewrefresh) - * 5.2.12 [Select](#select) - * 5.2.12.1 [RQ.SRS-006.RBAC.Select](#rqsrs-006rbacselect) - * 5.2.12.2 [RQ.SRS-006.RBAC.Select.Column](#rqsrs-006rbacselectcolumn) - * 5.2.12.3 [RQ.SRS-006.RBAC.Select.Cluster](#rqsrs-006rbacselectcluster) - * 5.2.12.4 [RQ.SRS-006.RBAC.Select.TableEngines](#rqsrs-006rbacselecttableengines) - * 5.2.13 [Insert](#insert) - * 5.2.13.1 [RQ.SRS-006.RBAC.Insert](#rqsrs-006rbacinsert) - * 5.2.13.2 [RQ.SRS-006.RBAC.Insert.Column](#rqsrs-006rbacinsertcolumn) - * 5.2.13.3 [RQ.SRS-006.RBAC.Insert.Cluster](#rqsrs-006rbacinsertcluster) - * 5.2.13.4 [RQ.SRS-006.RBAC.Insert.TableEngines](#rqsrs-006rbacinserttableengines) - * 5.2.14 [Alter](#alter) - * 5.2.14.1 [Alter Column](#alter-column) - * 5.2.14.1.1 [RQ.SRS-006.RBAC.Privileges.AlterColumn](#rqsrs-006rbacprivilegesaltercolumn) - * 5.2.14.1.2 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant](#rqsrs-006rbacprivilegesaltercolumngrant) - * 5.2.14.1.3 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke](#rqsrs-006rbacprivilegesaltercolumnrevoke) - * 5.2.14.1.4 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Column](#rqsrs-006rbacprivilegesaltercolumncolumn) - * 5.2.14.1.5 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster](#rqsrs-006rbacprivilegesaltercolumncluster) - * 5.2.14.1.6 [RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines](#rqsrs-006rbacprivilegesaltercolumntableengines) - * 5.2.14.2 [Alter Index](#alter-index) - * 5.2.14.2.1 [RQ.SRS-006.RBAC.Privileges.AlterIndex](#rqsrs-006rbacprivilegesalterindex) - * 5.2.14.2.2 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant](#rqsrs-006rbacprivilegesalterindexgrant) - * 5.2.14.2.3 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke](#rqsrs-006rbacprivilegesalterindexrevoke) - * 5.2.14.2.4 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster](#rqsrs-006rbacprivilegesalterindexcluster) - * 5.2.14.2.5 [RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines](#rqsrs-006rbacprivilegesalterindextableengines) - * 5.2.14.3 [Alter Constraint](#alter-constraint) - * 5.2.14.3.1 [RQ.SRS-006.RBAC.Privileges.AlterConstraint](#rqsrs-006rbacprivilegesalterconstraint) - * 5.2.14.3.2 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant](#rqsrs-006rbacprivilegesalterconstraintgrant) - * 5.2.14.3.3 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke](#rqsrs-006rbacprivilegesalterconstraintrevoke) - * 5.2.14.3.4 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster](#rqsrs-006rbacprivilegesalterconstraintcluster) - * 5.2.14.3.5 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines](#rqsrs-006rbacprivilegesalterconstrainttableengines) - * 5.2.14.4 [Alter TTL](#alter-ttl) - * 5.2.14.4.1 [RQ.SRS-006.RBAC.Privileges.AlterTTL](#rqsrs-006rbacprivilegesalterttl) - * 5.2.14.4.2 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant](#rqsrs-006rbacprivilegesalterttlgrant) - * 5.2.14.4.3 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke](#rqsrs-006rbacprivilegesalterttlrevoke) - * 5.2.14.4.4 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster](#rqsrs-006rbacprivilegesalterttlcluster) - * 5.2.14.4.5 [RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines](#rqsrs-006rbacprivilegesalterttltableengines) - * 5.2.14.5 [Alter Settings](#alter-settings) - * 5.2.14.5.1 [RQ.SRS-006.RBAC.Privileges.AlterSettings](#rqsrs-006rbacprivilegesaltersettings) - * 5.2.14.5.2 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant](#rqsrs-006rbacprivilegesaltersettingsgrant) - * 5.2.14.5.3 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke](#rqsrs-006rbacprivilegesaltersettingsrevoke) - * 5.2.14.5.4 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster](#rqsrs-006rbacprivilegesaltersettingscluster) - * 5.2.14.5.5 [RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines](#rqsrs-006rbacprivilegesaltersettingstableengines) - * 5.2.14.6 [Alter Update](#alter-update) - * 5.2.14.6.1 [RQ.SRS-006.RBAC.Privileges.AlterUpdate](#rqsrs-006rbacprivilegesalterupdate) - * 5.2.14.6.2 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant](#rqsrs-006rbacprivilegesalterupdategrant) - * 5.2.14.6.3 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke](#rqsrs-006rbacprivilegesalterupdaterevoke) - * 5.2.14.6.4 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines](#rqsrs-006rbacprivilegesalterupdatetableengines) - * 5.2.14.7 [Alter Delete](#alter-delete) - * 5.2.14.7.1 [RQ.SRS-006.RBAC.Privileges.AlterDelete](#rqsrs-006rbacprivilegesalterdelete) - * 5.2.14.7.2 [RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant](#rqsrs-006rbacprivilegesalterdeletegrant) - * 5.2.14.7.3 [RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke](#rqsrs-006rbacprivilegesalterdeleterevoke) - * 5.2.14.7.4 [RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines](#rqsrs-006rbacprivilegesalterdeletetableengines) - * 5.2.14.8 [Alter Freeze Partition](#alter-freeze-partition) - * 5.2.14.8.1 [RQ.SRS-006.RBAC.Privileges.AlterFreeze](#rqsrs-006rbacprivilegesalterfreeze) - * 5.2.14.8.2 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant](#rqsrs-006rbacprivilegesalterfreezegrant) - * 5.2.14.8.3 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke](#rqsrs-006rbacprivilegesalterfreezerevoke) - * 5.2.14.8.4 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines](#rqsrs-006rbacprivilegesalterfreezetableengines) - * 5.2.14.9 [Alter Fetch Partition](#alter-fetch-partition) - * 5.2.14.9.1 [RQ.SRS-006.RBAC.Privileges.AlterFetch](#rqsrs-006rbacprivilegesalterfetch) - * 5.2.14.9.2 [RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant](#rqsrs-006rbacprivilegesalterfetchgrant) - * 5.2.14.9.3 [RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke](#rqsrs-006rbacprivilegesalterfetchrevoke) - * 5.2.14.9.4 [RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines](#rqsrs-006rbacprivilegesalterfetchtableengines) - * 5.2.14.10 [Alter Move Partition](#alter-move-partition) - * 5.2.14.10.1 [RQ.SRS-006.RBAC.Privileges.AlterMove](#rqsrs-006rbacprivilegesaltermove) - * 5.2.14.10.2 [RQ.SRS-006.RBAC.Privileges.AlterMove.Grant](#rqsrs-006rbacprivilegesaltermovegrant) - * 5.2.14.10.3 [RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke](#rqsrs-006rbacprivilegesaltermoverevoke) - * 5.2.14.10.4 [RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines](#rqsrs-006rbacprivilegesaltermovetableengines) - * 5.2.15 [RQ.SRS-006.RBAC.Privileges.CreateTable](#rqsrs-006rbacprivilegescreatetable) - * 5.2.16 [RQ.SRS-006.RBAC.Privileges.CreateDatabase](#rqsrs-006rbacprivilegescreatedatabase) - * 5.2.17 [RQ.SRS-006.RBAC.Privileges.CreateDictionary](#rqsrs-006rbacprivilegescreatedictionary) - * 5.2.18 [RQ.SRS-006.RBAC.Privileges.CreateTemporaryTable](#rqsrs-006rbacprivilegescreatetemporarytable) - * 5.2.19 [RQ.SRS-006.RBAC.Privileges.AttachDatabase](#rqsrs-006rbacprivilegesattachdatabase) - * 5.2.20 [RQ.SRS-006.RBAC.Privileges.AttachDictionary](#rqsrs-006rbacprivilegesattachdictionary) - * 5.2.21 [RQ.SRS-006.RBAC.Privileges.AttachTemporaryTable](#rqsrs-006rbacprivilegesattachtemporarytable) - * 5.2.22 [RQ.SRS-006.RBAC.Privileges.AttachTable](#rqsrs-006rbacprivilegesattachtable) - * 5.2.23 [RQ.SRS-006.RBAC.Privileges.DropTable](#rqsrs-006rbacprivilegesdroptable) - * 5.2.24 [RQ.SRS-006.RBAC.Privileges.DropDatabase](#rqsrs-006rbacprivilegesdropdatabase) - * 5.2.25 [RQ.SRS-006.RBAC.Privileges.DropDictionary](#rqsrs-006rbacprivilegesdropdictionary) - * 5.2.26 [RQ.SRS-006.RBAC.Privileges.DetachTable](#rqsrs-006rbacprivilegesdetachtable) - * 5.2.27 [RQ.SRS-006.RBAC.Privileges.DetachView](#rqsrs-006rbacprivilegesdetachview) - * 5.2.28 [RQ.SRS-006.RBAC.Privileges.DetachDatabase](#rqsrs-006rbacprivilegesdetachdatabase) - * 5.2.29 [RQ.SRS-006.RBAC.Privileges.DetachDictionary](#rqsrs-006rbacprivilegesdetachdictionary) - * 5.2.30 [RQ.SRS-006.RBAC.Privileges.Truncate](#rqsrs-006rbacprivilegestruncate) - * 5.2.31 [RQ.SRS-006.RBAC.Privileges.Optimize](#rqsrs-006rbacprivilegesoptimize) - * 5.2.32 [RQ.SRS-006.RBAC.Privileges.KillQuery](#rqsrs-006rbacprivilegeskillquery) - * 5.2.33 [Kill Mutation](#kill-mutation) - * 5.2.33.1 [RQ.SRS-006.RBAC.Privileges.KillMutation](#rqsrs-006rbacprivilegeskillmutation) - * 5.2.33.2 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate](#rqsrs-006rbacprivilegeskillmutationalterupdate) - * 5.2.33.3 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete](#rqsrs-006rbacprivilegeskillmutationalterdelete) - * 5.2.33.4 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn](#rqsrs-006rbacprivilegeskillmutationalterdropcolumn) - * 5.2.34 [Show](#show) - * 5.2.34.1 [RQ.SRS-006.RBAC.ShowTables.Privilege](#rqsrs-006rbacshowtablesprivilege) - * 5.2.34.2 [RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege](#rqsrs-006rbacshowtablesrequiredprivilege) - * 5.2.34.3 [RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege](#rqsrs-006rbacexiststablerequiredprivilege) - * 5.2.34.4 [RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege](#rqsrs-006rbacchecktablerequiredprivilege) - * 5.2.34.5 [RQ.SRS-006.RBAC.ShowDatabases.Privilege](#rqsrs-006rbacshowdatabasesprivilege) - * 5.2.34.6 [RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege](#rqsrs-006rbacshowdatabasesrequiredprivilege) - * 5.2.34.7 [RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege](#rqsrs-006rbacshowcreatedatabaserequiredprivilege) - * 5.2.34.8 [RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege](#rqsrs-006rbacusedatabaserequiredprivilege) - * 5.2.34.9 [RQ.SRS-006.RBAC.ShowColumns.Privilege](#rqsrs-006rbacshowcolumnsprivilege) - * 5.2.34.10 [RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege](#rqsrs-006rbacshowcreatetablerequiredprivilege) - * 5.2.34.11 [RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege](#rqsrs-006rbacdescribetablerequiredprivilege) - * 5.2.34.12 [RQ.SRS-006.RBAC.ShowDictionaries.Privilege](#rqsrs-006rbacshowdictionariesprivilege) - * 5.2.34.13 [RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege](#rqsrs-006rbacshowdictionariesrequiredprivilege) - * 5.2.34.14 [RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege](#rqsrs-006rbacshowcreatedictionaryrequiredprivilege) - * 5.2.34.15 [RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege](#rqsrs-006rbacexistsdictionaryrequiredprivilege) - * 5.2.35 [Access Management](#access-management) - * 5.2.35.1 [RQ.SRS-006.RBAC.Privileges.CreateUser](#rqsrs-006rbacprivilegescreateuser) - * 5.2.35.2 [RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole](#rqsrs-006rbacprivilegescreateuserdefaultrole) - * 5.2.35.3 [RQ.SRS-006.RBAC.Privileges.AlterUser](#rqsrs-006rbacprivilegesalteruser) - * 5.2.35.4 [RQ.SRS-006.RBAC.Privileges.DropUser](#rqsrs-006rbacprivilegesdropuser) - * 5.2.35.5 [RQ.SRS-006.RBAC.Privileges.CreateRole](#rqsrs-006rbacprivilegescreaterole) - * 5.2.35.6 [RQ.SRS-006.RBAC.Privileges.AlterRole](#rqsrs-006rbacprivilegesalterrole) - * 5.2.35.7 [RQ.SRS-006.RBAC.Privileges.DropRole](#rqsrs-006rbacprivilegesdroprole) - * 5.2.35.8 [RQ.SRS-006.RBAC.Privileges.CreateRowPolicy](#rqsrs-006rbacprivilegescreaterowpolicy) - * 5.2.35.9 [RQ.SRS-006.RBAC.Privileges.AlterRowPolicy](#rqsrs-006rbacprivilegesalterrowpolicy) - * 5.2.35.10 [RQ.SRS-006.RBAC.Privileges.DropRowPolicy](#rqsrs-006rbacprivilegesdroprowpolicy) - * 5.2.35.11 [RQ.SRS-006.RBAC.Privileges.CreateQuota](#rqsrs-006rbacprivilegescreatequota) - * 5.2.35.12 [RQ.SRS-006.RBAC.Privileges.AlterQuota](#rqsrs-006rbacprivilegesalterquota) - * 5.2.35.13 [RQ.SRS-006.RBAC.Privileges.DropQuota](#rqsrs-006rbacprivilegesdropquota) - * 5.2.35.14 [RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile](#rqsrs-006rbacprivilegescreatesettingsprofile) - * 5.2.35.15 [RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile](#rqsrs-006rbacprivilegesaltersettingsprofile) - * 5.2.35.16 [RQ.SRS-006.RBAC.Privileges.DropSettingsProfile](#rqsrs-006rbacprivilegesdropsettingsprofile) - * 5.2.35.17 [RQ.SRS-006.RBAC.Privileges.RoleAdmin](#rqsrs-006rbacprivilegesroleadmin) - * 5.2.35.18 [Show Access](#show-access) - * 5.2.35.18.1 [RQ.SRS-006.RBAC.ShowUsers.Privilege](#rqsrs-006rbacshowusersprivilege) - * 5.2.35.18.2 [RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege](#rqsrs-006rbacshowusersrequiredprivilege) - * 5.2.35.18.3 [RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege](#rqsrs-006rbacshowcreateuserrequiredprivilege) - * 5.2.35.18.4 [RQ.SRS-006.RBAC.ShowRoles.Privilege](#rqsrs-006rbacshowrolesprivilege) - * 5.2.35.18.5 [RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege](#rqsrs-006rbacshowrolesrequiredprivilege) - * 5.2.35.18.6 [RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege](#rqsrs-006rbacshowcreaterolerequiredprivilege) - * 5.2.35.18.7 [RQ.SRS-006.RBAC.ShowRowPolicies.Privilege](#rqsrs-006rbacshowrowpoliciesprivilege) - * 5.2.35.18.8 [RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege](#rqsrs-006rbacshowrowpoliciesrequiredprivilege) - * 5.2.35.18.9 [RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege](#rqsrs-006rbacshowcreaterowpolicyrequiredprivilege) - * 5.2.35.18.10 [RQ.SRS-006.RBAC.ShowQuotas.Privilege](#rqsrs-006rbacshowquotasprivilege) - * 5.2.35.18.11 [RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege](#rqsrs-006rbacshowquotasrequiredprivilege) - * 5.2.35.18.12 [RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege](#rqsrs-006rbacshowcreatequotarequiredprivilege) - * 5.2.35.18.13 [RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege](#rqsrs-006rbacshowsettingsprofilesprivilege) - * 5.2.35.18.14 [RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege](#rqsrs-006rbacshowsettingsprofilesrequiredprivilege) - * 5.2.35.18.15 [RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege](#rqsrs-006rbacshowcreatesettingsprofilerequiredprivilege) - * 5.2.36 [dictGet](#dictget) - * 5.2.36.1 [RQ.SRS-006.RBAC.dictGet.Privilege](#rqsrs-006rbacdictgetprivilege) - * 5.2.36.2 [RQ.SRS-006.RBAC.dictGet.RequiredPrivilege](#rqsrs-006rbacdictgetrequiredprivilege) - * 5.2.36.3 [RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege](#rqsrs-006rbacdictgettyperequiredprivilege) - * 5.2.36.4 [RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege](#rqsrs-006rbacdictgetordefaultrequiredprivilege) - * 5.2.36.5 [RQ.SRS-006.RBAC.dictHas.RequiredPrivilege](#rqsrs-006rbacdicthasrequiredprivilege) - * 5.2.36.6 [RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege](#rqsrs-006rbacdictgethierarchyrequiredprivilege) - * 5.2.36.7 [RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege](#rqsrs-006rbacdictisinrequiredprivilege) - * 5.2.37 [Introspection](#introspection) - * 5.2.37.1 [RQ.SRS-006.RBAC.Privileges.Introspection](#rqsrs-006rbacprivilegesintrospection) - * 5.2.37.2 [RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine](#rqsrs-006rbacprivilegesintrospectionaddresstoline) - * 5.2.37.3 [RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol](#rqsrs-006rbacprivilegesintrospectionaddresstosymbol) - * 5.2.37.4 [RQ.SRS-006.RBAC.Privileges.Introspection.demangle](#rqsrs-006rbacprivilegesintrospectiondemangle) - * 5.2.38 [System](#system) - * 5.2.38.1 [RQ.SRS-006.RBAC.Privileges.System.Shutdown](#rqsrs-006rbacprivilegessystemshutdown) - * 5.2.38.2 [RQ.SRS-006.RBAC.Privileges.System.DropCache](#rqsrs-006rbacprivilegessystemdropcache) - * 5.2.38.3 [RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS](#rqsrs-006rbacprivilegessystemdropcachedns) - * 5.2.38.4 [RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark](#rqsrs-006rbacprivilegessystemdropcachemark) - * 5.2.38.5 [RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed](#rqsrs-006rbacprivilegessystemdropcacheuncompressed) - * 5.2.38.6 [RQ.SRS-006.RBAC.Privileges.System.Reload](#rqsrs-006rbacprivilegessystemreload) - * 5.2.38.7 [RQ.SRS-006.RBAC.Privileges.System.Reload.Config](#rqsrs-006rbacprivilegessystemreloadconfig) - * 5.2.38.8 [RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary](#rqsrs-006rbacprivilegessystemreloaddictionary) - * 5.2.38.9 [RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries](#rqsrs-006rbacprivilegessystemreloaddictionaries) - * 5.2.38.10 [RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries](#rqsrs-006rbacprivilegessystemreloadembeddeddictionaries) - * 5.2.38.11 [RQ.SRS-006.RBAC.Privileges.System.Merges](#rqsrs-006rbacprivilegessystemmerges) - * 5.2.38.12 [RQ.SRS-006.RBAC.Privileges.System.TTLMerges](#rqsrs-006rbacprivilegessystemttlmerges) - * 5.2.38.13 [RQ.SRS-006.RBAC.Privileges.System.Fetches](#rqsrs-006rbacprivilegessystemfetches) - * 5.2.38.14 [RQ.SRS-006.RBAC.Privileges.System.Moves](#rqsrs-006rbacprivilegessystemmoves) - * 5.2.38.15 [RQ.SRS-006.RBAC.Privileges.System.Sends](#rqsrs-006rbacprivilegessystemsends) - * 5.2.38.16 [RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed](#rqsrs-006rbacprivilegessystemsendsdistributed) - * 5.2.38.17 [RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated](#rqsrs-006rbacprivilegessystemsendsreplicated) - * 5.2.38.18 [RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues](#rqsrs-006rbacprivilegessystemreplicationqueues) - * 5.2.38.19 [RQ.SRS-006.RBAC.Privileges.System.SyncReplica](#rqsrs-006rbacprivilegessystemsyncreplica) - * 5.2.38.20 [RQ.SRS-006.RBAC.Privileges.System.RestartReplica](#rqsrs-006rbacprivilegessystemrestartreplica) - * 5.2.38.21 [RQ.SRS-006.RBAC.Privileges.System.Flush](#rqsrs-006rbacprivilegessystemflush) - * 5.2.38.22 [RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed](#rqsrs-006rbacprivilegessystemflushdistributed) - * 5.2.38.23 [RQ.SRS-006.RBAC.Privileges.System.Flush.Logs](#rqsrs-006rbacprivilegessystemflushlogs) - * 5.2.39 [Sources](#sources) - * 5.2.39.1 [RQ.SRS-006.RBAC.Privileges.Sources](#rqsrs-006rbacprivilegessources) - * 5.2.39.2 [RQ.SRS-006.RBAC.Privileges.Sources.File](#rqsrs-006rbacprivilegessourcesfile) - * 5.2.39.3 [RQ.SRS-006.RBAC.Privileges.Sources.URL](#rqsrs-006rbacprivilegessourcesurl) - * 5.2.39.4 [RQ.SRS-006.RBAC.Privileges.Sources.Remote](#rqsrs-006rbacprivilegessourcesremote) - * 5.2.39.5 [RQ.SRS-006.RBAC.Privileges.Sources.MySQL](#rqsrs-006rbacprivilegessourcesmysql) - * 5.2.39.6 [RQ.SRS-006.RBAC.Privileges.Sources.ODBC](#rqsrs-006rbacprivilegessourcesodbc) - * 5.2.39.7 [RQ.SRS-006.RBAC.Privileges.Sources.JDBC](#rqsrs-006rbacprivilegessourcesjdbc) - * 5.2.39.8 [RQ.SRS-006.RBAC.Privileges.Sources.HDFS](#rqsrs-006rbacprivilegessourceshdfs) - * 5.2.39.9 [RQ.SRS-006.RBAC.Privileges.Sources.S3](#rqsrs-006rbacprivilegessourcess3) - * 5.2.40 [RQ.SRS-006.RBAC.Privileges.GrantOption](#rqsrs-006rbacprivilegesgrantoption) - * 5.2.41 [RQ.SRS-006.RBAC.Privileges.All](#rqsrs-006rbacprivilegesall) - * 5.2.42 [RQ.SRS-006.RBAC.Privileges.AdminOption](#rqsrs-006rbacprivilegesadminoption) + * 5.2 [Login](#login) + * 5.2.1 [RQ.SRS-006.RBAC.Login](#rqsrs-006rbaclogin) + * 5.2.2 [RQ.SRS-006.RBAC.Login.DefaultUser](#rqsrs-006rbaclogindefaultuser) + * 5.3 [User](#user) + * 5.3.1 [RQ.SRS-006.RBAC.User](#rqsrs-006rbacuser) + * 5.3.2 [RQ.SRS-006.RBAC.User.Roles](#rqsrs-006rbacuserroles) + * 5.3.3 [RQ.SRS-006.RBAC.User.Privileges](#rqsrs-006rbacuserprivileges) + * 5.3.4 [RQ.SRS-006.RBAC.User.Variables](#rqsrs-006rbacuservariables) + * 5.3.5 [RQ.SRS-006.RBAC.User.Variables.Constraints](#rqsrs-006rbacuservariablesconstraints) + * 5.3.6 [RQ.SRS-006.RBAC.User.SettingsProfile](#rqsrs-006rbacusersettingsprofile) + * 5.3.7 [RQ.SRS-006.RBAC.User.Quotas](#rqsrs-006rbacuserquotas) + * 5.3.8 [RQ.SRS-006.RBAC.User.RowPolicies](#rqsrs-006rbacuserrowpolicies) + * 5.3.9 [RQ.SRS-006.RBAC.User.DefaultRole](#rqsrs-006rbacuserdefaultrole) + * 5.3.10 [RQ.SRS-006.RBAC.User.RoleSelection](#rqsrs-006rbacuserroleselection) + * 5.3.11 [RQ.SRS-006.RBAC.User.ShowCreate](#rqsrs-006rbacusershowcreate) + * 5.3.12 [RQ.SRS-006.RBAC.User.ShowPrivileges](#rqsrs-006rbacusershowprivileges) + * 5.3.13 [RQ.SRS-006.RBAC.User.Use.DefaultRole](#rqsrs-006rbacuserusedefaultrole) + * 5.3.14 [RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole](#rqsrs-006rbacuseruseallroleswhennodefaultrole) + * 5.3.15 [Create User](#create-user) + * 5.3.15.1 [RQ.SRS-006.RBAC.User.Create](#rqsrs-006rbacusercreate) + * 5.3.15.2 [RQ.SRS-006.RBAC.User.Create.IfNotExists](#rqsrs-006rbacusercreateifnotexists) + * 5.3.15.3 [RQ.SRS-006.RBAC.User.Create.Replace](#rqsrs-006rbacusercreatereplace) + * 5.3.15.4 [RQ.SRS-006.RBAC.User.Create.Password.NoPassword](#rqsrs-006rbacusercreatepasswordnopassword) + * 5.3.15.5 [RQ.SRS-006.RBAC.User.Create.Password.NoPassword.Login](#rqsrs-006rbacusercreatepasswordnopasswordlogin) + * 5.3.15.6 [RQ.SRS-006.RBAC.User.Create.Password.PlainText](#rqsrs-006rbacusercreatepasswordplaintext) + * 5.3.15.7 [RQ.SRS-006.RBAC.User.Create.Password.PlainText.Login](#rqsrs-006rbacusercreatepasswordplaintextlogin) + * 5.3.15.8 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Password](#rqsrs-006rbacusercreatepasswordsha256password) + * 5.3.15.9 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Password.Login](#rqsrs-006rbacusercreatepasswordsha256passwordlogin) + * 5.3.15.10 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash](#rqsrs-006rbacusercreatepasswordsha256hash) + * 5.3.15.11 [RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash.Login](#rqsrs-006rbacusercreatepasswordsha256hashlogin) + * 5.3.15.12 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password](#rqsrs-006rbacusercreatepassworddoublesha1password) + * 5.3.15.13 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password.Login](#rqsrs-006rbacusercreatepassworddoublesha1passwordlogin) + * 5.3.15.14 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash](#rqsrs-006rbacusercreatepassworddoublesha1hash) + * 5.3.15.15 [RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash.Login](#rqsrs-006rbacusercreatepassworddoublesha1hashlogin) + * 5.3.15.16 [RQ.SRS-006.RBAC.User.Create.Host.Name](#rqsrs-006rbacusercreatehostname) + * 5.3.15.17 [RQ.SRS-006.RBAC.User.Create.Host.Regexp](#rqsrs-006rbacusercreatehostregexp) + * 5.3.15.18 [RQ.SRS-006.RBAC.User.Create.Host.IP](#rqsrs-006rbacusercreatehostip) + * 5.3.15.19 [RQ.SRS-006.RBAC.User.Create.Host.Any](#rqsrs-006rbacusercreatehostany) + * 5.3.15.20 [RQ.SRS-006.RBAC.User.Create.Host.None](#rqsrs-006rbacusercreatehostnone) + * 5.3.15.21 [RQ.SRS-006.RBAC.User.Create.Host.Local](#rqsrs-006rbacusercreatehostlocal) + * 5.3.15.22 [RQ.SRS-006.RBAC.User.Create.Host.Like](#rqsrs-006rbacusercreatehostlike) + * 5.3.15.23 [RQ.SRS-006.RBAC.User.Create.Host.Default](#rqsrs-006rbacusercreatehostdefault) + * 5.3.15.24 [RQ.SRS-006.RBAC.User.Create.DefaultRole](#rqsrs-006rbacusercreatedefaultrole) + * 5.3.15.25 [RQ.SRS-006.RBAC.User.Create.DefaultRole.None](#rqsrs-006rbacusercreatedefaultrolenone) + * 5.3.15.26 [RQ.SRS-006.RBAC.User.Create.DefaultRole.All](#rqsrs-006rbacusercreatedefaultroleall) + * 5.3.15.27 [RQ.SRS-006.RBAC.User.Create.Settings](#rqsrs-006rbacusercreatesettings) + * 5.3.15.28 [RQ.SRS-006.RBAC.User.Create.OnCluster](#rqsrs-006rbacusercreateoncluster) + * 5.3.15.29 [RQ.SRS-006.RBAC.User.Create.Syntax](#rqsrs-006rbacusercreatesyntax) + * 5.3.16 [Alter User](#alter-user) + * 5.3.16.1 [RQ.SRS-006.RBAC.User.Alter](#rqsrs-006rbacuseralter) + * 5.3.16.2 [RQ.SRS-006.RBAC.User.Alter.OrderOfEvaluation](#rqsrs-006rbacuseralterorderofevaluation) + * 5.3.16.3 [RQ.SRS-006.RBAC.User.Alter.IfExists](#rqsrs-006rbacuseralterifexists) + * 5.3.16.4 [RQ.SRS-006.RBAC.User.Alter.Cluster](#rqsrs-006rbacuseraltercluster) + * 5.3.16.5 [RQ.SRS-006.RBAC.User.Alter.Rename](#rqsrs-006rbacuseralterrename) + * 5.3.16.6 [RQ.SRS-006.RBAC.User.Alter.Password.PlainText](#rqsrs-006rbacuseralterpasswordplaintext) + * 5.3.16.7 [RQ.SRS-006.RBAC.User.Alter.Password.Sha256Password](#rqsrs-006rbacuseralterpasswordsha256password) + * 5.3.16.8 [RQ.SRS-006.RBAC.User.Alter.Password.DoubleSha1Password](#rqsrs-006rbacuseralterpassworddoublesha1password) + * 5.3.16.9 [RQ.SRS-006.RBAC.User.Alter.Host.AddDrop](#rqsrs-006rbacuseralterhostadddrop) + * 5.3.16.10 [RQ.SRS-006.RBAC.User.Alter.Host.Local](#rqsrs-006rbacuseralterhostlocal) + * 5.3.16.11 [RQ.SRS-006.RBAC.User.Alter.Host.Name](#rqsrs-006rbacuseralterhostname) + * 5.3.16.12 [RQ.SRS-006.RBAC.User.Alter.Host.Regexp](#rqsrs-006rbacuseralterhostregexp) + * 5.3.16.13 [RQ.SRS-006.RBAC.User.Alter.Host.IP](#rqsrs-006rbacuseralterhostip) + * 5.3.16.14 [RQ.SRS-006.RBAC.User.Alter.Host.Like](#rqsrs-006rbacuseralterhostlike) + * 5.3.16.15 [RQ.SRS-006.RBAC.User.Alter.Host.Any](#rqsrs-006rbacuseralterhostany) + * 5.3.16.16 [RQ.SRS-006.RBAC.User.Alter.Host.None](#rqsrs-006rbacuseralterhostnone) + * 5.3.16.17 [RQ.SRS-006.RBAC.User.Alter.DefaultRole](#rqsrs-006rbacuseralterdefaultrole) + * 5.3.16.18 [RQ.SRS-006.RBAC.User.Alter.DefaultRole.All](#rqsrs-006rbacuseralterdefaultroleall) + * 5.3.16.19 [RQ.SRS-006.RBAC.User.Alter.DefaultRole.AllExcept](#rqsrs-006rbacuseralterdefaultroleallexcept) + * 5.3.16.20 [RQ.SRS-006.RBAC.User.Alter.Settings](#rqsrs-006rbacuseraltersettings) + * 5.3.16.21 [RQ.SRS-006.RBAC.User.Alter.Settings.Min](#rqsrs-006rbacuseraltersettingsmin) + * 5.3.16.22 [RQ.SRS-006.RBAC.User.Alter.Settings.Max](#rqsrs-006rbacuseraltersettingsmax) + * 5.3.16.23 [RQ.SRS-006.RBAC.User.Alter.Settings.Profile](#rqsrs-006rbacuseraltersettingsprofile) + * 5.3.16.24 [RQ.SRS-006.RBAC.User.Alter.Syntax](#rqsrs-006rbacuseraltersyntax) + * 5.3.17 [Show Create User](#show-create-user) + * 5.3.17.1 [RQ.SRS-006.RBAC.User.ShowCreateUser](#rqsrs-006rbacusershowcreateuser) + * 5.3.17.2 [RQ.SRS-006.RBAC.User.ShowCreateUser.For](#rqsrs-006rbacusershowcreateuserfor) + * 5.3.17.3 [RQ.SRS-006.RBAC.User.ShowCreateUser.Syntax](#rqsrs-006rbacusershowcreateusersyntax) + * 5.3.18 [Drop User](#drop-user) + * 5.3.18.1 [RQ.SRS-006.RBAC.User.Drop](#rqsrs-006rbacuserdrop) + * 5.3.18.2 [RQ.SRS-006.RBAC.User.Drop.IfExists](#rqsrs-006rbacuserdropifexists) + * 5.3.18.3 [RQ.SRS-006.RBAC.User.Drop.OnCluster](#rqsrs-006rbacuserdroponcluster) + * 5.3.18.4 [RQ.SRS-006.RBAC.User.Drop.Syntax](#rqsrs-006rbacuserdropsyntax) + * 5.4 [Role](#role) + * 5.4.1 [RQ.SRS-006.RBAC.Role](#rqsrs-006rbacrole) + * 5.4.2 [RQ.SRS-006.RBAC.Role.Privileges](#rqsrs-006rbacroleprivileges) + * 5.4.3 [RQ.SRS-006.RBAC.Role.Variables](#rqsrs-006rbacrolevariables) + * 5.4.4 [RQ.SRS-006.RBAC.Role.SettingsProfile](#rqsrs-006rbacrolesettingsprofile) + * 5.4.5 [RQ.SRS-006.RBAC.Role.Quotas](#rqsrs-006rbacrolequotas) + * 5.4.6 [RQ.SRS-006.RBAC.Role.RowPolicies](#rqsrs-006rbacrolerowpolicies) + * 5.4.7 [Create Role](#create-role) + * 5.4.7.1 [RQ.SRS-006.RBAC.Role.Create](#rqsrs-006rbacrolecreate) + * 5.4.7.2 [RQ.SRS-006.RBAC.Role.Create.IfNotExists](#rqsrs-006rbacrolecreateifnotexists) + * 5.4.7.3 [RQ.SRS-006.RBAC.Role.Create.Replace](#rqsrs-006rbacrolecreatereplace) + * 5.4.7.4 [RQ.SRS-006.RBAC.Role.Create.Settings](#rqsrs-006rbacrolecreatesettings) + * 5.4.7.5 [RQ.SRS-006.RBAC.Role.Create.Syntax](#rqsrs-006rbacrolecreatesyntax) + * 5.4.8 [Alter Role](#alter-role) + * 5.4.8.1 [RQ.SRS-006.RBAC.Role.Alter](#rqsrs-006rbacrolealter) + * 5.4.8.2 [RQ.SRS-006.RBAC.Role.Alter.IfExists](#rqsrs-006rbacrolealterifexists) + * 5.4.8.3 [RQ.SRS-006.RBAC.Role.Alter.Cluster](#rqsrs-006rbacrolealtercluster) + * 5.4.8.4 [RQ.SRS-006.RBAC.Role.Alter.Rename](#rqsrs-006rbacrolealterrename) + * 5.4.8.5 [RQ.SRS-006.RBAC.Role.Alter.Settings](#rqsrs-006rbacrolealtersettings) + * 5.4.8.6 [RQ.SRS-006.RBAC.Role.Alter.Syntax](#rqsrs-006rbacrolealtersyntax) + * 5.4.9 [Drop Role](#drop-role) + * 5.4.9.1 [RQ.SRS-006.RBAC.Role.Drop](#rqsrs-006rbacroledrop) + * 5.4.9.2 [RQ.SRS-006.RBAC.Role.Drop.IfExists](#rqsrs-006rbacroledropifexists) + * 5.4.9.3 [RQ.SRS-006.RBAC.Role.Drop.Cluster](#rqsrs-006rbacroledropcluster) + * 5.4.9.4 [RQ.SRS-006.RBAC.Role.Drop.Syntax](#rqsrs-006rbacroledropsyntax) + * 5.4.10 [Show Create Role](#show-create-role) + * 5.4.10.1 [RQ.SRS-006.RBAC.Role.ShowCreate](#rqsrs-006rbacroleshowcreate) + * 5.4.10.2 [RQ.SRS-006.RBAC.Role.ShowCreate.Syntax](#rqsrs-006rbacroleshowcreatesyntax) + * 5.5 [Partial Revokes](#partial-revokes) + * 5.5.1 [RQ.SRS-006.RBAC.PartialRevokes](#rqsrs-006rbacpartialrevokes) + * 5.5.2 [RQ.SRS-006.RBAC.PartialRevoke.Syntax](#rqsrs-006rbacpartialrevokesyntax) + * 5.6 [Settings Profile](#settings-profile) + * 5.6.1 [RQ.SRS-006.RBAC.SettingsProfile](#rqsrs-006rbacsettingsprofile) + * 5.6.2 [RQ.SRS-006.RBAC.SettingsProfile.Constraints](#rqsrs-006rbacsettingsprofileconstraints) + * 5.6.3 [Create Settings Profile](#create-settings-profile) + * 5.6.3.1 [RQ.SRS-006.RBAC.SettingsProfile.Create](#rqsrs-006rbacsettingsprofilecreate) + * 5.6.3.2 [RQ.SRS-006.RBAC.SettingsProfile.Create.IfNotExists](#rqsrs-006rbacsettingsprofilecreateifnotexists) + * 5.6.3.3 [RQ.SRS-006.RBAC.SettingsProfile.Create.Replace](#rqsrs-006rbacsettingsprofilecreatereplace) + * 5.6.3.4 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables](#rqsrs-006rbacsettingsprofilecreatevariables) + * 5.6.3.5 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Value](#rqsrs-006rbacsettingsprofilecreatevariablesvalue) + * 5.6.3.6 [RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Constraints](#rqsrs-006rbacsettingsprofilecreatevariablesconstraints) + * 5.6.3.7 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment](#rqsrs-006rbacsettingsprofilecreateassignment) + * 5.6.3.8 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.None](#rqsrs-006rbacsettingsprofilecreateassignmentnone) + * 5.6.3.9 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.All](#rqsrs-006rbacsettingsprofilecreateassignmentall) + * 5.6.3.10 [RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.AllExcept](#rqsrs-006rbacsettingsprofilecreateassignmentallexcept) + * 5.6.3.11 [RQ.SRS-006.RBAC.SettingsProfile.Create.Inherit](#rqsrs-006rbacsettingsprofilecreateinherit) + * 5.6.3.12 [RQ.SRS-006.RBAC.SettingsProfile.Create.OnCluster](#rqsrs-006rbacsettingsprofilecreateoncluster) + * 5.6.3.13 [RQ.SRS-006.RBAC.SettingsProfile.Create.Syntax](#rqsrs-006rbacsettingsprofilecreatesyntax) + * 5.6.4 [Alter Settings Profile](#alter-settings-profile) + * 5.6.4.1 [RQ.SRS-006.RBAC.SettingsProfile.Alter](#rqsrs-006rbacsettingsprofilealter) + * 5.6.4.2 [RQ.SRS-006.RBAC.SettingsProfile.Alter.IfExists](#rqsrs-006rbacsettingsprofilealterifexists) + * 5.6.4.3 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Rename](#rqsrs-006rbacsettingsprofilealterrename) + * 5.6.4.4 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables](#rqsrs-006rbacsettingsprofilealtervariables) + * 5.6.4.5 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Value](#rqsrs-006rbacsettingsprofilealtervariablesvalue) + * 5.6.4.6 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Constraints](#rqsrs-006rbacsettingsprofilealtervariablesconstraints) + * 5.6.4.7 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment](#rqsrs-006rbacsettingsprofilealterassignment) + * 5.6.4.8 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.None](#rqsrs-006rbacsettingsprofilealterassignmentnone) + * 5.6.4.9 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.All](#rqsrs-006rbacsettingsprofilealterassignmentall) + * 5.6.4.10 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.AllExcept](#rqsrs-006rbacsettingsprofilealterassignmentallexcept) + * 5.6.4.11 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.Inherit](#rqsrs-006rbacsettingsprofilealterassignmentinherit) + * 5.6.4.12 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.OnCluster](#rqsrs-006rbacsettingsprofilealterassignmentoncluster) + * 5.6.4.13 [RQ.SRS-006.RBAC.SettingsProfile.Alter.Syntax](#rqsrs-006rbacsettingsprofilealtersyntax) + * 5.6.5 [Drop Settings Profile](#drop-settings-profile) + * 5.6.5.1 [RQ.SRS-006.RBAC.SettingsProfile.Drop](#rqsrs-006rbacsettingsprofiledrop) + * 5.6.5.2 [RQ.SRS-006.RBAC.SettingsProfile.Drop.IfExists](#rqsrs-006rbacsettingsprofiledropifexists) + * 5.6.5.3 [RQ.SRS-006.RBAC.SettingsProfile.Drop.OnCluster](#rqsrs-006rbacsettingsprofiledroponcluster) + * 5.6.5.4 [RQ.SRS-006.RBAC.SettingsProfile.Drop.Syntax](#rqsrs-006rbacsettingsprofiledropsyntax) + * 5.6.6 [Show Create Settings Profile](#show-create-settings-profile) + * 5.6.6.1 [RQ.SRS-006.RBAC.SettingsProfile.ShowCreateSettingsProfile](#rqsrs-006rbacsettingsprofileshowcreatesettingsprofile) + * 5.7 [Quotas](#quotas) + * 5.7.1 [RQ.SRS-006.RBAC.Quotas](#rqsrs-006rbacquotas) + * 5.7.2 [RQ.SRS-006.RBAC.Quotas.Keyed](#rqsrs-006rbacquotaskeyed) + * 5.7.3 [RQ.SRS-006.RBAC.Quotas.Queries](#rqsrs-006rbacquotasqueries) + * 5.7.4 [RQ.SRS-006.RBAC.Quotas.Errors](#rqsrs-006rbacquotaserrors) + * 5.7.5 [RQ.SRS-006.RBAC.Quotas.ResultRows](#rqsrs-006rbacquotasresultrows) + * 5.7.6 [RQ.SRS-006.RBAC.Quotas.ReadRows](#rqsrs-006rbacquotasreadrows) + * 5.7.7 [RQ.SRS-006.RBAC.Quotas.ResultBytes](#rqsrs-006rbacquotasresultbytes) + * 5.7.8 [RQ.SRS-006.RBAC.Quotas.ReadBytes](#rqsrs-006rbacquotasreadbytes) + * 5.7.9 [RQ.SRS-006.RBAC.Quotas.ExecutionTime](#rqsrs-006rbacquotasexecutiontime) + * 5.7.10 [Create Quotas](#create-quotas) + * 5.7.10.1 [RQ.SRS-006.RBAC.Quota.Create](#rqsrs-006rbacquotacreate) + * 5.7.10.2 [RQ.SRS-006.RBAC.Quota.Create.IfNotExists](#rqsrs-006rbacquotacreateifnotexists) + * 5.7.10.3 [RQ.SRS-006.RBAC.Quota.Create.Replace](#rqsrs-006rbacquotacreatereplace) + * 5.7.10.4 [RQ.SRS-006.RBAC.Quota.Create.Cluster](#rqsrs-006rbacquotacreatecluster) + * 5.7.10.5 [RQ.SRS-006.RBAC.Quota.Create.Interval](#rqsrs-006rbacquotacreateinterval) + * 5.7.10.6 [RQ.SRS-006.RBAC.Quota.Create.Interval.Randomized](#rqsrs-006rbacquotacreateintervalrandomized) + * 5.7.10.7 [RQ.SRS-006.RBAC.Quota.Create.Queries](#rqsrs-006rbacquotacreatequeries) + * 5.7.10.8 [RQ.SRS-006.RBAC.Quota.Create.Errors](#rqsrs-006rbacquotacreateerrors) + * 5.7.10.9 [RQ.SRS-006.RBAC.Quota.Create.ResultRows](#rqsrs-006rbacquotacreateresultrows) + * 5.7.10.10 [RQ.SRS-006.RBAC.Quota.Create.ReadRows](#rqsrs-006rbacquotacreatereadrows) + * 5.7.10.11 [RQ.SRS-006.RBAC.Quota.Create.ResultBytes](#rqsrs-006rbacquotacreateresultbytes) + * 5.7.10.12 [RQ.SRS-006.RBAC.Quota.Create.ReadBytes](#rqsrs-006rbacquotacreatereadbytes) + * 5.7.10.13 [RQ.SRS-006.RBAC.Quota.Create.ExecutionTime](#rqsrs-006rbacquotacreateexecutiontime) + * 5.7.10.14 [RQ.SRS-006.RBAC.Quota.Create.NoLimits](#rqsrs-006rbacquotacreatenolimits) + * 5.7.10.15 [RQ.SRS-006.RBAC.Quota.Create.TrackingOnly](#rqsrs-006rbacquotacreatetrackingonly) + * 5.7.10.16 [RQ.SRS-006.RBAC.Quota.Create.KeyedBy](#rqsrs-006rbacquotacreatekeyedby) + * 5.7.10.17 [RQ.SRS-006.RBAC.Quota.Create.KeyedByOptions](#rqsrs-006rbacquotacreatekeyedbyoptions) + * 5.7.10.18 [RQ.SRS-006.RBAC.Quota.Create.Assignment](#rqsrs-006rbacquotacreateassignment) + * 5.7.10.19 [RQ.SRS-006.RBAC.Quota.Create.Assignment.None](#rqsrs-006rbacquotacreateassignmentnone) + * 5.7.10.20 [RQ.SRS-006.RBAC.Quota.Create.Assignment.All](#rqsrs-006rbacquotacreateassignmentall) + * 5.7.10.21 [RQ.SRS-006.RBAC.Quota.Create.Assignment.Except](#rqsrs-006rbacquotacreateassignmentexcept) + * 5.7.10.22 [RQ.SRS-006.RBAC.Quota.Create.Syntax](#rqsrs-006rbacquotacreatesyntax) + * 5.7.11 [Alter Quota](#alter-quota) + * 5.7.11.1 [RQ.SRS-006.RBAC.Quota.Alter](#rqsrs-006rbacquotaalter) + * 5.7.11.2 [RQ.SRS-006.RBAC.Quota.Alter.IfExists](#rqsrs-006rbacquotaalterifexists) + * 5.7.11.3 [RQ.SRS-006.RBAC.Quota.Alter.Rename](#rqsrs-006rbacquotaalterrename) + * 5.7.11.4 [RQ.SRS-006.RBAC.Quota.Alter.Cluster](#rqsrs-006rbacquotaaltercluster) + * 5.7.11.5 [RQ.SRS-006.RBAC.Quota.Alter.Interval](#rqsrs-006rbacquotaalterinterval) + * 5.7.11.6 [RQ.SRS-006.RBAC.Quota.Alter.Interval.Randomized](#rqsrs-006rbacquotaalterintervalrandomized) + * 5.7.11.7 [RQ.SRS-006.RBAC.Quota.Alter.Queries](#rqsrs-006rbacquotaalterqueries) + * 5.7.11.8 [RQ.SRS-006.RBAC.Quota.Alter.Errors](#rqsrs-006rbacquotaaltererrors) + * 5.7.11.9 [RQ.SRS-006.RBAC.Quota.Alter.ResultRows](#rqsrs-006rbacquotaalterresultrows) + * 5.7.11.10 [RQ.SRS-006.RBAC.Quota.Alter.ReadRows](#rqsrs-006rbacquotaalterreadrows) + * 5.7.11.11 [RQ.SRS-006.RBAC.Quota.ALter.ResultBytes](#rqsrs-006rbacquotaalterresultbytes) + * 5.7.11.12 [RQ.SRS-006.RBAC.Quota.Alter.ReadBytes](#rqsrs-006rbacquotaalterreadbytes) + * 5.7.11.13 [RQ.SRS-006.RBAC.Quota.Alter.ExecutionTime](#rqsrs-006rbacquotaalterexecutiontime) + * 5.7.11.14 [RQ.SRS-006.RBAC.Quota.Alter.NoLimits](#rqsrs-006rbacquotaalternolimits) + * 5.7.11.15 [RQ.SRS-006.RBAC.Quota.Alter.TrackingOnly](#rqsrs-006rbacquotaaltertrackingonly) + * 5.7.11.16 [RQ.SRS-006.RBAC.Quota.Alter.KeyedBy](#rqsrs-006rbacquotaalterkeyedby) + * 5.7.11.17 [RQ.SRS-006.RBAC.Quota.Alter.KeyedByOptions](#rqsrs-006rbacquotaalterkeyedbyoptions) + * 5.7.11.18 [RQ.SRS-006.RBAC.Quota.Alter.Assignment](#rqsrs-006rbacquotaalterassignment) + * 5.7.11.19 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.None](#rqsrs-006rbacquotaalterassignmentnone) + * 5.7.11.20 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.All](#rqsrs-006rbacquotaalterassignmentall) + * 5.7.11.21 [RQ.SRS-006.RBAC.Quota.Alter.Assignment.Except](#rqsrs-006rbacquotaalterassignmentexcept) + * 5.7.11.22 [RQ.SRS-006.RBAC.Quota.Alter.Syntax](#rqsrs-006rbacquotaaltersyntax) + * 5.7.12 [Drop Quota](#drop-quota) + * 5.7.12.1 [RQ.SRS-006.RBAC.Quota.Drop](#rqsrs-006rbacquotadrop) + * 5.7.12.2 [RQ.SRS-006.RBAC.Quota.Drop.IfExists](#rqsrs-006rbacquotadropifexists) + * 5.7.12.3 [RQ.SRS-006.RBAC.Quota.Drop.Cluster](#rqsrs-006rbacquotadropcluster) + * 5.7.12.4 [RQ.SRS-006.RBAC.Quota.Drop.Syntax](#rqsrs-006rbacquotadropsyntax) + * 5.7.13 [Show Quotas](#show-quotas) + * 5.7.13.1 [RQ.SRS-006.RBAC.Quota.ShowQuotas](#rqsrs-006rbacquotashowquotas) + * 5.7.13.2 [RQ.SRS-006.RBAC.Quota.ShowQuotas.IntoOutfile](#rqsrs-006rbacquotashowquotasintooutfile) + * 5.7.13.3 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Format](#rqsrs-006rbacquotashowquotasformat) + * 5.7.13.4 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Settings](#rqsrs-006rbacquotashowquotassettings) + * 5.7.13.5 [RQ.SRS-006.RBAC.Quota.ShowQuotas.Syntax](#rqsrs-006rbacquotashowquotassyntax) + * 5.7.14 [Show Create Quota](#show-create-quota) + * 5.7.14.1 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Name](#rqsrs-006rbacquotashowcreatequotaname) + * 5.7.14.2 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Current](#rqsrs-006rbacquotashowcreatequotacurrent) + * 5.7.14.3 [RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Syntax](#rqsrs-006rbacquotashowcreatequotasyntax) + * 5.8 [Row Policy](#row-policy) + * 5.8.1 [RQ.SRS-006.RBAC.RowPolicy](#rqsrs-006rbacrowpolicy) + * 5.8.2 [RQ.SRS-006.RBAC.RowPolicy.Condition](#rqsrs-006rbacrowpolicycondition) + * 5.8.3 [RQ.SRS-006.RBAC.RowPolicy.Restriction](#rqsrs-006rbacrowpolicyrestriction) + * 5.8.4 [RQ.SRS-006.RBAC.RowPolicy.Nesting](#rqsrs-006rbacrowpolicynesting) + * 5.8.5 [Create Row Policy](#create-row-policy) + * 5.8.5.1 [RQ.SRS-006.RBAC.RowPolicy.Create](#rqsrs-006rbacrowpolicycreate) + * 5.8.5.2 [RQ.SRS-006.RBAC.RowPolicy.Create.IfNotExists](#rqsrs-006rbacrowpolicycreateifnotexists) + * 5.8.5.3 [RQ.SRS-006.RBAC.RowPolicy.Create.Replace](#rqsrs-006rbacrowpolicycreatereplace) + * 5.8.5.4 [RQ.SRS-006.RBAC.RowPolicy.Create.OnCluster](#rqsrs-006rbacrowpolicycreateoncluster) + * 5.8.5.5 [RQ.SRS-006.RBAC.RowPolicy.Create.On](#rqsrs-006rbacrowpolicycreateon) + * 5.8.5.6 [RQ.SRS-006.RBAC.RowPolicy.Create.Access](#rqsrs-006rbacrowpolicycreateaccess) + * 5.8.5.7 [RQ.SRS-006.RBAC.RowPolicy.Create.Access.Permissive](#rqsrs-006rbacrowpolicycreateaccesspermissive) + * 5.8.5.8 [RQ.SRS-006.RBAC.RowPolicy.Create.Access.Restrictive](#rqsrs-006rbacrowpolicycreateaccessrestrictive) + * 5.8.5.9 [RQ.SRS-006.RBAC.RowPolicy.Create.ForSelect](#rqsrs-006rbacrowpolicycreateforselect) + * 5.8.5.10 [RQ.SRS-006.RBAC.RowPolicy.Create.Condition](#rqsrs-006rbacrowpolicycreatecondition) + * 5.8.5.11 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment](#rqsrs-006rbacrowpolicycreateassignment) + * 5.8.5.12 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.None](#rqsrs-006rbacrowpolicycreateassignmentnone) + * 5.8.5.13 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.All](#rqsrs-006rbacrowpolicycreateassignmentall) + * 5.8.5.14 [RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.AllExcept](#rqsrs-006rbacrowpolicycreateassignmentallexcept) + * 5.8.5.15 [RQ.SRS-006.RBAC.RowPolicy.Create.Syntax](#rqsrs-006rbacrowpolicycreatesyntax) + * 5.8.6 [Alter Row Policy](#alter-row-policy) + * 5.8.6.1 [RQ.SRS-006.RBAC.RowPolicy.Alter](#rqsrs-006rbacrowpolicyalter) + * 5.8.6.2 [RQ.SRS-006.RBAC.RowPolicy.Alter.IfExists](#rqsrs-006rbacrowpolicyalterifexists) + * 5.8.6.3 [RQ.SRS-006.RBAC.RowPolicy.Alter.ForSelect](#rqsrs-006rbacrowpolicyalterforselect) + * 5.8.6.4 [RQ.SRS-006.RBAC.RowPolicy.Alter.OnCluster](#rqsrs-006rbacrowpolicyalteroncluster) + * 5.8.6.5 [RQ.SRS-006.RBAC.RowPolicy.Alter.On](#rqsrs-006rbacrowpolicyalteron) + * 5.8.6.6 [RQ.SRS-006.RBAC.RowPolicy.Alter.Rename](#rqsrs-006rbacrowpolicyalterrename) + * 5.8.6.7 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access](#rqsrs-006rbacrowpolicyalteraccess) + * 5.8.6.8 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Permissive](#rqsrs-006rbacrowpolicyalteraccesspermissive) + * 5.8.6.9 [RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Restrictive](#rqsrs-006rbacrowpolicyalteraccessrestrictive) + * 5.8.6.10 [RQ.SRS-006.RBAC.RowPolicy.Alter.Condition](#rqsrs-006rbacrowpolicyaltercondition) + * 5.8.6.11 [RQ.SRS-006.RBAC.RowPolicy.Alter.Condition.None](#rqsrs-006rbacrowpolicyalterconditionnone) + * 5.8.6.12 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment](#rqsrs-006rbacrowpolicyalterassignment) + * 5.8.6.13 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.None](#rqsrs-006rbacrowpolicyalterassignmentnone) + * 5.8.6.14 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.All](#rqsrs-006rbacrowpolicyalterassignmentall) + * 5.8.6.15 [RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.AllExcept](#rqsrs-006rbacrowpolicyalterassignmentallexcept) + * 5.8.6.16 [RQ.SRS-006.RBAC.RowPolicy.Alter.Syntax](#rqsrs-006rbacrowpolicyaltersyntax) + * 5.8.7 [Drop Row Policy](#drop-row-policy) + * 5.8.7.1 [RQ.SRS-006.RBAC.RowPolicy.Drop](#rqsrs-006rbacrowpolicydrop) + * 5.8.7.2 [RQ.SRS-006.RBAC.RowPolicy.Drop.IfExists](#rqsrs-006rbacrowpolicydropifexists) + * 5.8.7.3 [RQ.SRS-006.RBAC.RowPolicy.Drop.On](#rqsrs-006rbacrowpolicydropon) + * 5.8.7.4 [RQ.SRS-006.RBAC.RowPolicy.Drop.OnCluster](#rqsrs-006rbacrowpolicydroponcluster) + * 5.8.7.5 [RQ.SRS-006.RBAC.RowPolicy.Drop.Syntax](#rqsrs-006rbacrowpolicydropsyntax) + * 5.8.8 [Show Create Row Policy](#show-create-row-policy) + * 5.8.8.1 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy](#rqsrs-006rbacrowpolicyshowcreaterowpolicy) + * 5.8.8.2 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.On](#rqsrs-006rbacrowpolicyshowcreaterowpolicyon) + * 5.8.8.3 [RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.Syntax](#rqsrs-006rbacrowpolicyshowcreaterowpolicysyntax) + * 5.8.8.4 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies](#rqsrs-006rbacrowpolicyshowrowpolicies) + * 5.8.8.5 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.On](#rqsrs-006rbacrowpolicyshowrowpolicieson) + * 5.8.8.6 [RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.Syntax](#rqsrs-006rbacrowpolicyshowrowpoliciessyntax) + * 5.9 [Set Default Role](#set-default-role) + * 5.9.1 [RQ.SRS-006.RBAC.SetDefaultRole](#rqsrs-006rbacsetdefaultrole) + * 5.9.2 [RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser](#rqsrs-006rbacsetdefaultrolecurrentuser) + * 5.9.3 [RQ.SRS-006.RBAC.SetDefaultRole.All](#rqsrs-006rbacsetdefaultroleall) + * 5.9.4 [RQ.SRS-006.RBAC.SetDefaultRole.AllExcept](#rqsrs-006rbacsetdefaultroleallexcept) + * 5.9.5 [RQ.SRS-006.RBAC.SetDefaultRole.None](#rqsrs-006rbacsetdefaultrolenone) + * 5.9.6 [RQ.SRS-006.RBAC.SetDefaultRole.Syntax](#rqsrs-006rbacsetdefaultrolesyntax) + * 5.10 [Set Role](#set-role) + * 5.10.1 [RQ.SRS-006.RBAC.SetRole](#rqsrs-006rbacsetrole) + * 5.10.2 [RQ.SRS-006.RBAC.SetRole.Default](#rqsrs-006rbacsetroledefault) + * 5.10.3 [RQ.SRS-006.RBAC.SetRole.None](#rqsrs-006rbacsetrolenone) + * 5.10.4 [RQ.SRS-006.RBAC.SetRole.All](#rqsrs-006rbacsetroleall) + * 5.10.5 [RQ.SRS-006.RBAC.SetRole.AllExcept](#rqsrs-006rbacsetroleallexcept) + * 5.10.6 [RQ.SRS-006.RBAC.SetRole.Syntax](#rqsrs-006rbacsetrolesyntax) + * 5.11 [Grant](#grant) + * 5.11.1 [RQ.SRS-006.RBAC.Grant.Privilege.To](#rqsrs-006rbacgrantprivilegeto) + * 5.11.2 [RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser](#rqsrs-006rbacgrantprivilegetocurrentuser) + * 5.11.3 [RQ.SRS-006.RBAC.Grant.Privilege.Select](#rqsrs-006rbacgrantprivilegeselect) + * 5.11.4 [RQ.SRS-006.RBAC.Grant.Privilege.Insert](#rqsrs-006rbacgrantprivilegeinsert) + * 5.11.5 [RQ.SRS-006.RBAC.Grant.Privilege.Alter](#rqsrs-006rbacgrantprivilegealter) + * 5.11.6 [RQ.SRS-006.RBAC.Grant.Privilege.Create](#rqsrs-006rbacgrantprivilegecreate) + * 5.11.7 [RQ.SRS-006.RBAC.Grant.Privilege.Drop](#rqsrs-006rbacgrantprivilegedrop) + * 5.11.8 [RQ.SRS-006.RBAC.Grant.Privilege.Truncate](#rqsrs-006rbacgrantprivilegetruncate) + * 5.11.9 [RQ.SRS-006.RBAC.Grant.Privilege.Optimize](#rqsrs-006rbacgrantprivilegeoptimize) + * 5.11.10 [RQ.SRS-006.RBAC.Grant.Privilege.Show](#rqsrs-006rbacgrantprivilegeshow) + * 5.11.11 [RQ.SRS-006.RBAC.Grant.Privilege.KillQuery](#rqsrs-006rbacgrantprivilegekillquery) + * 5.11.12 [RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement](#rqsrs-006rbacgrantprivilegeaccessmanagement) + * 5.11.13 [RQ.SRS-006.RBAC.Grant.Privilege.System](#rqsrs-006rbacgrantprivilegesystem) + * 5.11.14 [RQ.SRS-006.RBAC.Grant.Privilege.Introspection](#rqsrs-006rbacgrantprivilegeintrospection) + * 5.11.15 [RQ.SRS-006.RBAC.Grant.Privilege.Sources](#rqsrs-006rbacgrantprivilegesources) + * 5.11.16 [RQ.SRS-006.RBAC.Grant.Privilege.DictGet](#rqsrs-006rbacgrantprivilegedictget) + * 5.11.17 [RQ.SRS-006.RBAC.Grant.Privilege.None](#rqsrs-006rbacgrantprivilegenone) + * 5.11.18 [RQ.SRS-006.RBAC.Grant.Privilege.All](#rqsrs-006rbacgrantprivilegeall) + * 5.11.19 [RQ.SRS-006.RBAC.Grant.Privilege.GrantOption](#rqsrs-006rbacgrantprivilegegrantoption) + * 5.11.20 [RQ.SRS-006.RBAC.Grant.Privilege.On](#rqsrs-006rbacgrantprivilegeon) + * 5.11.21 [RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns](#rqsrs-006rbacgrantprivilegeprivilegecolumns) + * 5.11.22 [RQ.SRS-006.RBAC.Grant.Privilege.OnCluster](#rqsrs-006rbacgrantprivilegeoncluster) + * 5.11.23 [RQ.SRS-006.RBAC.Grant.Privilege.Syntax](#rqsrs-006rbacgrantprivilegesyntax) + * 5.12 [Revoke](#revoke) + * 5.12.1 [RQ.SRS-006.RBAC.Revoke.Privilege.Cluster](#rqsrs-006rbacrevokeprivilegecluster) + * 5.12.2 [RQ.SRS-006.RBAC.Revoke.Privilege.Select](#rqsrs-006rbacrevokeprivilegeselect) + * 5.12.3 [RQ.SRS-006.RBAC.Revoke.Privilege.Insert](#rqsrs-006rbacrevokeprivilegeinsert) + * 5.12.4 [RQ.SRS-006.RBAC.Revoke.Privilege.Alter](#rqsrs-006rbacrevokeprivilegealter) + * 5.12.5 [RQ.SRS-006.RBAC.Revoke.Privilege.Create](#rqsrs-006rbacrevokeprivilegecreate) + * 5.12.6 [RQ.SRS-006.RBAC.Revoke.Privilege.Drop](#rqsrs-006rbacrevokeprivilegedrop) + * 5.12.7 [RQ.SRS-006.RBAC.Revoke.Privilege.Truncate](#rqsrs-006rbacrevokeprivilegetruncate) + * 5.12.8 [RQ.SRS-006.RBAC.Revoke.Privilege.Optimize](#rqsrs-006rbacrevokeprivilegeoptimize) + * 5.12.9 [RQ.SRS-006.RBAC.Revoke.Privilege.Show](#rqsrs-006rbacrevokeprivilegeshow) + * 5.12.10 [RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery](#rqsrs-006rbacrevokeprivilegekillquery) + * 5.12.11 [RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement](#rqsrs-006rbacrevokeprivilegeaccessmanagement) + * 5.12.12 [RQ.SRS-006.RBAC.Revoke.Privilege.System](#rqsrs-006rbacrevokeprivilegesystem) + * 5.12.13 [RQ.SRS-006.RBAC.Revoke.Privilege.Introspection](#rqsrs-006rbacrevokeprivilegeintrospection) + * 5.12.14 [RQ.SRS-006.RBAC.Revoke.Privilege.Sources](#rqsrs-006rbacrevokeprivilegesources) + * 5.12.15 [RQ.SRS-006.RBAC.Revoke.Privilege.DictGet](#rqsrs-006rbacrevokeprivilegedictget) + * 5.12.16 [RQ.SRS-006.RBAC.Revoke.Privilege.PrivilegeColumns](#rqsrs-006rbacrevokeprivilegeprivilegecolumns) + * 5.12.17 [RQ.SRS-006.RBAC.Revoke.Privilege.Multiple](#rqsrs-006rbacrevokeprivilegemultiple) + * 5.12.18 [RQ.SRS-006.RBAC.Revoke.Privilege.All](#rqsrs-006rbacrevokeprivilegeall) + * 5.12.19 [RQ.SRS-006.RBAC.Revoke.Privilege.None](#rqsrs-006rbacrevokeprivilegenone) + * 5.12.20 [RQ.SRS-006.RBAC.Revoke.Privilege.On](#rqsrs-006rbacrevokeprivilegeon) + * 5.12.21 [RQ.SRS-006.RBAC.Revoke.Privilege.From](#rqsrs-006rbacrevokeprivilegefrom) + * 5.12.22 [RQ.SRS-006.RBAC.Revoke.Privilege.Syntax](#rqsrs-006rbacrevokeprivilegesyntax) + * 5.13 [Grant Role](#grant-role) + * 5.13.1 [RQ.SRS-006.RBAC.Grant.Role](#rqsrs-006rbacgrantrole) + * 5.13.2 [RQ.SRS-006.RBAC.Grant.Role.CurrentUser](#rqsrs-006rbacgrantrolecurrentuser) + * 5.13.3 [RQ.SRS-006.RBAC.Grant.Role.AdminOption](#rqsrs-006rbacgrantroleadminoption) + * 5.13.4 [RQ.SRS-006.RBAC.Grant.Role.OnCluster](#rqsrs-006rbacgrantroleoncluster) + * 5.13.5 [RQ.SRS-006.RBAC.Grant.Role.Syntax](#rqsrs-006rbacgrantrolesyntax) + * 5.14 [Revoke Role](#revoke-role) + * 5.14.1 [RQ.SRS-006.RBAC.Revoke.Role](#rqsrs-006rbacrevokerole) + * 5.14.2 [RQ.SRS-006.RBAC.Revoke.Role.Keywords](#rqsrs-006rbacrevokerolekeywords) + * 5.14.3 [RQ.SRS-006.RBAC.Revoke.Role.Cluster](#rqsrs-006rbacrevokerolecluster) + * 5.14.4 [RQ.SRS-006.RBAC.Revoke.AdminOption](#rqsrs-006rbacrevokeadminoption) + * 5.14.5 [RQ.SRS-006.RBAC.Revoke.Role.Syntax](#rqsrs-006rbacrevokerolesyntax) + * 5.15 [Show Grants](#show-grants) + * 5.15.1 [RQ.SRS-006.RBAC.Show.Grants](#rqsrs-006rbacshowgrants) + * 5.15.2 [RQ.SRS-006.RBAC.Show.Grants.For](#rqsrs-006rbacshowgrantsfor) + * 5.15.3 [RQ.SRS-006.RBAC.Show.Grants.Syntax](#rqsrs-006rbacshowgrantssyntax) + * 5.16 [Table Privileges](#table-privileges) + * 5.16.1 [RQ.SRS-006.RBAC.Table.PublicTables](#rqsrs-006rbactablepublictables) + * 5.16.2 [RQ.SRS-006.RBAC.Table.SensitiveTables](#rqsrs-006rbactablesensitivetables) + * 5.17 [Distributed Tables](#distributed-tables) + * 5.17.1 [RQ.SRS-006.RBAC.DistributedTable.Create](#rqsrs-006rbacdistributedtablecreate) + * 5.17.2 [RQ.SRS-006.RBAC.DistributedTable.Select](#rqsrs-006rbacdistributedtableselect) + * 5.17.3 [RQ.SRS-006.RBAC.DistributedTable.Insert](#rqsrs-006rbacdistributedtableinsert) + * 5.17.4 [RQ.SRS-006.RBAC.DistributedTable.SpecialTables](#rqsrs-006rbacdistributedtablespecialtables) + * 5.17.5 [RQ.SRS-006.RBAC.DistributedTable.LocalUser](#rqsrs-006rbacdistributedtablelocaluser) + * 5.17.6 [RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges](#rqsrs-006rbacdistributedtablesameuserdifferentnodesdifferentprivileges) + * 5.18 [Views](#views) + * 5.18.1 [View](#view) + * 5.18.1.1 [RQ.SRS-006.RBAC.View](#rqsrs-006rbacview) + * 5.18.1.2 [RQ.SRS-006.RBAC.View.Create](#rqsrs-006rbacviewcreate) + * 5.18.1.3 [RQ.SRS-006.RBAC.View.Select](#rqsrs-006rbacviewselect) + * 5.18.1.4 [RQ.SRS-006.RBAC.View.Drop](#rqsrs-006rbacviewdrop) + * 5.18.2 [Materialized View](#materialized-view) + * 5.18.2.1 [RQ.SRS-006.RBAC.MaterializedView](#rqsrs-006rbacmaterializedview) + * 5.18.2.2 [RQ.SRS-006.RBAC.MaterializedView.Create](#rqsrs-006rbacmaterializedviewcreate) + * 5.18.2.3 [RQ.SRS-006.RBAC.MaterializedView.Select](#rqsrs-006rbacmaterializedviewselect) + * 5.18.2.4 [RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable](#rqsrs-006rbacmaterializedviewselecttargettable) + * 5.18.2.5 [RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable](#rqsrs-006rbacmaterializedviewselectsourcetable) + * 5.18.2.6 [RQ.SRS-006.RBAC.MaterializedView.Drop](#rqsrs-006rbacmaterializedviewdrop) + * 5.18.2.7 [RQ.SRS-006.RBAC.MaterializedView.ModifyQuery](#rqsrs-006rbacmaterializedviewmodifyquery) + * 5.18.2.8 [RQ.SRS-006.RBAC.MaterializedView.Insert](#rqsrs-006rbacmaterializedviewinsert) + * 5.18.2.9 [RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable](#rqsrs-006rbacmaterializedviewinsertsourcetable) + * 5.18.2.10 [RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable](#rqsrs-006rbacmaterializedviewinserttargettable) + * 5.18.3 [Live View](#live-view) + * 5.18.3.1 [RQ.SRS-006.RBAC.LiveView](#rqsrs-006rbacliveview) + * 5.18.3.2 [RQ.SRS-006.RBAC.LiveView.Create](#rqsrs-006rbacliveviewcreate) + * 5.18.3.3 [RQ.SRS-006.RBAC.LiveView.Select](#rqsrs-006rbacliveviewselect) + * 5.18.3.4 [RQ.SRS-006.RBAC.LiveView.Drop](#rqsrs-006rbacliveviewdrop) + * 5.18.3.5 [RQ.SRS-006.RBAC.LiveView.Refresh](#rqsrs-006rbacliveviewrefresh) + * 5.19 [Select](#select) + * 5.19.1 [RQ.SRS-006.RBAC.Select](#rqsrs-006rbacselect) + * 5.19.2 [RQ.SRS-006.RBAC.Select.Column](#rqsrs-006rbacselectcolumn) + * 5.19.3 [RQ.SRS-006.RBAC.Select.Cluster](#rqsrs-006rbacselectcluster) + * 5.19.4 [RQ.SRS-006.RBAC.Select.TableEngines](#rqsrs-006rbacselecttableengines) + * 5.20 [Insert](#insert) + * 5.20.1 [RQ.SRS-006.RBAC.Insert](#rqsrs-006rbacinsert) + * 5.20.2 [RQ.SRS-006.RBAC.Insert.Column](#rqsrs-006rbacinsertcolumn) + * 5.20.3 [RQ.SRS-006.RBAC.Insert.Cluster](#rqsrs-006rbacinsertcluster) + * 5.20.4 [RQ.SRS-006.RBAC.Insert.TableEngines](#rqsrs-006rbacinserttableengines) + * 5.21 [Alter](#alter) + * 5.21.1 [Alter Column](#alter-column) + * 5.21.1.1 [RQ.SRS-006.RBAC.Privileges.AlterColumn](#rqsrs-006rbacprivilegesaltercolumn) + * 5.21.1.2 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant](#rqsrs-006rbacprivilegesaltercolumngrant) + * 5.21.1.3 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke](#rqsrs-006rbacprivilegesaltercolumnrevoke) + * 5.21.1.4 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Column](#rqsrs-006rbacprivilegesaltercolumncolumn) + * 5.21.1.5 [RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster](#rqsrs-006rbacprivilegesaltercolumncluster) + * 5.21.1.6 [RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines](#rqsrs-006rbacprivilegesaltercolumntableengines) + * 5.21.2 [Alter Index](#alter-index) + * 5.21.2.1 [RQ.SRS-006.RBAC.Privileges.AlterIndex](#rqsrs-006rbacprivilegesalterindex) + * 5.21.2.2 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant](#rqsrs-006rbacprivilegesalterindexgrant) + * 5.21.2.3 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke](#rqsrs-006rbacprivilegesalterindexrevoke) + * 5.21.2.4 [RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster](#rqsrs-006rbacprivilegesalterindexcluster) + * 5.21.2.5 [RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines](#rqsrs-006rbacprivilegesalterindextableengines) + * 5.21.3 [Alter Constraint](#alter-constraint) + * 5.21.3.1 [RQ.SRS-006.RBAC.Privileges.AlterConstraint](#rqsrs-006rbacprivilegesalterconstraint) + * 5.21.3.2 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant](#rqsrs-006rbacprivilegesalterconstraintgrant) + * 5.21.3.3 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke](#rqsrs-006rbacprivilegesalterconstraintrevoke) + * 5.21.3.4 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster](#rqsrs-006rbacprivilegesalterconstraintcluster) + * 5.21.3.5 [RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines](#rqsrs-006rbacprivilegesalterconstrainttableengines) + * 5.21.4 [Alter TTL](#alter-ttl) + * 5.21.4.1 [RQ.SRS-006.RBAC.Privileges.AlterTTL](#rqsrs-006rbacprivilegesalterttl) + * 5.21.4.2 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant](#rqsrs-006rbacprivilegesalterttlgrant) + * 5.21.4.3 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke](#rqsrs-006rbacprivilegesalterttlrevoke) + * 5.21.4.4 [RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster](#rqsrs-006rbacprivilegesalterttlcluster) + * 5.21.4.5 [RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines](#rqsrs-006rbacprivilegesalterttltableengines) + * 5.21.5 [Alter Settings](#alter-settings) + * 5.21.5.1 [RQ.SRS-006.RBAC.Privileges.AlterSettings](#rqsrs-006rbacprivilegesaltersettings) + * 5.21.5.2 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant](#rqsrs-006rbacprivilegesaltersettingsgrant) + * 5.21.5.3 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke](#rqsrs-006rbacprivilegesaltersettingsrevoke) + * 5.21.5.4 [RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster](#rqsrs-006rbacprivilegesaltersettingscluster) + * 5.21.5.5 [RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines](#rqsrs-006rbacprivilegesaltersettingstableengines) + * 5.21.6 [Alter Update](#alter-update) + * 5.21.6.1 [RQ.SRS-006.RBAC.Privileges.AlterUpdate](#rqsrs-006rbacprivilegesalterupdate) + * 5.21.6.2 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant](#rqsrs-006rbacprivilegesalterupdategrant) + * 5.21.6.3 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke](#rqsrs-006rbacprivilegesalterupdaterevoke) + * 5.21.6.4 [RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines](#rqsrs-006rbacprivilegesalterupdatetableengines) + * 5.21.7 [Alter Delete](#alter-delete) + * 5.21.7.1 [RQ.SRS-006.RBAC.Privileges.AlterDelete](#rqsrs-006rbacprivilegesalterdelete) + * 5.21.7.2 [RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant](#rqsrs-006rbacprivilegesalterdeletegrant) + * 5.21.7.3 [RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke](#rqsrs-006rbacprivilegesalterdeleterevoke) + * 5.21.7.4 [RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines](#rqsrs-006rbacprivilegesalterdeletetableengines) + * 5.21.8 [Alter Freeze Partition](#alter-freeze-partition) + * 5.21.8.1 [RQ.SRS-006.RBAC.Privileges.AlterFreeze](#rqsrs-006rbacprivilegesalterfreeze) + * 5.21.8.2 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant](#rqsrs-006rbacprivilegesalterfreezegrant) + * 5.21.8.3 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke](#rqsrs-006rbacprivilegesalterfreezerevoke) + * 5.21.8.4 [RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines](#rqsrs-006rbacprivilegesalterfreezetableengines) + * 5.21.9 [Alter Fetch Partition](#alter-fetch-partition) + * 5.21.9.1 [RQ.SRS-006.RBAC.Privileges.AlterFetch](#rqsrs-006rbacprivilegesalterfetch) + * 5.21.9.2 [RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant](#rqsrs-006rbacprivilegesalterfetchgrant) + * 5.21.9.3 [RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke](#rqsrs-006rbacprivilegesalterfetchrevoke) + * 5.21.9.4 [RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines](#rqsrs-006rbacprivilegesalterfetchtableengines) + * 5.21.10 [Alter Move Partition](#alter-move-partition) + * 5.21.10.1 [RQ.SRS-006.RBAC.Privileges.AlterMove](#rqsrs-006rbacprivilegesaltermove) + * 5.21.10.2 [RQ.SRS-006.RBAC.Privileges.AlterMove.Grant](#rqsrs-006rbacprivilegesaltermovegrant) + * 5.21.10.3 [RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke](#rqsrs-006rbacprivilegesaltermoverevoke) + * 5.21.10.4 [RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines](#rqsrs-006rbacprivilegesaltermovetableengines) + * 5.22 [Create](#create) + * 5.22.1 [RQ.SRS-006.RBAC.Privileges.CreateTable](#rqsrs-006rbacprivilegescreatetable) + * 5.22.2 [RQ.SRS-006.RBAC.Privileges.CreateDatabase](#rqsrs-006rbacprivilegescreatedatabase) + * 5.22.3 [RQ.SRS-006.RBAC.Privileges.CreateDictionary](#rqsrs-006rbacprivilegescreatedictionary) + * 5.22.4 [RQ.SRS-006.RBAC.Privileges.CreateTemporaryTable](#rqsrs-006rbacprivilegescreatetemporarytable) + * 5.23 [Attach](#attach) + * 5.23.1 [RQ.SRS-006.RBAC.Privileges.AttachDatabase](#rqsrs-006rbacprivilegesattachdatabase) + * 5.23.2 [RQ.SRS-006.RBAC.Privileges.AttachDictionary](#rqsrs-006rbacprivilegesattachdictionary) + * 5.23.3 [RQ.SRS-006.RBAC.Privileges.AttachTemporaryTable](#rqsrs-006rbacprivilegesattachtemporarytable) + * 5.23.4 [RQ.SRS-006.RBAC.Privileges.AttachTable](#rqsrs-006rbacprivilegesattachtable) + * 5.24 [Drop](#drop) + * 5.24.1 [RQ.SRS-006.RBAC.Privileges.DropTable](#rqsrs-006rbacprivilegesdroptable) + * 5.24.2 [RQ.SRS-006.RBAC.Privileges.DropDatabase](#rqsrs-006rbacprivilegesdropdatabase) + * 5.24.3 [RQ.SRS-006.RBAC.Privileges.DropDictionary](#rqsrs-006rbacprivilegesdropdictionary) + * 5.25 [Detach](#detach) + * 5.25.1 [RQ.SRS-006.RBAC.Privileges.DetachTable](#rqsrs-006rbacprivilegesdetachtable) + * 5.25.2 [RQ.SRS-006.RBAC.Privileges.DetachView](#rqsrs-006rbacprivilegesdetachview) + * 5.25.3 [RQ.SRS-006.RBAC.Privileges.DetachDatabase](#rqsrs-006rbacprivilegesdetachdatabase) + * 5.25.4 [RQ.SRS-006.RBAC.Privileges.DetachDictionary](#rqsrs-006rbacprivilegesdetachdictionary) + * 5.26 [Truncate](#truncate) + * 5.26.1 [RQ.SRS-006.RBAC.Privileges.Truncate](#rqsrs-006rbacprivilegestruncate) + * 5.27 [Optimize](#optimize) + * 5.27.1 [RQ.SRS-006.RBAC.Privileges.Optimize](#rqsrs-006rbacprivilegesoptimize) + * 5.28 [Kill Query](#kill-query) + * 5.28.1 [RQ.SRS-006.RBAC.Privileges.KillQuery](#rqsrs-006rbacprivilegeskillquery) + * 5.29 [Kill Mutation](#kill-mutation) + * 5.29.1 [RQ.SRS-006.RBAC.Privileges.KillMutation](#rqsrs-006rbacprivilegeskillmutation) + * 5.29.2 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate](#rqsrs-006rbacprivilegeskillmutationalterupdate) + * 5.29.3 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete](#rqsrs-006rbacprivilegeskillmutationalterdelete) + * 5.29.4 [RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn](#rqsrs-006rbacprivilegeskillmutationalterdropcolumn) + * 5.30 [Show](#show) + * 5.30.1 [RQ.SRS-006.RBAC.ShowTables.Privilege](#rqsrs-006rbacshowtablesprivilege) + * 5.30.2 [RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege](#rqsrs-006rbacshowtablesrequiredprivilege) + * 5.30.3 [RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege](#rqsrs-006rbacexiststablerequiredprivilege) + * 5.30.4 [RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege](#rqsrs-006rbacchecktablerequiredprivilege) + * 5.30.5 [RQ.SRS-006.RBAC.ShowDatabases.Privilege](#rqsrs-006rbacshowdatabasesprivilege) + * 5.30.6 [RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege](#rqsrs-006rbacshowdatabasesrequiredprivilege) + * 5.30.7 [RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege](#rqsrs-006rbacshowcreatedatabaserequiredprivilege) + * 5.30.8 [RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege](#rqsrs-006rbacusedatabaserequiredprivilege) + * 5.30.9 [RQ.SRS-006.RBAC.ShowColumns.Privilege](#rqsrs-006rbacshowcolumnsprivilege) + * 5.30.10 [RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege](#rqsrs-006rbacshowcreatetablerequiredprivilege) + * 5.30.11 [RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege](#rqsrs-006rbacdescribetablerequiredprivilege) + * 5.30.12 [RQ.SRS-006.RBAC.ShowDictionaries.Privilege](#rqsrs-006rbacshowdictionariesprivilege) + * 5.30.13 [RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege](#rqsrs-006rbacshowdictionariesrequiredprivilege) + * 5.30.14 [RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege](#rqsrs-006rbacshowcreatedictionaryrequiredprivilege) + * 5.30.15 [RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege](#rqsrs-006rbacexistsdictionaryrequiredprivilege) + * 5.31 [Access Management](#access-management) + * 5.31.1 [RQ.SRS-006.RBAC.Privileges.CreateUser](#rqsrs-006rbacprivilegescreateuser) + * 5.31.2 [RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole](#rqsrs-006rbacprivilegescreateuserdefaultrole) + * 5.31.3 [RQ.SRS-006.RBAC.Privileges.AlterUser](#rqsrs-006rbacprivilegesalteruser) + * 5.31.4 [RQ.SRS-006.RBAC.Privileges.DropUser](#rqsrs-006rbacprivilegesdropuser) + * 5.31.5 [RQ.SRS-006.RBAC.Privileges.CreateRole](#rqsrs-006rbacprivilegescreaterole) + * 5.31.6 [RQ.SRS-006.RBAC.Privileges.AlterRole](#rqsrs-006rbacprivilegesalterrole) + * 5.31.7 [RQ.SRS-006.RBAC.Privileges.DropRole](#rqsrs-006rbacprivilegesdroprole) + * 5.31.8 [RQ.SRS-006.RBAC.Privileges.CreateRowPolicy](#rqsrs-006rbacprivilegescreaterowpolicy) + * 5.31.9 [RQ.SRS-006.RBAC.Privileges.AlterRowPolicy](#rqsrs-006rbacprivilegesalterrowpolicy) + * 5.31.10 [RQ.SRS-006.RBAC.Privileges.DropRowPolicy](#rqsrs-006rbacprivilegesdroprowpolicy) + * 5.31.11 [RQ.SRS-006.RBAC.Privileges.CreateQuota](#rqsrs-006rbacprivilegescreatequota) + * 5.31.12 [RQ.SRS-006.RBAC.Privileges.AlterQuota](#rqsrs-006rbacprivilegesalterquota) + * 5.31.13 [RQ.SRS-006.RBAC.Privileges.DropQuota](#rqsrs-006rbacprivilegesdropquota) + * 5.31.14 [RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile](#rqsrs-006rbacprivilegescreatesettingsprofile) + * 5.31.15 [RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile](#rqsrs-006rbacprivilegesaltersettingsprofile) + * 5.31.16 [RQ.SRS-006.RBAC.Privileges.DropSettingsProfile](#rqsrs-006rbacprivilegesdropsettingsprofile) + * 5.31.17 [RQ.SRS-006.RBAC.Privileges.RoleAdmin](#rqsrs-006rbacprivilegesroleadmin) + * 5.31.18 [Show Access](#show-access) + * 5.31.18.1 [RQ.SRS-006.RBAC.ShowUsers.Privilege](#rqsrs-006rbacshowusersprivilege) + * 5.31.18.2 [RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege](#rqsrs-006rbacshowusersrequiredprivilege) + * 5.31.18.3 [RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege](#rqsrs-006rbacshowcreateuserrequiredprivilege) + * 5.31.18.4 [RQ.SRS-006.RBAC.ShowRoles.Privilege](#rqsrs-006rbacshowrolesprivilege) + * 5.31.18.5 [RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege](#rqsrs-006rbacshowrolesrequiredprivilege) + * 5.31.18.6 [RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege](#rqsrs-006rbacshowcreaterolerequiredprivilege) + * 5.31.18.7 [RQ.SRS-006.RBAC.ShowRowPolicies.Privilege](#rqsrs-006rbacshowrowpoliciesprivilege) + * 5.31.18.8 [RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege](#rqsrs-006rbacshowrowpoliciesrequiredprivilege) + * 5.31.18.9 [RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege](#rqsrs-006rbacshowcreaterowpolicyrequiredprivilege) + * 5.31.18.10 [RQ.SRS-006.RBAC.ShowQuotas.Privilege](#rqsrs-006rbacshowquotasprivilege) + * 5.31.18.11 [RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege](#rqsrs-006rbacshowquotasrequiredprivilege) + * 5.31.18.12 [RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege](#rqsrs-006rbacshowcreatequotarequiredprivilege) + * 5.31.18.13 [RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege](#rqsrs-006rbacshowsettingsprofilesprivilege) + * 5.31.18.14 [RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege](#rqsrs-006rbacshowsettingsprofilesrequiredprivilege) + * 5.31.18.15 [RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege](#rqsrs-006rbacshowcreatesettingsprofilerequiredprivilege) + * 5.32 [dictGet](#dictget) + * 5.32.1 [RQ.SRS-006.RBAC.dictGet.Privilege](#rqsrs-006rbacdictgetprivilege) + * 5.32.2 [RQ.SRS-006.RBAC.dictGet.RequiredPrivilege](#rqsrs-006rbacdictgetrequiredprivilege) + * 5.32.3 [RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege](#rqsrs-006rbacdictgettyperequiredprivilege) + * 5.32.4 [RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege](#rqsrs-006rbacdictgetordefaultrequiredprivilege) + * 5.32.5 [RQ.SRS-006.RBAC.dictHas.RequiredPrivilege](#rqsrs-006rbacdicthasrequiredprivilege) + * 5.32.6 [RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege](#rqsrs-006rbacdictgethierarchyrequiredprivilege) + * 5.32.7 [RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege](#rqsrs-006rbacdictisinrequiredprivilege) + * 5.33 [Introspection](#introspection) + * 5.33.1 [RQ.SRS-006.RBAC.Privileges.Introspection](#rqsrs-006rbacprivilegesintrospection) + * 5.33.2 [RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine](#rqsrs-006rbacprivilegesintrospectionaddresstoline) + * 5.33.3 [RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol](#rqsrs-006rbacprivilegesintrospectionaddresstosymbol) + * 5.33.4 [RQ.SRS-006.RBAC.Privileges.Introspection.demangle](#rqsrs-006rbacprivilegesintrospectiondemangle) + * 5.34 [System](#system) + * 5.34.1 [RQ.SRS-006.RBAC.Privileges.System.Shutdown](#rqsrs-006rbacprivilegessystemshutdown) + * 5.34.2 [RQ.SRS-006.RBAC.Privileges.System.DropCache](#rqsrs-006rbacprivilegessystemdropcache) + * 5.34.3 [RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS](#rqsrs-006rbacprivilegessystemdropcachedns) + * 5.34.4 [RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark](#rqsrs-006rbacprivilegessystemdropcachemark) + * 5.34.5 [RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed](#rqsrs-006rbacprivilegessystemdropcacheuncompressed) + * 5.34.6 [RQ.SRS-006.RBAC.Privileges.System.Reload](#rqsrs-006rbacprivilegessystemreload) + * 5.34.7 [RQ.SRS-006.RBAC.Privileges.System.Reload.Config](#rqsrs-006rbacprivilegessystemreloadconfig) + * 5.34.8 [RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary](#rqsrs-006rbacprivilegessystemreloaddictionary) + * 5.34.9 [RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries](#rqsrs-006rbacprivilegessystemreloaddictionaries) + * 5.34.10 [RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries](#rqsrs-006rbacprivilegessystemreloadembeddeddictionaries) + * 5.34.11 [RQ.SRS-006.RBAC.Privileges.System.Merges](#rqsrs-006rbacprivilegessystemmerges) + * 5.34.12 [RQ.SRS-006.RBAC.Privileges.System.TTLMerges](#rqsrs-006rbacprivilegessystemttlmerges) + * 5.34.13 [RQ.SRS-006.RBAC.Privileges.System.Fetches](#rqsrs-006rbacprivilegessystemfetches) + * 5.34.14 [RQ.SRS-006.RBAC.Privileges.System.Moves](#rqsrs-006rbacprivilegessystemmoves) + * 5.34.15 [RQ.SRS-006.RBAC.Privileges.System.Sends](#rqsrs-006rbacprivilegessystemsends) + * 5.34.16 [RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed](#rqsrs-006rbacprivilegessystemsendsdistributed) + * 5.34.17 [RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated](#rqsrs-006rbacprivilegessystemsendsreplicated) + * 5.34.18 [RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues](#rqsrs-006rbacprivilegessystemreplicationqueues) + * 5.34.19 [RQ.SRS-006.RBAC.Privileges.System.SyncReplica](#rqsrs-006rbacprivilegessystemsyncreplica) + * 5.34.20 [RQ.SRS-006.RBAC.Privileges.System.RestartReplica](#rqsrs-006rbacprivilegessystemrestartreplica) + * 5.34.21 [RQ.SRS-006.RBAC.Privileges.System.Flush](#rqsrs-006rbacprivilegessystemflush) + * 5.34.22 [RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed](#rqsrs-006rbacprivilegessystemflushdistributed) + * 5.34.23 [RQ.SRS-006.RBAC.Privileges.System.Flush.Logs](#rqsrs-006rbacprivilegessystemflushlogs) + * 5.35 [Sources](#sources) + * 5.35.1 [RQ.SRS-006.RBAC.Privileges.Sources](#rqsrs-006rbacprivilegessources) + * 5.35.2 [RQ.SRS-006.RBAC.Privileges.Sources.File](#rqsrs-006rbacprivilegessourcesfile) + * 5.35.3 [RQ.SRS-006.RBAC.Privileges.Sources.URL](#rqsrs-006rbacprivilegessourcesurl) + * 5.35.4 [RQ.SRS-006.RBAC.Privileges.Sources.Remote](#rqsrs-006rbacprivilegessourcesremote) + * 5.35.5 [RQ.SRS-006.RBAC.Privileges.Sources.MySQL](#rqsrs-006rbacprivilegessourcesmysql) + * 5.35.6 [RQ.SRS-006.RBAC.Privileges.Sources.ODBC](#rqsrs-006rbacprivilegessourcesodbc) + * 5.35.7 [RQ.SRS-006.RBAC.Privileges.Sources.JDBC](#rqsrs-006rbacprivilegessourcesjdbc) + * 5.35.8 [RQ.SRS-006.RBAC.Privileges.Sources.HDFS](#rqsrs-006rbacprivilegessourceshdfs) + * 5.35.9 [RQ.SRS-006.RBAC.Privileges.Sources.S3](#rqsrs-006rbacprivilegessourcess3) + * 5.36 [RQ.SRS-006.RBAC.Privileges.GrantOption](#rqsrs-006rbacprivilegesgrantoption) + * 5.37 [RQ.SRS-006.RBAC.Privileges.All](#rqsrs-006rbacprivilegesall) + * 5.38 [RQ.SRS-006.RBAC.Privileges.RoleAll](#rqsrs-006rbacprivilegesroleall) + * 5.39 [RQ.SRS-006.RBAC.Privileges.None](#rqsrs-006rbacprivilegesnone) + * 5.40 [RQ.SRS-006.RBAC.Privileges.AdminOption](#rqsrs-006rbacprivilegesadminoption) * 6 [References](#references) ## Revision History @@ -656,256 +10643,103 @@ version: 1.0 [ClickHouse] SHALL support role based access control. -#### Login +### Login -##### RQ.SRS-006.RBAC.Login +#### RQ.SRS-006.RBAC.Login version: 1.0 [ClickHouse] SHALL only allow access to the server for a given user only when correct username and password are used during the connection to the server. -##### RQ.SRS-006.RBAC.Login.DefaultUser +#### RQ.SRS-006.RBAC.Login.DefaultUser version: 1.0 [ClickHouse] SHALL use the **default user** when no username and password are specified during the connection to the server. -#### User +### User -##### RQ.SRS-006.RBAC.User +#### RQ.SRS-006.RBAC.User version: 1.0 [ClickHouse] SHALL support creation and manipulation of one or more **user** accounts to which roles, privileges, settings profile, quotas and row policies can be assigned. -##### RQ.SRS-006.RBAC.User.Roles +#### RQ.SRS-006.RBAC.User.Roles version: 1.0 [ClickHouse] SHALL support assigning one or more **roles** to a **user**. -##### RQ.SRS-006.RBAC.User.Privileges +#### RQ.SRS-006.RBAC.User.Privileges version: 1.0 [ClickHouse] SHALL support assigning one or more privileges to a **user**. -##### RQ.SRS-006.RBAC.User.Variables +#### RQ.SRS-006.RBAC.User.Variables version: 1.0 [ClickHouse] SHALL support assigning one or more variables to a **user**. -##### RQ.SRS-006.RBAC.User.Variables.Constraints +#### RQ.SRS-006.RBAC.User.Variables.Constraints version: 1.0 [ClickHouse] SHALL support assigning min, max and read-only constraints for the variables that can be set and read by the **user**. -##### RQ.SRS-006.RBAC.User.SettingsProfile +#### RQ.SRS-006.RBAC.User.SettingsProfile version: 1.0 [ClickHouse] SHALL support assigning one or more **settings profiles** to a **user**. -##### RQ.SRS-006.RBAC.User.Quotas +#### RQ.SRS-006.RBAC.User.Quotas version: 1.0 [ClickHouse] SHALL support assigning one or more **quotas** to a **user**. -##### RQ.SRS-006.RBAC.User.RowPolicies +#### RQ.SRS-006.RBAC.User.RowPolicies version: 1.0 [ClickHouse] SHALL support assigning one or more **row policies** to a **user**. -##### RQ.SRS-006.RBAC.User.AccountLock -version: 1.0 - -[ClickHouse] SHALL support locking and unlocking of **user** accounts. - -##### RQ.SRS-006.RBAC.User.AccountLock.DenyAccess -version: 1.0 - -[ClickHouse] SHALL deny access to the user whose account is locked. - -##### RQ.SRS-006.RBAC.User.DefaultRole +#### RQ.SRS-006.RBAC.User.DefaultRole version: 1.0 [ClickHouse] SHALL support assigning a default role to a **user**. -##### RQ.SRS-006.RBAC.User.RoleSelection +#### RQ.SRS-006.RBAC.User.RoleSelection version: 1.0 [ClickHouse] SHALL support selection of one or more **roles** from the available roles -that are assigned to a **user**. +that are assigned to a **user** using `SET ROLE` statement. -##### RQ.SRS-006.RBAC.User.ShowCreate +#### RQ.SRS-006.RBAC.User.ShowCreate version: 1.0 [ClickHouse] SHALL support showing the command of how **user** account was created. -##### RQ.SRS-006.RBAC.User.ShowPrivileges +#### RQ.SRS-006.RBAC.User.ShowPrivileges version: 1.0 [ClickHouse] SHALL support listing the privileges of the **user**. -#### Role - -##### RQ.SRS-006.RBAC.Role -version: 1.0 - -[ClikHouse] SHALL support creation and manipulation of **roles** -to which privileges, settings profile, quotas and row policies can be -assigned. - -##### RQ.SRS-006.RBAC.Role.Privileges -version: 1.0 - -[ClickHouse] SHALL support assigning one or more privileges to a **role**. - -##### RQ.SRS-006.RBAC.Role.Variables -version: 1.0 - -[ClickHouse] SHALL support assigning one or more variables to a **role**. - -##### RQ.SRS-006.RBAC.Role.SettingsProfile -version: 1.0 - -[ClickHouse] SHALL support assigning one or more **settings profiles** -to a **role**. - -##### RQ.SRS-006.RBAC.Role.Quotas -version: 1.0 - -[ClickHouse] SHALL support assigning one or more **quotas** to a **role**. - -##### RQ.SRS-006.RBAC.Role.RowPolicies -version: 1.0 - -[ClickHouse] SHALL support assigning one or more **row policies** to a **role**. - -#### Partial Revokes - -##### RQ.SRS-006.RBAC.PartialRevokes -version: 1.0 - -[ClickHouse] SHALL support partial revoking of privileges granted -to a **user** or a **role**. - -#### Settings Profile - -##### RQ.SRS-006.RBAC.SettingsProfile -version: 1.0 - -[ClickHouse] SHALL support creation and manipulation of **settings profiles** -that can include value definition for one or more variables and can -can be assigned to one or more **users** or **roles**. - -##### RQ.SRS-006.RBAC.SettingsProfile.Constraints -version: 1.0 - -[ClickHouse] SHALL support assigning min, max and read-only constraints -for the variables specified in the **settings profile**. - -##### RQ.SRS-006.RBAC.SettingsProfile.ShowCreate -version: 1.0 - -[ClickHouse] SHALL support showing the command of how **setting profile** was created. - -#### Quotas - -##### RQ.SRS-006.RBAC.Quotas -version: 1.0 - -[ClickHouse] SHALL support creation and manipulation of **quotas** -that can be used to limit resource usage by a **user** or a **role** -over a period of time. - -##### RQ.SRS-006.RBAC.Quotas.Keyed -version: 1.0 - -[ClickHouse] SHALL support creating **quotas** that are keyed -so that a quota is tracked separately for each key value. - -##### RQ.SRS-006.RBAC.Quotas.Queries -version: 1.0 - -[ClickHouse] SHALL support setting **queries** quota to limit the total number of requests. - -##### RQ.SRS-006.RBAC.Quotas.Errors -version: 1.0 - -[ClickHouse] SHALL support setting **errors** quota to limit the number of queries that threw an exception. - -##### RQ.SRS-006.RBAC.Quotas.ResultRows -version: 1.0 - -[ClickHouse] SHALL support setting **result rows** quota to limit the -the total number of rows given as the result. - -##### RQ.SRS-006.RBAC.Quotas.ReadRows -version: 1.0 - -[ClickHouse] SHALL support setting **read rows** quota to limit the total -number of source rows read from tables for running the query on all remote servers. - -##### RQ.SRS-006.RBAC.Quotas.ResultBytes -version: 1.0 - -[ClickHouse] SHALL support setting **result bytes** quota to limit the total number -of bytes that can be returned as the result. - -##### RQ.SRS-006.RBAC.Quotas.ReadBytes -version: 1.0 - -[ClickHouse] SHALL support setting **read bytes** quota to limit the total number -of source bytes read from tables for running the query on all remote servers. - -##### RQ.SRS-006.RBAC.Quotas.ExecutionTime -version: 1.0 - -[ClickHouse] SHALL support setting **execution time** quota to limit the maximum -query execution time. - -##### RQ.SRS-006.RBAC.Quotas.ShowCreate -version: 1.0 - -[ClickHouse] SHALL support showing the command of how **quota** was created. - -#### Row Policy - -##### RQ.SRS-006.RBAC.RowPolicy -version: 1.0 - -[ClickHouse] SHALL support creation and manipulation of table **row policies** -that can be used to limit access to the table contents for a **user** or a **role** -using a specified **condition**. - -##### RQ.SRS-006.RBAC.RowPolicy.Condition -version: 1.0 - -[ClickHouse] SHALL support row policy **conditions** that can be any SQL -expression that returns a boolean. - -##### RQ.SRS-006.RBAC.RowPolicy.ShowCreate -version: 1.0 - -[ClickHouse] SHALL support showing the command of how **row policy** was created. - -### Specific - -##### RQ.SRS-006.RBAC.User.Use.DefaultRole +#### RQ.SRS-006.RBAC.User.Use.DefaultRole version: 1.0 [ClickHouse] SHALL by default use default role or roles assigned to the user if specified. -##### RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole +#### RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole version: 1.0 [ClickHouse] SHALL by default use all the roles assigned to the user if no default role or roles are specified for the user. +#### Create User + ##### RQ.SRS-006.RBAC.User.Create version: 1.0 @@ -1103,6 +10937,8 @@ CREATE USER [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name] [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] ``` +#### Alter User + ##### RQ.SRS-006.RBAC.User.Alter version: 1.0 @@ -1119,7 +10955,8 @@ the left. version: 1.0 [ClickHouse] SHALL support `IF EXISTS` clause in the `ALTER USER` statement -to skip raising an exception (producing a warning instead) if a user with the specified **name** does not exist. If the `IF EXISTS` clause is not specified then an exception SHALL be raised if a user with the **name** does not exist. +to skip raising an exception (producing a warning instead) if a user with the specified **name** does not exist. +If the `IF EXISTS` clause is not specified then an exception SHALL be raised if a user with the **name** does not exist. ##### RQ.SRS-006.RBAC.User.Alter.Cluster version: 1.0 @@ -1157,7 +10994,8 @@ to some password as identification when altering user account using ##### RQ.SRS-006.RBAC.User.Alter.Host.AddDrop version: 1.0 -[ClickHouse] SHALL support altering user by adding and dropping access to hosts with the `ADD HOST` or the `DROP HOST`in the `ALTER USER` statement. +[ClickHouse] SHALL support altering user by adding and dropping access to hosts +with the `ADD HOST` or the `DROP HOST` in the `ALTER USER` statement. ##### RQ.SRS-006.RBAC.User.Alter.Host.Local version: 1.0 @@ -1189,7 +11027,8 @@ which user can access the server using the `HOST IP` clause in the ##### RQ.SRS-006.RBAC.User.Alter.Host.Like version: 1.0 -[ClickHouse] SHALL support specifying sone or more similar hosts using `LIKE` command syntax using the `HOST LIKE` clause in the `ALTER USER` statement. +[ClickHouse] SHALL support specifying one or more similar hosts using `LIKE` command syntax +using the `HOST LIKE` clause in the `ALTER USER` statement. ##### RQ.SRS-006.RBAC.User.Alter.Host.Any version: 1.0 @@ -1232,7 +11071,6 @@ version: 1.0 [ClickHouse] SHALL support specifying a minimum value for the variable specifed using `SETTINGS` with `MIN` clause in the `ALTER USER` statement. - ##### RQ.SRS-006.RBAC.User.Alter.Settings.Max version: 1.0 @@ -1257,85 +11095,7 @@ ALTER USER [IF EXISTS] name [ON CLUSTER cluster_name] [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] ``` -##### RQ.SRS-006.RBAC.SetDefaultRole -version: 1.0 - -[ClickHouse] SHALL support setting or changing granted roles to default for one or more -users using `SET DEFAULT ROLE` statement which -SHALL permanently change the default roles for the user or users if successful. - -##### RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser -version: 1.0 - -[ClickHouse] SHALL support setting or changing granted roles to default for -the current user using `CURRENT_USER` clause in the `SET DEFAULT ROLE` statement. - -##### RQ.SRS-006.RBAC.SetDefaultRole.All -version: 1.0 - -[ClickHouse] SHALL support setting or changing all granted roles to default -for one or more users using `ALL` clause in the `SET DEFAULT ROLE` statement. - -##### RQ.SRS-006.RBAC.SetDefaultRole.AllExcept -version: 1.0 - -[ClickHouse] SHALL support setting or changing all granted roles except those specified -to default for one or more users using `ALL EXCEPT` clause in the `SET DEFAULT ROLE` statement. - -##### RQ.SRS-006.RBAC.SetDefaultRole.None -version: 1.0 - -[ClickHouse] SHALL support removing all granted roles from default -for one or more users using `NONE` clause in the `SET DEFAULT ROLE` statement. - -##### RQ.SRS-006.RBAC.SetDefaultRole.Syntax -version: 1.0 - -[ClickHouse] SHALL support the following syntax for the `SET DEFAULT ROLE` statement. - -```sql -SET DEFAULT ROLE - {NONE | role [,...] | ALL | ALL EXCEPT role [,...]} - TO {user|CURRENT_USER} [,...] - -``` - -##### RQ.SRS-006.RBAC.SetRole -version: 1.0 - -[ClickHouse] SHALL support activating role or roles for the current user -using `SET ROLE` statement. - -##### RQ.SRS-006.RBAC.SetRole.Default -version: 1.0 - -[ClickHouse] SHALL support activating default roles for the current user -using `DEFAULT` clause in the `SET ROLE` statement. - -##### RQ.SRS-006.RBAC.SetRole.None -version: 1.0 - -[ClickHouse] SHALL support activating no roles for the current user -using `NONE` clause in the `SET ROLE` statement. - -##### RQ.SRS-006.RBAC.SetRole.All -version: 1.0 - -[ClickHouse] SHALL support activating all roles for the current user -using `ALL` clause in the `SET ROLE` statement. - -##### RQ.SRS-006.RBAC.SetRole.AllExcept -version: 1.0 - -[ClickHouse] SHALL support activating all roles except those specified -for the current user using `ALL EXCEPT` clause in the `SET ROLE` statement. - -##### RQ.SRS-006.RBAC.SetRole.Syntax -version: 1.0 - -```sql -SET ROLE {DEFAULT | NONE | role [,...] | ALL | ALL EXCEPT role [,...]} -``` +#### Show Create User ##### RQ.SRS-006.RBAC.User.ShowCreateUser version: 1.0 @@ -1358,6 +11118,8 @@ version: 1.0 SHOW CREATE USER [name | CURRENT_USER] ``` +#### Drop User + ##### RQ.SRS-006.RBAC.User.Drop version: 1.0 @@ -1386,6 +11148,43 @@ version: 1.0 DROP USER [IF EXISTS] name [,...] [ON CLUSTER cluster_name] ``` +### Role + +#### RQ.SRS-006.RBAC.Role +version: 1.0 + +[ClikHouse] SHALL support creation and manipulation of **roles** +to which privileges, settings profile, quotas and row policies can be +assigned. + +#### RQ.SRS-006.RBAC.Role.Privileges +version: 1.0 + +[ClickHouse] SHALL support assigning one or more privileges to a **role**. + +#### RQ.SRS-006.RBAC.Role.Variables +version: 1.0 + +[ClickHouse] SHALL support assigning one or more variables to a **role**. + +#### RQ.SRS-006.RBAC.Role.SettingsProfile +version: 1.0 + +[ClickHouse] SHALL support assigning one or more **settings profiles** +to a **role**. + +#### RQ.SRS-006.RBAC.Role.Quotas +version: 1.0 + +[ClickHouse] SHALL support assigning one or more **quotas** to a **role**. + +#### RQ.SRS-006.RBAC.Role.RowPolicies +version: 1.0 + +[ClickHouse] SHALL support assigning one or more **row policies** to a **role**. + +#### Create Role + ##### RQ.SRS-006.RBAC.Role.Create version: 1.0 @@ -1421,6 +11220,8 @@ CREATE ROLE [IF NOT EXISTS | OR REPLACE] name [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] ``` +#### Alter Role + ##### RQ.SRS-006.RBAC.Role.Alter version: 1.0 @@ -1467,6 +11268,8 @@ ALTER ROLE [IF EXISTS] name [ON CLUSTER cluster_name] [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] ``` +#### Drop Role + ##### RQ.SRS-006.RBAC.Role.Drop version: 1.0 @@ -1494,6 +11297,8 @@ version: 1.0 DROP ROLE [IF EXISTS] name [,...] [ON CLUSTER cluster_name] ``` +#### Show Create Role + ##### RQ.SRS-006.RBAC.Role.ShowCreate version: 1.0 @@ -1509,326 +11314,15 @@ version: 1.0 SHOW CREATE ROLE name ``` -##### RQ.SRS-006.RBAC.Grant.Privilege.To +### Partial Revokes + +#### RQ.SRS-006.RBAC.PartialRevokes version: 1.0 -[ClickHouse] SHALL support granting privileges to one or more users or roles using `TO` clause -in the `GRANT PRIVILEGE` statement. +[ClickHouse] SHALL support partial revoking of privileges granted +to a **user** or a **role**. -##### RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser -version: 1.0 - -[ClickHouse] SHALL support granting privileges to current user using `TO CURRENT_USER` clause -in the `GRANT PRIVILEGE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Select -version: 1.0 - -[ClickHouse] SHALL support granting the **select** privilege to one or more users or roles -for a database or a table using the `GRANT SELECT` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Insert -version: 1.0 - -[ClickHouse] SHALL support granting the **insert** privilege to one or more users or roles -for a database or a table using the `GRANT INSERT` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Alter -version: 1.0 - -[ClickHouse] SHALL support granting the **alter** privilege to one or more users or roles -for a database or a table using the `GRANT ALTER` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Create -version: 1.0 - -[ClickHouse] SHALL support granting the **create** privilege to one or more users or roles -using the `GRANT CREATE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Drop -version: 1.0 - -[ClickHouse] SHALL support granting the **drop** privilege to one or more users or roles -using the `GRANT DROP` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Truncate -version: 1.0 - -[ClickHouse] SHALL support granting the **truncate** privilege to one or more users or roles -for a database or a table using `GRANT TRUNCATE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Optimize -version: 1.0 - -[ClickHouse] SHALL support granting the **optimize** privilege to one or more users or roles -for a database or a table using `GRANT OPTIMIZE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Show -version: 1.0 - -[ClickHouse] SHALL support granting the **show** privilege to one or more users or roles -for a database or a table using `GRANT SHOW` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.KillQuery -version: 1.0 - -[ClickHouse] SHALL support granting the **kill query** privilege to one or more users or roles -for a database or a table using `GRANT KILL QUERY` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement -version: 1.0 - -[ClickHouse] SHALL support granting the **access management** privileges to one or more users or roles -for a database or a table using `GRANT ACCESS MANAGEMENT` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.System -version: 1.0 - -[ClickHouse] SHALL support granting the **system** privileges to one or more users or roles -for a database or a table using `GRANT SYSTEM` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Introspection -version: 1.0 - -[ClickHouse] SHALL support granting the **introspection** privileges to one or more users or roles -for a database or a table using `GRANT INTROSPECTION` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Sources -version: 1.0 - -[ClickHouse] SHALL support granting the **sources** privileges to one or more users or roles -for a database or a table using `GRANT SOURCES` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.DictGet -version: 1.0 - -[ClickHouse] SHALL support granting the **dictGet** privilege to one or more users or roles -for a database or a table using `GRANT dictGet` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.None -version: 1.0 - -[ClickHouse] SHALL support granting no privileges to one or more users or roles -for a database or a table using `GRANT NONE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.All -version: 1.0 - -[ClickHouse] SHALL support granting the **all** privileges to one or more users or roles -for a database or a table using the `GRANT ALL` or `GRANT ALL PRIVILEGES` statements. - -##### RQ.SRS-006.RBAC.Grant.Privilege.GrantOption -version: 1.0 - -[ClickHouse] SHALL support granting the **grant option** privilege to one or more users or roles -for a database or a table using the `WITH GRANT OPTION` clause in the `GRANT` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.On -version: 1.0 - -[ClickHouse] SHALL support the `ON` clause in the `GRANT` privilege statement -which SHALL allow to specify one or more tables to which the privilege SHALL -be granted using the following patterns - -* `*.*` any table in any database -* `database.*` any table in the specified database -* `database.table` specific table in the specified database -* `*` any table in the current database -* `table` specific table in the current database - -##### RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns -version: 1.0 - -[ClickHouse] SHALL support granting the privilege **some_privilege** to one or more users or roles -for a database or a table using the `GRANT some_privilege(column)` statement for one column. -Multiple columns will be supported with `GRANT some_privilege(column1, column2...)` statement. -The privileges will be granted for only the specified columns. - -##### RQ.SRS-006.RBAC.Grant.Privilege.OnCluster -version: 1.0 - -[ClickHouse] SHALL support specifying cluster on which to grant privileges using the `ON CLUSTER` -clause in the `GRANT PRIVILEGE` statement. - -##### RQ.SRS-006.RBAC.Grant.Privilege.Syntax -version: 1.0 - -[ClickHouse] SHALL support the following syntax for the `GRANT` statement that -grants explicit privileges to a user or a role. - -```sql -GRANT [ON CLUSTER cluster_name] privilege[(column_name [,...])] [,...] - ON {db.table|db.*|*.*|table|*} - TO {user | role | CURRENT_USER} [,...] - [WITH GRANT OPTION] -``` - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Cluster -version: 1.0 - -[ClickHouse] SHALL support revoking privileges to one or more users or roles -for a database or a table on some specific cluster using the `REVOKE ON CLUSTER cluster_name` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Any -version: 1.0 - -[ClickHouse] SHALL support revoking ANY privilege to one or more users or roles -for a database or a table using the `REVOKE some_privilege` statement. -**some_privilege** refers to any Clickhouse defined privilege, whose hierarchy includes -SELECT, INSERT, ALTER, CREATE, DROP, TRUNCATE, OPTIMIZE, SHOW, KILL QUERY, ACCESS MANAGEMENT, -SYSTEM, INTROSPECTION, SOURCES, dictGet and all of their sub-privileges. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Select -version: 1.0 - -[ClickHouse] SHALL support revoking the **select** privilege to one or more users or roles -for a database or a table using the `REVOKE SELECT` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Insert -version: 1.0 - -[ClickHouse] SHALL support revoking the **insert** privilege to one or more users or roles -for a database or a table using the `REVOKE INSERT` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Alter -version: 1.0 - -[ClickHouse] SHALL support revoking the **alter** privilege to one or more users or roles -for a database or a table using the `REVOKE ALTER` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Create -version: 1.0 - -[ClickHouse] SHALL support revoking the **create** privilege to one or more users or roles -using the `REVOKE CREATE` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Drop -version: 1.0 - -[ClickHouse] SHALL support revoking the **drop** privilege to one or more users or roles -using the `REVOKE DROP` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Truncate -version: 1.0 - -[ClickHouse] SHALL support revoking the **truncate** privilege to one or more users or roles -for a database or a table using the `REVOKE TRUNCATE` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Optimize -version: 1.0 - -[ClickHouse] SHALL support revoking the **optimize** privilege to one or more users or roles -for a database or a table using the `REVOKE OPTIMIZE` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Show -version: 1.0 - -[ClickHouse] SHALL support revoking the **show** privilege to one or more users or roles -for a database or a table using the `REVOKE SHOW` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery -version: 1.0 - -[ClickHouse] SHALL support revoking the **kill query** privilege to one or more users or roles -for a database or a table using the `REVOKE KILL QUERY` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement -version: 1.0 - -[ClickHouse] SHALL support revoking the **access management** privilege to one or more users or roles -for a database or a table using the `REVOKE ACCESS MANAGEMENT` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.System -version: 1.0 - -[ClickHouse] SHALL support revoking the **system** privilege to one or more users or roles -for a database or a table using the `REVOKE SYSTEM` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Introspection -version: 1.0 - -[ClickHouse] SHALL support revoking the **introspection** privilege to one or more users or roles -for a database or a table using the `REVOKE INTROSPECTION` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Sources -version: 1.0 - -[ClickHouse] SHALL support revoking the **sources** privilege to one or more users or roles -for a database or a table using the `REVOKE SOURCES` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.DictGet -version: 1.0 - -[ClickHouse] SHALL support revoking the **dictGet** privilege to one or more users or roles -for a database or a table using the `REVOKE dictGet` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.PrivelegeColumns -version: 1.0 - -[ClickHouse] SHALL support revoking the privilege **some_privilege** to one or more users or roles -for a database or a table using the `REVOKE some_privilege(column)` statement for one column. -Multiple columns will be supported with `REVOKE some_privilege(column1, column2...)` statement. -The privileges will be revoked for only the specified columns. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Multiple -version: 1.0 - -[ClickHouse] SHALL support revoking MULTIPLE **privileges** to one or more users or roles -for a database or a table using the `REVOKE privilege1, privilege2...` statement. -**privileges** refers to any set of Clickhouse defined privilege, whose hierarchy includes -SELECT, INSERT, ALTER, CREATE, DROP, TRUNCATE, OPTIMIZE, SHOW, KILL QUERY, ACCESS MANAGEMENT, -SYSTEM, INTROSPECTION, SOURCES, dictGet and all of their sub-privileges. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.All -version: 1.0 - -[ClickHouse] SHALL support revoking **all** privileges to one or more users or roles -for a database or a table using the `REVOKE ALL` or `REVOKE ALL PRIVILEGES` statements. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.None -version: 1.0 - -[ClickHouse] SHALL support revoking **no** privileges to one or more users or roles -for a database or a table using the `REVOKE NONE` statement. - -##### RQ.SRS-006.RBAC.Revoke.Privilege.On -version: 1.0 - -[ClickHouse] SHALL support the `ON` clause in the `REVOKE` privilege statement -which SHALL allow to specify one or more tables to which the privilege SHALL -be revoked using the following patterns - -* `db.table` specific table in the specified database -* `db.*` any table in the specified database -* `*.*` any table in any database -* `table` specific table in the current database -* `*` any table in the current database - -##### RQ.SRS-006.RBAC.Revoke.Privilege.From -version: 1.0 - -[ClickHouse] SHALL support the `FROM` clause in the `REVOKE` privilege statement -which SHALL allow to specify one or more users to which the privilege SHALL -be revoked using the following patterns - -* `{user | CURRENT_USER} [,...]` some combination of users by name, which may include the current user -* `ALL` all users -* `ALL EXCEPT {user | CURRENT_USER} [,...]` the logical reverse of the first pattern - -##### RQ.SRS-006.RBAC.Revoke.Privilege.Syntax -version: 1.0 - -[ClickHouse] SHALL support the following syntax for the `REVOKE` statement that -revokes explicit privileges of a user or a role. - -```sql -REVOKE [ON CLUSTER cluster_name] privilege - [(column_name [,...])] [,...] - ON {db.table|db.*|*.*|table|*} - FROM {user | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user | CURRENT_USER} [,...] -``` - -##### RQ.SRS-006.RBAC.PartialRevoke.Syntax +#### RQ.SRS-006.RBAC.PartialRevoke.Syntax version: 1.0 [ClickHouse] SHALL support partial revokes by using `partial_revokes` variable @@ -1846,102 +11340,22 @@ To enable partial revokes the `partial revokes` variable SHALL be set to `1` SET partial_revokes = 1 ``` -##### RQ.SRS-006.RBAC.Grant.Role +### Settings Profile + +#### RQ.SRS-006.RBAC.SettingsProfile version: 1.0 -[ClickHouse] SHALL support granting one or more roles to -one or more users or roles using the `GRANT` role statement. +[ClickHouse] SHALL support creation and manipulation of **settings profiles** +that can include value definition for one or more variables and can +can be assigned to one or more **users** or **roles**. -##### RQ.SRS-006.RBAC.Grant.Role.CurrentUser +#### RQ.SRS-006.RBAC.SettingsProfile.Constraints version: 1.0 -[ClickHouse] SHALL support granting one or more roles to current user using -`TO CURRENT_USER` clause in the `GRANT` role statement. +[ClickHouse] SHALL support assigning min, max and read-only constraints +for the variables specified in the **settings profile**. -##### RQ.SRS-006.RBAC.Grant.Role.AdminOption -version: 1.0 - -[ClickHouse] SHALL support granting `admin option` privilege -to one or more users or roles using the `WITH ADMIN OPTION` clause -in the `GRANT` role statement. - -##### RQ.SRS-006.RBAC.Grant.Role.OnCluster -version: 1.0 - -[ClickHouse] SHALL support specifying cluster on which the user is to be granted one or more roles -using `ON CLUSTER` clause in the `GRANT` statement. - -##### RQ.SRS-006.RBAC.Grant.Role.Syntax -version: 1.0 - -[ClickHouse] SHALL support the following syntax for `GRANT` role statement - -``` sql -GRANT - ON CLUSTER cluster_name - role [, role ...] - TO {user | role | CURRENT_USER} [,...] - [WITH ADMIN OPTION] -``` - -##### RQ.SRS-006.RBAC.Revoke.Role -version: 1.0 - -[ClickHouse] SHALL support revoking one or more roles from -one or more users or roles using the `REVOKE` role statement. - -##### RQ.SRS-006.RBAC.Revoke.Role.Keywords -version: 1.0 - -[ClickHouse] SHALL support revoking one or more roles from -special groupings of one or more users or roles with the `ALL`, `ALL EXCEPT`, -and `CURRENT_USER` keywords. - -##### RQ.SRS-006.RBAC.Revoke.Role.Cluster -version: 1.0 - -[ClickHouse] SHALL support revoking one or more roles from -one or more users or roles from one or more clusters -using the `REVOKE ON CLUSTER` role statement. - -##### RQ.SRS-006.RBAC.Revoke.AdminOption -version: 1.0 - -[ClickHouse] SHALL support revoking `admin option` privilege -in one or more users or roles using the `ADMIN OPTION FOR` clause -in the `REVOKE` role statement. - -##### RQ.SRS-006.RBAC.Revoke.Role.Syntax -version: 1.0 - -[ClickHouse] SHALL support the following syntax for the `REVOKE` role statement - -```sql -REVOKE [ON CLUSTER cluster_name] [ADMIN OPTION FOR] - role [,...] - FROM {user | role | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user_name | role_name | CURRENT_USER} [,...] -``` - -##### RQ.SRS-006.RBAC.Show.Grants -version: 1.0 - -[ClickHouse] SHALL support listing all the privileges granted to current user and role -using the `SHOW GRANTS` statement. - -##### RQ.SRS-006.RBAC.Show.Grants.For -version: 1.0 - -[ClickHouse] SHALL support listing all the privileges granted to a user or a role -using the `FOR` clause in the `SHOW GRANTS` statement. - -##### RQ.SRS-006.RBAC.Show.Grants.Syntax -version: 1.0 - -[Clickhouse] SHALL use the following syntax for the `SHOW GRANTS` statement - -``` sql -SHOW GRANTS [FOR user_or_role] -``` +#### Create Settings Profile ##### RQ.SRS-006.RBAC.SettingsProfile.Create version: 1.0 @@ -2027,6 +11441,8 @@ CREATE SETTINGS PROFILE [IF NOT EXISTS | OR REPLACE] name [TO {user_or_role [,...] | NONE | ALL | ALL EXCEPT user_or_role [,...]}] ``` +#### Alter Settings Profile + ##### RQ.SRS-006.RBAC.SettingsProfile.Alter version: 1.0 @@ -2112,6 +11528,8 @@ ALTER SETTINGS PROFILE [IF EXISTS] name [TO {user_or_role [,...] | NONE | ALL | ALL EXCEPT user_or_role [,...]]} ``` +#### Drop Settings Profile + ##### RQ.SRS-006.RBAC.SettingsProfile.Drop version: 1.0 @@ -2140,6 +11558,8 @@ version: 1.0 DROP SETTINGS PROFILE [IF EXISTS] name [,name,...] ``` +#### Show Create Settings Profile + ##### RQ.SRS-006.RBAC.SettingsProfile.ShowCreateSettingsProfile version: 1.0 @@ -2150,6 +11570,63 @@ using the `SHOW CREATE SETTINGS PROFILE` statement with the following syntax SHOW CREATE SETTINGS PROFILE name ``` +### Quotas + +#### RQ.SRS-006.RBAC.Quotas +version: 1.0 + +[ClickHouse] SHALL support creation and manipulation of **quotas** +that can be used to limit resource usage by a **user** or a **role** +over a period of time. + +#### RQ.SRS-006.RBAC.Quotas.Keyed +version: 1.0 + +[ClickHouse] SHALL support creating **quotas** that are keyed +so that a quota is tracked separately for each key value. + +#### RQ.SRS-006.RBAC.Quotas.Queries +version: 1.0 + +[ClickHouse] SHALL support setting **queries** quota to limit the total number of requests. + +#### RQ.SRS-006.RBAC.Quotas.Errors +version: 1.0 + +[ClickHouse] SHALL support setting **errors** quota to limit the number of queries that threw an exception. + +#### RQ.SRS-006.RBAC.Quotas.ResultRows +version: 1.0 + +[ClickHouse] SHALL support setting **result rows** quota to limit the +the total number of rows given as the result. + +#### RQ.SRS-006.RBAC.Quotas.ReadRows +version: 1.0 + +[ClickHouse] SHALL support setting **read rows** quota to limit the total +number of source rows read from tables for running the query on all remote servers. + +#### RQ.SRS-006.RBAC.Quotas.ResultBytes +version: 1.0 + +[ClickHouse] SHALL support setting **result bytes** quota to limit the total number +of bytes that can be returned as the result. + +#### RQ.SRS-006.RBAC.Quotas.ReadBytes +version: 1.0 + +[ClickHouse] SHALL support setting **read bytes** quota to limit the total number +of source bytes read from tables for running the query on all remote servers. + +#### RQ.SRS-006.RBAC.Quotas.ExecutionTime +version: 1.0 + +[ClickHouse] SHALL support setting **execution time** quota to limit the maximum +query execution time. + +#### Create Quotas + ##### RQ.SRS-006.RBAC.Quota.Create version: 1.0 @@ -2188,7 +11665,6 @@ of `{SECOND | MINUTE | HOUR | DAY | MONTH}`. Thus, the complete syntax SHALL be: `FOR INTERVAL number {SECOND | MINUTE | HOUR | DAY}` where number is some real number to define the interval. - ##### RQ.SRS-006.RBAC.Quota.Create.Interval.Randomized version: 1.0 @@ -2311,6 +11787,8 @@ CREATE QUOTA [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name] [TO {role [,...] | ALL | ALL EXCEPT role [,...]}] ``` +#### Alter Quota + ##### RQ.SRS-006.RBAC.Quota.Alter version: 1.0 @@ -2469,6 +11947,8 @@ ALTER QUOTA [IF EXIST] name [TO {user_or_role [,...] | NONE | ALL} [EXCEPT user_or_role [,...]]] ``` +#### Drop Quota + ##### RQ.SRS-006.RBAC.Quota.Drop version: 1.0 @@ -2497,6 +11977,8 @@ version: 1.0 DROP QUOTA [IF EXISTS] name [,name...] ``` +#### Show Quotas + ##### RQ.SRS-006.RBAC.Quota.ShowQuotas version: 1.0 @@ -2521,7 +12003,6 @@ version: 1.0 [ClickHouse] SHALL support the `SETTINGS` clause in the `SHOW QUOTAS` statement to define settings in the showing of all quotas. - ##### RQ.SRS-006.RBAC.Quota.ShowQuotas.Syntax version: 1.0 @@ -2530,6 +12011,9 @@ with the following syntax ``` sql SHOW QUOTAS ``` + +#### Show Create Quota + ##### RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Name version: 1.0 @@ -2557,6 +12041,34 @@ using the `SHOW CREATE QUOTA` statement. SHOW CREATE QUOTA [name | CURRENT] ``` +### Row Policy + +#### RQ.SRS-006.RBAC.RowPolicy +version: 1.0 + +[ClickHouse] SHALL support creation and manipulation of table **row policies** +that can be used to limit access to the table contents for a **user** or a **role** +using a specified **condition**. + +#### RQ.SRS-006.RBAC.RowPolicy.Condition +version: 1.0 + +[ClickHouse] SHALL support row policy **conditions** that can be any SQL +expression that returns a boolean. + +#### RQ.SRS-006.RBAC.RowPolicy.Restriction +version: 1.0 + +[ClickHouse] SHALL restrict all access to a table when a row policy with a condition is created on that table. +All users require a permissive row policy in order to view the table. + +#### RQ.SRS-006.RBAC.RowPolicy.Nesting +version: 1.0 + +[ClickHouse] SHALL restrict rows of tables or views created on top of a table with row policies according to those policies. + +#### Create Row Policy + ##### RQ.SRS-006.RBAC.RowPolicy.Create version: 1.0 @@ -2611,14 +12123,14 @@ version: 1.0 [ClickHouse] SHALL support specifying which rows are affected using the `FOR SELECT` clause in the `CREATE ROW POLICY` statement. -REQUIRES CONFIRMATION +REQUIRES CONDITION. ##### RQ.SRS-006.RBAC.RowPolicy.Create.Condition version: 1.0 [ClickHouse] SHALL support specifying a condition that that can be any SQL expression which returns a boolean using the `USING` -clause in the `CREATE ROW POLOCY` statement. +clause in the `CREATE ROW POLICY` statement. ##### RQ.SRS-006.RBAC.RowPolicy.Create.Assignment version: 1.0 @@ -2657,6 +12169,8 @@ CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name [ON CLUSTER cluster [TO {role [,...] | ALL | ALL EXCEPT role [,...]}] ``` +#### Alter Row Policy + ##### RQ.SRS-006.RBAC.RowPolicy.Alter version: 1.0 @@ -2763,6 +12277,8 @@ ALTER [ROW] POLICY [IF EXISTS] name [ON CLUSTER cluster_name] ON [database.]tabl [TO {role [,...] | ALL | ALL EXCEPT role [,...]}] ``` +#### Drop Row Policy + ##### RQ.SRS-006.RBAC.RowPolicy.Drop version: 1.0 @@ -2797,6 +12313,8 @@ version: 1.0 DROP [ROW] POLICY [IF EXISTS] name [,...] ON [database.]table [,...] [ON CLUSTER cluster_name] ``` +#### Show Create Row Policy + ##### RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy version: 1.0 @@ -2838,9 +12356,510 @@ version: 1.0 SHOW [ROW] POLICIES [ON [database.]table] ``` -#### Table Privileges +### Set Default Role -##### RQ.SRS-006.RBAC.Table.PublicTables +#### RQ.SRS-006.RBAC.SetDefaultRole +version: 1.0 + +[ClickHouse] SHALL support setting or changing granted roles to default for one or more +users using `SET DEFAULT ROLE` statement which +SHALL permanently change the default roles for the user or users if successful. + +#### RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser +version: 1.0 + +[ClickHouse] SHALL support setting or changing granted roles to default for +the current user using `CURRENT_USER` clause in the `SET DEFAULT ROLE` statement. + +#### RQ.SRS-006.RBAC.SetDefaultRole.All +version: 1.0 + +[ClickHouse] SHALL support setting or changing all granted roles to default +for one or more users using `ALL` clause in the `SET DEFAULT ROLE` statement. + +#### RQ.SRS-006.RBAC.SetDefaultRole.AllExcept +version: 1.0 + +[ClickHouse] SHALL support setting or changing all granted roles except those specified +to default for one or more users using `ALL EXCEPT` clause in the `SET DEFAULT ROLE` statement. + +#### RQ.SRS-006.RBAC.SetDefaultRole.None +version: 1.0 + +[ClickHouse] SHALL support removing all granted roles from default +for one or more users using `NONE` clause in the `SET DEFAULT ROLE` statement. + +#### RQ.SRS-006.RBAC.SetDefaultRole.Syntax +version: 1.0 + +[ClickHouse] SHALL support the following syntax for the `SET DEFAULT ROLE` statement. + +```sql +SET DEFAULT ROLE + {NONE | role [,...] | ALL | ALL EXCEPT role [,...]} + TO {user|CURRENT_USER} [,...] + +``` + +### Set Role + +#### RQ.SRS-006.RBAC.SetRole +version: 1.0 + +[ClickHouse] SHALL support activating role or roles for the current user +using `SET ROLE` statement. + +#### RQ.SRS-006.RBAC.SetRole.Default +version: 1.0 + +[ClickHouse] SHALL support activating default roles for the current user +using `DEFAULT` clause in the `SET ROLE` statement. + +#### RQ.SRS-006.RBAC.SetRole.None +version: 1.0 + +[ClickHouse] SHALL support activating no roles for the current user +using `NONE` clause in the `SET ROLE` statement. + +#### RQ.SRS-006.RBAC.SetRole.All +version: 1.0 + +[ClickHouse] SHALL support activating all roles for the current user +using `ALL` clause in the `SET ROLE` statement. + +#### RQ.SRS-006.RBAC.SetRole.AllExcept +version: 1.0 + +[ClickHouse] SHALL support activating all roles except those specified +for the current user using `ALL EXCEPT` clause in the `SET ROLE` statement. + +#### RQ.SRS-006.RBAC.SetRole.Syntax +version: 1.0 + +```sql +SET ROLE {DEFAULT | NONE | role [,...] | ALL | ALL EXCEPT role [,...]} +``` + +### Grant + +#### RQ.SRS-006.RBAC.Grant.Privilege.To +version: 1.0 + +[ClickHouse] SHALL support granting privileges to one or more users or roles using `TO` clause +in the `GRANT PRIVILEGE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser +version: 1.0 + +[ClickHouse] SHALL support granting privileges to current user using `TO CURRENT_USER` clause +in the `GRANT PRIVILEGE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Select +version: 1.0 + +[ClickHouse] SHALL support granting the **select** privilege to one or more users or roles +for a database or a table using the `GRANT SELECT` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Insert +version: 1.0 + +[ClickHouse] SHALL support granting the **insert** privilege to one or more users or roles +for a database or a table using the `GRANT INSERT` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Alter +version: 1.0 + +[ClickHouse] SHALL support granting the **alter** privilege to one or more users or roles +for a database or a table using the `GRANT ALTER` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Create +version: 1.0 + +[ClickHouse] SHALL support granting the **create** privilege to one or more users or roles +using the `GRANT CREATE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Drop +version: 1.0 + +[ClickHouse] SHALL support granting the **drop** privilege to one or more users or roles +using the `GRANT DROP` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Truncate +version: 1.0 + +[ClickHouse] SHALL support granting the **truncate** privilege to one or more users or roles +for a database or a table using `GRANT TRUNCATE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Optimize +version: 1.0 + +[ClickHouse] SHALL support granting the **optimize** privilege to one or more users or roles +for a database or a table using `GRANT OPTIMIZE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Show +version: 1.0 + +[ClickHouse] SHALL support granting the **show** privilege to one or more users or roles +for a database or a table using `GRANT SHOW` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.KillQuery +version: 1.0 + +[ClickHouse] SHALL support granting the **kill query** privilege to one or more users or roles +for a database or a table using `GRANT KILL QUERY` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement +version: 1.0 + +[ClickHouse] SHALL support granting the **access management** privileges to one or more users or roles +for a database or a table using `GRANT ACCESS MANAGEMENT` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.System +version: 1.0 + +[ClickHouse] SHALL support granting the **system** privileges to one or more users or roles +for a database or a table using `GRANT SYSTEM` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Introspection +version: 1.0 + +[ClickHouse] SHALL support granting the **introspection** privileges to one or more users or roles +for a database or a table using `GRANT INTROSPECTION` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Sources +version: 1.0 + +[ClickHouse] SHALL support granting the **sources** privileges to one or more users or roles +for a database or a table using `GRANT SOURCES` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.DictGet +version: 1.0 + +[ClickHouse] SHALL support granting the **dictGet** privilege to one or more users or roles +for a database or a table using `GRANT dictGet` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.None +version: 1.0 + +[ClickHouse] SHALL support granting no privileges to one or more users or roles +for a database or a table using `GRANT NONE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.All +version: 1.0 + +[ClickHouse] SHALL support granting the **all** privileges to one or more users or roles +using the `GRANT ALL` or `GRANT ALL PRIVILEGES` statements. + +#### RQ.SRS-006.RBAC.Grant.Privilege.GrantOption +version: 1.0 + +[ClickHouse] SHALL support granting the **grant option** privilege to one or more users or roles +for a database or a table using the `WITH GRANT OPTION` clause in the `GRANT` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.On +version: 1.0 + +[ClickHouse] SHALL support the `ON` clause in the `GRANT` privilege statement +which SHALL allow to specify one or more tables to which the privilege SHALL +be granted using the following patterns + +* `*.*` any table in any database +* `database.*` any table in the specified database +* `database.table` specific table in the specified database +* `*` any table in the current database +* `table` specific table in the current database + +#### RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns +version: 1.0 + +[ClickHouse] SHALL support granting the privilege **some_privilege** to one or more users or roles +for a database or a table using the `GRANT some_privilege(column)` statement for one column. +Multiple columns will be supported with `GRANT some_privilege(column1, column2...)` statement. +The privileges will be granted for only the specified columns. + +#### RQ.SRS-006.RBAC.Grant.Privilege.OnCluster +version: 1.0 + +[ClickHouse] SHALL support specifying cluster on which to grant privileges using the `ON CLUSTER` +clause in the `GRANT PRIVILEGE` statement. + +#### RQ.SRS-006.RBAC.Grant.Privilege.Syntax +version: 1.0 + +[ClickHouse] SHALL support the following syntax for the `GRANT` statement that +grants explicit privileges to a user or a role. + +```sql +GRANT [ON CLUSTER cluster_name] privilege[(column_name [,...])] [,...] + ON {db.table|db.*|*.*|table|*} + TO {user | role | CURRENT_USER} [,...] + [WITH GRANT OPTION] +``` + +### Revoke + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Cluster +version: 1.0 + +[ClickHouse] SHALL support revoking privileges to one or more users or roles +for a database or a table on some specific cluster using the `REVOKE ON CLUSTER cluster_name` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Select +version: 1.0 + +[ClickHouse] SHALL support revoking the **select** privilege to one or more users or roles +for a database or a table using the `REVOKE SELECT` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Insert +version: 1.0 + +[ClickHouse] SHALL support revoking the **insert** privilege to one or more users or roles +for a database or a table using the `REVOKE INSERT` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Alter +version: 1.0 + +[ClickHouse] SHALL support revoking the **alter** privilege to one or more users or roles +for a database or a table using the `REVOKE ALTER` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Create +version: 1.0 + +[ClickHouse] SHALL support revoking the **create** privilege to one or more users or roles +using the `REVOKE CREATE` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Drop +version: 1.0 + +[ClickHouse] SHALL support revoking the **drop** privilege to one or more users or roles +using the `REVOKE DROP` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Truncate +version: 1.0 + +[ClickHouse] SHALL support revoking the **truncate** privilege to one or more users or roles +for a database or a table using the `REVOKE TRUNCATE` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Optimize +version: 1.0 + +[ClickHouse] SHALL support revoking the **optimize** privilege to one or more users or roles +for a database or a table using the `REVOKE OPTIMIZE` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Show +version: 1.0 + +[ClickHouse] SHALL support revoking the **show** privilege to one or more users or roles +for a database or a table using the `REVOKE SHOW` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery +version: 1.0 + +[ClickHouse] SHALL support revoking the **kill query** privilege to one or more users or roles +for a database or a table using the `REVOKE KILL QUERY` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement +version: 1.0 + +[ClickHouse] SHALL support revoking the **access management** privilege to one or more users or roles +for a database or a table using the `REVOKE ACCESS MANAGEMENT` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.System +version: 1.0 + +[ClickHouse] SHALL support revoking the **system** privilege to one or more users or roles +for a database or a table using the `REVOKE SYSTEM` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Introspection +version: 1.0 + +[ClickHouse] SHALL support revoking the **introspection** privilege to one or more users or roles +for a database or a table using the `REVOKE INTROSPECTION` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Sources +version: 1.0 + +[ClickHouse] SHALL support revoking the **sources** privilege to one or more users or roles +for a database or a table using the `REVOKE SOURCES` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.DictGet +version: 1.0 + +[ClickHouse] SHALL support revoking the **dictGet** privilege to one or more users or roles +for a database or a table using the `REVOKE dictGet` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.PrivilegeColumns +version: 1.0 + +[ClickHouse] SHALL support revoking the privilege **some_privilege** to one or more users or roles +for a database or a table using the `REVOKE some_privilege(column)` statement for one column. +Multiple columns will be supported with `REVOKE some_privilege(column1, column2...)` statement. +The privileges will be revoked for only the specified columns. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Multiple +version: 1.0 + +[ClickHouse] SHALL support revoking MULTIPLE **privileges** to one or more users or roles +for a database or a table using the `REVOKE privilege1, privilege2...` statement. +**privileges** refers to any set of Clickhouse defined privilege, whose hierarchy includes +SELECT, INSERT, ALTER, CREATE, DROP, TRUNCATE, OPTIMIZE, SHOW, KILL QUERY, ACCESS MANAGEMENT, +SYSTEM, INTROSPECTION, SOURCES, dictGet and all of their sub-privileges. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.All +version: 1.0 + +[ClickHouse] SHALL support revoking **all** privileges to one or more users or roles +for a database or a table using the `REVOKE ALL` or `REVOKE ALL PRIVILEGES` statements. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.None +version: 1.0 + +[ClickHouse] SHALL support revoking **no** privileges to one or more users or roles +for a database or a table using the `REVOKE NONE` statement. + +#### RQ.SRS-006.RBAC.Revoke.Privilege.On +version: 1.0 + +[ClickHouse] SHALL support the `ON` clause in the `REVOKE` privilege statement +which SHALL allow to specify one or more tables to which the privilege SHALL +be revoked using the following patterns + +* `db.table` specific table in the specified database +* `db.*` any table in the specified database +* `*.*` any table in any database +* `table` specific table in the current database +* `*` any table in the current database + +#### RQ.SRS-006.RBAC.Revoke.Privilege.From +version: 1.0 + +[ClickHouse] SHALL support the `FROM` clause in the `REVOKE` privilege statement +which SHALL allow to specify one or more users to which the privilege SHALL +be revoked using the following patterns + +* `{user | CURRENT_USER} [,...]` some combination of users by name, which may include the current user +* `ALL` all users +* `ALL EXCEPT {user | CURRENT_USER} [,...]` the logical reverse of the first pattern + +#### RQ.SRS-006.RBAC.Revoke.Privilege.Syntax +version: 1.0 + +[ClickHouse] SHALL support the following syntax for the `REVOKE` statement that +revokes explicit privileges of a user or a role. + +```sql +REVOKE [ON CLUSTER cluster_name] privilege + [(column_name [,...])] [,...] + ON {db.table|db.*|*.*|table|*} + FROM {user | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user | CURRENT_USER} [,...] +``` + +### Grant Role + +#### RQ.SRS-006.RBAC.Grant.Role +version: 1.0 + +[ClickHouse] SHALL support granting one or more roles to +one or more users or roles using the `GRANT` role statement. + +#### RQ.SRS-006.RBAC.Grant.Role.CurrentUser +version: 1.0 + +[ClickHouse] SHALL support granting one or more roles to current user using +`TO CURRENT_USER` clause in the `GRANT` role statement. + +#### RQ.SRS-006.RBAC.Grant.Role.AdminOption +version: 1.0 + +[ClickHouse] SHALL support granting `admin option` privilege +to one or more users or roles using the `WITH ADMIN OPTION` clause +in the `GRANT` role statement. + +#### RQ.SRS-006.RBAC.Grant.Role.OnCluster +version: 1.0 + +[ClickHouse] SHALL support specifying cluster on which the user is to be granted one or more roles +using `ON CLUSTER` clause in the `GRANT` statement. + +#### RQ.SRS-006.RBAC.Grant.Role.Syntax +version: 1.0 + +[ClickHouse] SHALL support the following syntax for `GRANT` role statement + +``` sql +GRANT + ON CLUSTER cluster_name + role [, role ...] + TO {user | role | CURRENT_USER} [,...] + [WITH ADMIN OPTION] +``` + +### Revoke Role + +#### RQ.SRS-006.RBAC.Revoke.Role +version: 1.0 + +[ClickHouse] SHALL support revoking one or more roles from +one or more users or roles using the `REVOKE` role statement. + +#### RQ.SRS-006.RBAC.Revoke.Role.Keywords +version: 1.0 + +[ClickHouse] SHALL support revoking one or more roles from +special groupings of one or more users or roles with the `ALL`, `ALL EXCEPT`, +and `CURRENT_USER` keywords. + +#### RQ.SRS-006.RBAC.Revoke.Role.Cluster +version: 1.0 + +[ClickHouse] SHALL support revoking one or more roles from +one or more users or roles from one or more clusters +using the `REVOKE ON CLUSTER` role statement. + +#### RQ.SRS-006.RBAC.Revoke.AdminOption +version: 1.0 + +[ClickHouse] SHALL support revoking `admin option` privilege +in one or more users or roles using the `ADMIN OPTION FOR` clause +in the `REVOKE` role statement. + +#### RQ.SRS-006.RBAC.Revoke.Role.Syntax +version: 1.0 + +[ClickHouse] SHALL support the following syntax for the `REVOKE` role statement + +```sql +REVOKE [ON CLUSTER cluster_name] [ADMIN OPTION FOR] + role [,...] + FROM {user | role | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user_name | role_name | CURRENT_USER} [,...] +``` + +### Show Grants + +#### RQ.SRS-006.RBAC.Show.Grants +version: 1.0 + +[ClickHouse] SHALL support listing all the privileges granted to current user and role +using the `SHOW GRANTS` statement. + +#### RQ.SRS-006.RBAC.Show.Grants.For +version: 1.0 + +[ClickHouse] SHALL support listing all the privileges granted to a user or a role +using the `FOR` clause in the `SHOW GRANTS` statement. + +#### RQ.SRS-006.RBAC.Show.Grants.Syntax +version: 1.0 + +[Clickhouse] SHALL use the following syntax for the `SHOW GRANTS` statement + +``` sql +SHOW GRANTS [FOR user_or_role] +``` + +### Table Privileges + +#### RQ.SRS-006.RBAC.Table.PublicTables version: 1.0 [ClickHouse] SHALL support that a user without any privileges will be able to access the following tables @@ -2850,7 +12869,7 @@ version: 1.0 * system.contributors * system.functions -##### RQ.SRS-006.RBAC.Table.SensitiveTables +#### RQ.SRS-006.RBAC.Table.SensitiveTables version: 1.0 [ClickHouse] SHALL not support a user with no privileges accessing the following `system` tables: @@ -2867,15 +12886,15 @@ version: 1.0 * zookeeper * macros -#### Distributed Tables +### Distributed Tables -##### RQ.SRS-006.RBAC.DistributedTable.Create +#### RQ.SRS-006.RBAC.DistributedTable.Create version: 1.0 [ClickHouse] SHALL successfully `CREATE` a distributed table if and only if the user has **create table** privilege on the table and **remote** privilege on *.* -##### RQ.SRS-006.RBAC.DistributedTable.Select +#### RQ.SRS-006.RBAC.DistributedTable.Select version: 1.0 [ClickHouse] SHALL successfully `SELECT` from a distributed table if and only if @@ -2883,7 +12902,7 @@ the user has **select** privilege on the table and on the remote table specified Does not require **select** privilege for the remote table if the remote table does not exist on the same server as the user. -##### RQ.SRS-006.RBAC.DistributedTable.Insert +#### RQ.SRS-006.RBAC.DistributedTable.Insert version: 1.0 [ClickHouse] SHALL successfully `INSERT` into a distributed table if and only if @@ -2892,7 +12911,7 @@ the user has **insert** privilege on the table and on the remote table specified Does not require **insert** privilege for the remote table if the remote table does not exist on the same server as the user, insert executes into the remote table on a different server. -##### RQ.SRS-006.RBAC.DistributedTable.SpecialTables +#### RQ.SRS-006.RBAC.DistributedTable.SpecialTables version: 1.0 [ClickHouse] SHALL successfully execute a query using a distributed table that uses one of the special tables if and only if @@ -2902,29 +12921,29 @@ Special tables include: * distributed table * source table of a materialized view -##### RQ.SRS-006.RBAC.DistributedTable.LocalUser +#### RQ.SRS-006.RBAC.DistributedTable.LocalUser version: 1.0 [ClickHouse] SHALL successfully execute a query using a distributed table from a user present locally, but not remotely. -##### RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges +#### RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges version: 1.0 [ClickHouse] SHALL successfully execute a query using a distributed table by a user that exists on multiple nodes if and only if the user has the required privileges on the node the query is being executed from. -#### Views +### Views -##### View +#### View -###### RQ.SRS-006.RBAC.View +##### RQ.SRS-006.RBAC.View version: 1.0 [ClickHouse] SHALL support controlling access to **create**, **select** and **drop** privileges for a view for users or roles. -###### RQ.SRS-006.RBAC.View.Create +##### RQ.SRS-006.RBAC.View.Create version: 1.0 [ClickHouse] SHALL only successfully execute a `CREATE VIEW` command if and only if @@ -2942,7 +12961,7 @@ CREATE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNION ALL CREATE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2 ``` -###### RQ.SRS-006.RBAC.View.Select +##### RQ.SRS-006.RBAC.View.Select version: 1.0 [ClickHouse] SHALL only successfully `SELECT` from a view if and only if @@ -2962,21 +12981,21 @@ CREATE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2 SELECT * FROM view ``` -###### RQ.SRS-006.RBAC.View.Drop +##### RQ.SRS-006.RBAC.View.Drop version: 1.0 [ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if the user has **drop view** privilege on that view either explicitly or through a role. -##### Materialized View +#### Materialized View -###### RQ.SRS-006.RBAC.MaterializedView +##### RQ.SRS-006.RBAC.MaterializedView version: 1.0 [ClickHouse] SHALL support controlling access to **create**, **select**, **alter** and **drop** privileges for a materialized view for users or roles. -###### RQ.SRS-006.RBAC.MaterializedView.Create +##### RQ.SRS-006.RBAC.MaterializedView.Create version: 1.0 [ClickHouse] SHALL only successfully execute a `CREATE MATERIALIZED VIEW` command if and only if @@ -3008,7 +13027,7 @@ For example, CREATE MATERIALIZED VIEW view TO target_table AS SELECT * FROM source_table ``` -###### RQ.SRS-006.RBAC.MaterializedView.Select +##### RQ.SRS-006.RBAC.MaterializedView.Select version: 1.0 [ClickHouse] SHALL only successfully `SELECT` from a materialized view if and only if @@ -3028,25 +13047,25 @@ CREATE MATERIALIZED VIEW view0 ENGINE = Memory AS SELECT column FROM view1 UNION SELECT * FROM view ``` -###### RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable +##### RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable version: 1.0 [ClickHouse] SHALL only successfully `SELECT` from the target table, implicit or explicit, of a materialized view if and only if the user has `SELECT` privilege for the table, either explicitly or through a role. -###### RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable +##### RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable version: 1.0 [ClickHouse] SHALL only successfully `SELECT` from the source table of a materialized view if and only if the user has `SELECT` privilege for the table, either explicitly or through a role. -###### RQ.SRS-006.RBAC.MaterializedView.Drop +##### RQ.SRS-006.RBAC.MaterializedView.Drop version: 1.0 [ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if the user has **drop view** privilege on that view either explicitly or through a role. -###### RQ.SRS-006.RBAC.MaterializedView.ModifyQuery +##### RQ.SRS-006.RBAC.MaterializedView.ModifyQuery version: 1.0 [ClickHouse] SHALL only successfully execute a `MODIFY QUERY` command if and only if @@ -3059,33 +13078,33 @@ For example, ALTER TABLE view MODIFY QUERY SELECT * FROM source_table ``` -###### RQ.SRS-006.RBAC.MaterializedView.Insert +##### RQ.SRS-006.RBAC.MaterializedView.Insert version: 1.0 [ClickHouse] SHALL only succesfully `INSERT` into a materialized view if and only if the user has `INSERT` privilege on the view, either explicitly or through a role. -###### RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable +##### RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable version: 1.0 [ClickHouse] SHALL only succesfully `INSERT` into a source table of a materialized view if and only if the user has `INSERT` privilege on the source table, either explicitly or through a role. -###### RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable +##### RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable version: 1.0 [ClickHouse] SHALL only succesfully `INSERT` into a target table of a materialized view if and only if the user has `INSERT` privelege on the target table, either explicitly or through a role. -##### Live View +#### Live View -###### RQ.SRS-006.RBAC.LiveView +##### RQ.SRS-006.RBAC.LiveView version: 1.0 [ClickHouse] SHALL support controlling access to **create**, **select**, **alter** and **drop** privileges for a live view for users or roles. -###### RQ.SRS-006.RBAC.LiveView.Create +##### RQ.SRS-006.RBAC.LiveView.Create version: 1.0 [ClickHouse] SHALL only successfully execute a `CREATE LIVE VIEW` command if and only if @@ -3103,7 +13122,7 @@ CREATE LIVE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNIO CREATE LIVE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2 ``` -###### RQ.SRS-006.RBAC.LiveView.Select +##### RQ.SRS-006.RBAC.LiveView.Select version: 1.0 [ClickHouse] SHALL only successfully `SELECT` from a live view if and only if @@ -3123,28 +13142,28 @@ CREATE LIVE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM SELECT * FROM view ``` -###### RQ.SRS-006.RBAC.LiveView.Drop +##### RQ.SRS-006.RBAC.LiveView.Drop version: 1.0 [ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if the user has **drop view** privilege on that view either explicitly or through a role. -###### RQ.SRS-006.RBAC.LiveView.Refresh +##### RQ.SRS-006.RBAC.LiveView.Refresh version: 1.0 [ClickHouse] SHALL only successfully execute an `ALTER LIVE VIEW REFRESH` command if and only if the user has **refresh** privilege on that view either explicitly or through a role. -#### Select +### Select -##### RQ.SRS-006.RBAC.Select +#### RQ.SRS-006.RBAC.Select version: 1.0 [ClickHouse] SHALL execute `SELECT` if and only if the user has the **select** privilege for the destination table either because of the explicit grant or through one of the roles assigned to the user. -##### RQ.SRS-006.RBAC.Select.Column +#### RQ.SRS-006.RBAC.Select.Column version: 1.0 [ClickHouse] SHALL support granting or revoking **select** privilege @@ -3153,7 +13172,7 @@ Any `SELECT` statements SHALL not to be executed, unless the user has the **select** privilege for the destination column either because of the explicit grant or through one of the roles assigned to the user. -##### RQ.SRS-006.RBAC.Select.Cluster +#### RQ.SRS-006.RBAC.Select.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **select** privilege @@ -3161,7 +13180,7 @@ on a specified cluster to one or more **users** or **roles**. Any `SELECT` statements SHALL succeed only on nodes where the table exists and privilege was granted. -##### RQ.SRS-006.RBAC.Select.TableEngines +#### RQ.SRS-006.RBAC.Select.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **select** privilege @@ -3182,16 +13201,16 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -#### Insert +### Insert -##### RQ.SRS-006.RBAC.Insert +#### RQ.SRS-006.RBAC.Insert version: 1.0 [ClickHouse] SHALL execute `INSERT INTO` if and only if the user has the **insert** privilege for the destination table either because of the explicit grant or through one of the roles assigned to the user. -##### RQ.SRS-006.RBAC.Insert.Column +#### RQ.SRS-006.RBAC.Insert.Column version: 1.0 [ClickHouse] SHALL support granting or revoking **insert** privilege @@ -3200,7 +13219,7 @@ Any `INSERT INTO` statements SHALL not to be executed, unless the user has the **insert** privilege for the destination column either because of the explicit grant or through one of the roles assigned to the user. -##### RQ.SRS-006.RBAC.Insert.Cluster +#### RQ.SRS-006.RBAC.Insert.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **insert** privilege @@ -3208,7 +13227,7 @@ on a specified cluster to one or more **users** or **roles**. Any `INSERT INTO` statements SHALL succeed only on nodes where the table exists and privilege was granted. -##### RQ.SRS-006.RBAC.Insert.TableEngines +#### RQ.SRS-006.RBAC.Insert.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **insert** privilege @@ -3229,11 +13248,11 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -#### Alter +### Alter -##### Alter Column +#### Alter Column -###### RQ.SRS-006.RBAC.Privileges.AlterColumn +##### RQ.SRS-006.RBAC.Privileges.AlterColumn version: 1.0 [ClickHouse] SHALL support controlling access to the **alter column** privilege @@ -3243,19 +13262,19 @@ return an error, unless the user has the **alter column** privilege for the destination table either because of the explicit grant or through one of the roles assigned to the user. -###### RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant version: 1.0 [ClickHouse] SHALL support granting **alter column** privilege for a database or a specific table to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter column** privilege for a database or a specific table to one or more **users** or **roles** -###### RQ.SRS-006.RBAC.Privileges.AlterColumn.Column +##### RQ.SRS-006.RBAC.Privileges.AlterColumn.Column version: 1.0 [ClickHouse] SHALL support granting or revoking **alter column** privilege @@ -3264,7 +13283,7 @@ Any `ALTER TABLE ... ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN` statements SHALL retu unless the user has the **alter column** privilege for the destination column either because of the explicit grant or through one of the roles assigned to the user. -###### RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster +##### RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **alter column** privilege @@ -3272,7 +13291,7 @@ on a specified cluster to one or more **users** or **roles**. Any `ALTER TABLE ... ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN` statements SHALL succeed only on nodes where the table exists and privilege was granted. -###### RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter column** privilege @@ -3293,9 +13312,9 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Index +#### Alter Index -###### RQ.SRS-006.RBAC.Privileges.AlterIndex +##### RQ.SRS-006.RBAC.Privileges.AlterIndex version: 1.0 [ClickHouse] SHALL support controlling access to the **alter index** privilege @@ -3305,19 +13324,19 @@ return an error, unless the user has the **alter index** privilege for the destination table either because of the explicit grant or through one of the roles assigned to the user. -###### RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant version: 1.0 [ClickHouse] SHALL support granting **alter index** privilege for a database or a specific table to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter index** privilege for a database or a specific table to one or more **users** or **roles** -###### RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster +##### RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **alter index** privilege @@ -3325,7 +13344,7 @@ on a specified cluster to one or more **users** or **roles**. Any `ALTER TABLE ... ORDER BY | ADD|DROP|MATERIALIZE|CLEAR INDEX` statements SHALL succeed only on nodes where the table exists and privilege was granted. -###### RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter index** privilege @@ -3346,9 +13365,9 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Constraint +#### Alter Constraint -###### RQ.SRS-006.RBAC.Privileges.AlterConstraint +##### RQ.SRS-006.RBAC.Privileges.AlterConstraint version: 1.0 [ClickHouse] SHALL support controlling access to the **alter constraint** privilege @@ -3358,19 +13377,19 @@ return an error, unless the user has the **alter constraint** privilege for the destination table either because of the explicit grant or through one of the roles assigned to the user. -###### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant version: 1.0 [ClickHouse] SHALL support granting **alter constraint** privilege for a database or a specific table to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter constraint** privilege for a database or a specific table to one or more **users** or **roles** -###### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster +##### RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **alter constraint** privilege @@ -3378,7 +13397,7 @@ on a specified cluster to one or more **users** or **roles**. Any `ALTER TABLE ... ADD|DROP CONSTRAINT` statements SHALL succeed only on nodes where the table exists and privilege was granted. -###### RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter constraint** privilege @@ -3399,9 +13418,9 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter TTL +#### Alter TTL -###### RQ.SRS-006.RBAC.Privileges.AlterTTL +##### RQ.SRS-006.RBAC.Privileges.AlterTTL version: 1.0 [ClickHouse] SHALL support controlling access to the **alter ttl** or **alter materialize ttl** privilege @@ -3411,19 +13430,19 @@ return an error, unless the user has the **alter ttl** or **alter materialize tt the destination table either because of the explicit grant or through one of the roles assigned to the user. -###### RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant version: 1.0 [ClickHouse] SHALL support granting **alter ttl** or **alter materialize ttl** privilege for a database or a specific table to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter ttl** or **alter materialize ttl** privilege for a database or a specific table to one or more **users** or **roles** -###### RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster +##### RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **alter ttl** or **alter materialize ttl** privilege @@ -3431,7 +13450,7 @@ on a specified cluster to one or more **users** or **roles**. Any `ALTER TABLE ... ALTER TTL | ALTER MATERIALIZE TTL` statements SHALL succeed only on nodes where the table exists and privilege was granted. -###### RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter ttl** or **alter materialize ttl** privilege @@ -3439,9 +13458,9 @@ on tables created using the following engines * MergeTree -##### Alter Settings +#### Alter Settings -###### RQ.SRS-006.RBAC.Privileges.AlterSettings +##### RQ.SRS-006.RBAC.Privileges.AlterSettings version: 1.0 [ClickHouse] SHALL support controlling access to the **alter settings** privilege @@ -3452,19 +13471,19 @@ the destination table either because of the explicit grant or through one of the roles assigned to the user. The **alter settings** privilege allows modifying table engine settings. It doesn’t affect settings or server configuration parameters. -###### RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant version: 1.0 [ClickHouse] SHALL support granting **alter settings** privilege for a database or a specific table to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter settings** privilege for a database or a specific table to one or more **users** or **roles** -###### RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster +##### RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster version: 1.0 [ClickHouse] SHALL support granting or revoking **alter settings** privilege @@ -3472,7 +13491,7 @@ on a specified cluster to one or more **users** or **roles**. Any `ALTER TABLE ... MODIFY SETTING setting` statements SHALL succeed only on nodes where the table exists and privilege was granted. -###### RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter settings** privilege @@ -3493,27 +13512,27 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Update +#### Alter Update -###### RQ.SRS-006.RBAC.Privileges.AlterUpdate +##### RQ.SRS-006.RBAC.Privileges.AlterUpdate version: 1.0 [ClickHouse] SHALL successfully execute `ALTER UPDATE` statement if and only if the user has **alter update** privilege for that column, either directly or through a role. -###### RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant version: 1.0 [ClickHouse] SHALL support granting **alter update** privilege on a column level to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter update** privilege on a column level from one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter update** privilege @@ -3534,27 +13553,27 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Delete +#### Alter Delete -###### RQ.SRS-006.RBAC.Privileges.AlterDelete +##### RQ.SRS-006.RBAC.Privileges.AlterDelete version: 1.0 [ClickHouse] SHALL successfully execute `ALTER DELETE` statement if and only if the user has **alter delete** privilege for that table, either directly or through a role. -###### RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant version: 1.0 [ClickHouse] SHALL support granting **alter delete** privilege on a column level to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter delete** privilege on a column level from one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter delete** privilege @@ -3575,27 +13594,27 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Freeze Partition +#### Alter Freeze Partition -###### RQ.SRS-006.RBAC.Privileges.AlterFreeze +##### RQ.SRS-006.RBAC.Privileges.AlterFreeze version: 1.0 [ClickHouse] SHALL successfully execute `ALTER FREEZE` statement if and only if the user has **alter freeze** privilege for that table, either directly or through a role. -###### RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant version: 1.0 [ClickHouse] SHALL support granting **alter freeze** privilege on a column level to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter freeze** privilege on a column level from one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter freeze** privilege @@ -3616,27 +13635,27 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Fetch Partition +#### Alter Fetch Partition -###### RQ.SRS-006.RBAC.Privileges.AlterFetch +##### RQ.SRS-006.RBAC.Privileges.AlterFetch version: 1.0 [ClickHouse] SHALL successfully execute `ALTER FETCH` statement if and only if the user has **alter fetch** privilege for that table, either directly or through a role. -###### RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant version: 1.0 [ClickHouse] SHALL support granting **alter fetch** privilege on a column level to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter fetch** privilege on a column level from one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter fetch** privilege @@ -3650,9 +13669,9 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree -##### Alter Move Partition +#### Alter Move Partition -###### RQ.SRS-006.RBAC.Privileges.AlterMove +##### RQ.SRS-006.RBAC.Privileges.AlterMove version: 1.0 [ClickHouse] SHALL successfully execute `ALTER MOVE` statement if and only if the user has **alter move**, **select**, and **alter delete** privilege on the source table @@ -3662,19 +13681,19 @@ For example, ALTER TABLE source_table MOVE PARTITION 1 TO target_table ``` -###### RQ.SRS-006.RBAC.Privileges.AlterMove.Grant +##### RQ.SRS-006.RBAC.Privileges.AlterMove.Grant version: 1.0 [ClickHouse] SHALL support granting **alter move** privilege on a column level to one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke +##### RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke version: 1.0 [ClickHouse] SHALL support revoking **alter move** privilege on a column level from one or more **users** or **roles**. -###### RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines +##### RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines version: 1.0 [ClickHouse] SHALL support controlling access to the **alter move** privilege @@ -3695,6 +13714,8 @@ on tables created using the following engines * ReplicatedVersionedCollapsingMergeTree * ReplicatedGraphiteMergeTree +### Create + #### RQ.SRS-006.RBAC.Privileges.CreateTable version: 1.0 @@ -3731,6 +13752,8 @@ version: 1.0 [ClickHouse] SHALL successfully execute `CREATE TEMPORARY TABLE` statement if and only if the user has **create temporary table** privilege on the table, either directly or through a role. +### Attach + #### RQ.SRS-006.RBAC.Privileges.AttachDatabase version: 1.0 @@ -3755,6 +13778,8 @@ version: 1.0 [ClickHouse] SHALL successfully execute `ATTACH TABLE` statement if and only if the user has **create table** privilege on the table, either directly or through a role. +### Drop + #### RQ.SRS-006.RBAC.Privileges.DropTable version: 1.0 @@ -3773,6 +13798,8 @@ version: 1.0 [ClickHouse] SHALL successfully execute `DROP DICTIONARY` statement if and only if the user has **drop dictionary** privilege on the dictionary, either directly or through a role. +### Detach + #### RQ.SRS-006.RBAC.Privileges.DetachTable version: 1.0 @@ -3797,354 +13824,360 @@ version: 1.0 [ClickHouse] SHALL successfully execute `DETACH DICTIONARY` statement if and only if the user has **drop dictionary** privilege on the dictionary, either directly or through a role. +### Truncate + #### RQ.SRS-006.RBAC.Privileges.Truncate version: 1.0 [ClickHouse] SHALL successfully execute `TRUNCATE TABLE` statement if and only if the user has **truncate table** privilege on the table, either directly or through a role. +### Optimize + #### RQ.SRS-006.RBAC.Privileges.Optimize version: 1.0 [ClickHouse] SHALL successfully execute `OPTIMIZE TABLE` statement if and only if the user has **optimize table** privilege on the table, either directly or through a role. +### Kill Query + #### RQ.SRS-006.RBAC.Privileges.KillQuery version: 1.0 [ClickHouse] SHALL successfully execute `KILL QUERY` statement if and only if the user has **kill query** privilege, either directly or through a role. -#### Kill Mutation +### Kill Mutation -##### RQ.SRS-006.RBAC.Privileges.KillMutation +#### RQ.SRS-006.RBAC.Privileges.KillMutation version: 1.0 [ClickHouse] SHALL successfully execute `KILL MUTATION` statement if and only if the user has the privilege that created the mutation, either directly or through a role. For example, to `KILL MUTATION` after `ALTER UPDATE` query, the user needs `ALTER UPDATE` privilege. -##### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate +#### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate version: 1.0 [ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER UPDATE` mutation if and only if the user has `ALTER UPDATE` privilege on the table where the mutation was created, either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete +#### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete version: 1.0 [ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER DELETE` mutation if and only if the user has `ALTER DELETE` privilege on the table where the mutation was created, either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn +#### RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn version: 1.0 [ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER DROP COLUMN` mutation if and only if the user has `ALTER DROP COLUMN` privilege on the table where the mutation was created, either directly or through a role. -#### Show +### Show -##### RQ.SRS-006.RBAC.ShowTables.Privilege +#### RQ.SRS-006.RBAC.ShowTables.Privilege version: 1.0 [ClickHouse] SHALL grant **show tables** privilege on a table to a user if that user has recieved any grant, including `SHOW TABLES`, on that table, either directly or through a role. -##### RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW TABLES` statement if and only if the user has **show tables** privilege, or any privilege on the table either directly or through a role. -##### RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege +#### RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `EXISTS table` statement if and only if the user has **show tables** privilege, or any privilege on the table either directly or through a role. -##### RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege +#### RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `CHECK table` statement if and only if the user has **show tables** privilege, or any privilege on the table either directly or through a role. -##### RQ.SRS-006.RBAC.ShowDatabases.Privilege +#### RQ.SRS-006.RBAC.ShowDatabases.Privilege version: 1.0 [ClickHouse] SHALL grant **show databases** privilege on a database to a user if that user has recieved any grant, including `SHOW DATABASES`, on that table, either directly or through a role. -##### RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW DATABASES` statement if and only if the user has **show databases** privilege, or any privilege on the database either directly or through a role. -##### RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE DATABASE` statement if and only if the user has **show databases** privilege, or any privilege on the database either directly or through a role. -##### RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege +#### RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `USE database` statement if and only if the user has **show databases** privilege, or any privilege on the database either directly or through a role. -##### RQ.SRS-006.RBAC.ShowColumns.Privilege +#### RQ.SRS-006.RBAC.ShowColumns.Privilege version: 1.0 [ClickHouse] SHALL support granting or revoking the `SHOW COLUMNS` privilege. -##### RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE TABLE` statement if and only if the user has **show columns** privilege on that table, either directly or through a role. -##### RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege +#### RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `DESCRIBE table` statement if and only if the user has **show columns** privilege on that table, either directly or through a role. -##### RQ.SRS-006.RBAC.ShowDictionaries.Privilege +#### RQ.SRS-006.RBAC.ShowDictionaries.Privilege version: 1.0 [ClickHouse] SHALL grant **show dictionaries** privilege on a dictionary to a user if that user has recieved any grant, including `SHOW DICTIONARIES`, on that dictionary, either directly or through a role. -##### RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW DICTIONARIES` statement if and only if the user has **show dictionaries** privilege, or any privilege on the dictionary either directly or through a role. -##### RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege +#### RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE DICTIONARY` statement if and only if the user has **show dictionaries** privilege, or any privilege on the dictionary either directly or through a role. -##### RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege +#### RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `EXISTS dictionary` statement if and only if the user has **show dictionaries** privilege, or any privilege on the dictionary either directly or through a role. -#### Access Management +### Access Management -##### RQ.SRS-006.RBAC.Privileges.CreateUser +#### RQ.SRS-006.RBAC.Privileges.CreateUser version: 1.0 [ClickHouse] SHALL successfully execute `CREATE USER` statement if and only if the user has **create user** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole +#### RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole version: 1.0 [ClickHouse] SHALL successfully execute `CREATE USER` statement with `DEFAULT ROLE ` clause if and only if the user has **create user** privilege and the role with **admin option**, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.AlterUser +#### RQ.SRS-006.RBAC.Privileges.AlterUser version: 1.0 [ClickHouse] SHALL successfully execute `ALTER USER` statement if and only if the user has **alter user** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.DropUser +#### RQ.SRS-006.RBAC.Privileges.DropUser version: 1.0 [ClickHouse] SHALL successfully execute `DROP USER` statement if and only if the user has **drop user** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.CreateRole +#### RQ.SRS-006.RBAC.Privileges.CreateRole version: 1.0 [ClickHouse] SHALL successfully execute `CREATE ROLE` statement if and only if the user has **create role** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.AlterRole +#### RQ.SRS-006.RBAC.Privileges.AlterRole version: 1.0 [ClickHouse] SHALL successfully execute `ALTER ROLE` statement if and only if the user has **alter role** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.DropRole +#### RQ.SRS-006.RBAC.Privileges.DropRole version: 1.0 [ClickHouse] SHALL successfully execute `DROP ROLE` statement if and only if the user has **drop role** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.CreateRowPolicy +#### RQ.SRS-006.RBAC.Privileges.CreateRowPolicy version: 1.0 [ClickHouse] SHALL successfully execute `CREATE ROW POLICY` statement if and only if the user has **create row policy** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.AlterRowPolicy +#### RQ.SRS-006.RBAC.Privileges.AlterRowPolicy version: 1.0 [ClickHouse] SHALL successfully execute `ALTER ROW POLICY` statement if and only if the user has **alter row policy** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.DropRowPolicy +#### RQ.SRS-006.RBAC.Privileges.DropRowPolicy version: 1.0 [ClickHouse] SHALL successfully execute `DROP ROW POLICY` statement if and only if the user has **drop row policy** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.CreateQuota +#### RQ.SRS-006.RBAC.Privileges.CreateQuota version: 1.0 [ClickHouse] SHALL successfully execute `CREATE QUOTA` statement if and only if the user has **create quota** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.AlterQuota +#### RQ.SRS-006.RBAC.Privileges.AlterQuota version: 1.0 [ClickHouse] SHALL successfully execute `ALTER QUOTA` statement if and only if the user has **alter quota** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.DropQuota +#### RQ.SRS-006.RBAC.Privileges.DropQuota version: 1.0 [ClickHouse] SHALL successfully execute `DROP QUOTA` statement if and only if the user has **drop quota** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile +#### RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile version: 1.0 [ClickHouse] SHALL successfully execute `CREATE SETTINGS PROFILE` statement if and only if the user has **create settings profile** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile +#### RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile version: 1.0 [ClickHouse] SHALL successfully execute `ALTER SETTINGS PROFILE` statement if and only if the user has **alter settings profile** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.DropSettingsProfile +#### RQ.SRS-006.RBAC.Privileges.DropSettingsProfile version: 1.0 [ClickHouse] SHALL successfully execute `DROP SETTINGS PROFILE` statement if and only if the user has **drop settings profile** privilege, or either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.RoleAdmin +#### RQ.SRS-006.RBAC.Privileges.RoleAdmin version: 1.0 [ClickHouse] SHALL successfully execute any role grant or revoke by a user with `ROLE ADMIN` privilege. -##### Show Access +#### Show Access -###### RQ.SRS-006.RBAC.ShowUsers.Privilege +##### RQ.SRS-006.RBAC.ShowUsers.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `SHOW USERS` privilege when the user is granted `SHOW USERS`, `SHOW CREATE USER`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`. -###### RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW USERS` statement if and only if the user has **show users** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE USER` statement if and only if the user has **show users** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowRoles.Privilege +##### RQ.SRS-006.RBAC.ShowRoles.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `SHOW ROLES` privilege when the user is granted `SHOW ROLES`, `SHOW CREATE ROLE`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`. -###### RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW ROLES` statement if and only if the user has **show roles** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE ROLE` statement if and only if the user has **show roles** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowRowPolicies.Privilege +##### RQ.SRS-006.RBAC.ShowRowPolicies.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `SHOW ROW POLICIES` privilege when the user is granted `SHOW ROW POLICIES`, `SHOW POLICIES`, `SHOW CREATE ROW POLICY`, `SHOW CREATE POLICY`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`. -###### RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW ROW POLICIES` or `SHOW POLICIES` statement if and only if the user has **show row policies** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE ROW POLICY` or `SHOW CREATE POLICY` statement if and only if the user has **show row policies** privilege,either directly or through a role. -###### RQ.SRS-006.RBAC.ShowQuotas.Privilege +##### RQ.SRS-006.RBAC.ShowQuotas.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `SHOW QUOTAS` privilege when the user is granted `SHOW QUOTAS`, `SHOW CREATE QUOTA`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`. -###### RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW QUOTAS` statement if and only if the user has **show quotas** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE QUOTA` statement if and only if the user has **show quotas** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege +##### RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `SHOW SETTINGS PROFILES` privilege when the user is granted `SHOW SETTINGS PROFILES`, `SHOW PROFILES`, `SHOW CREATE SETTINGS PROFILE`, `SHOW SETTINGS PROFILE`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`. -###### RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW SETTINGS PROFILES` or `SHOW PROFILES` statement if and only if the user has **show settings profiles** privilege, either directly or through a role. -###### RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege +##### RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `SHOW CREATE SETTINGS PROFILE` or `SHOW CREATE PROFILE` statement if and only if the user has **show settings profiles** privilege, either directly or through a role. -#### dictGet +### dictGet -##### RQ.SRS-006.RBAC.dictGet.Privilege +#### RQ.SRS-006.RBAC.dictGet.Privilege version: 1.0 [ClickHouse] SHALL successfully grant `dictGet` privilege when the user is granted `dictGet`, `dictHas`, `dictGetHierarchy`, or `dictIsIn`. -##### RQ.SRS-006.RBAC.dictGet.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictGet.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictGet` statement if and only if the user has **dictGet** privilege on that dictionary, either directly or through a role. -##### RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictGet[TYPE]` statement @@ -4166,270 +14199,283 @@ Available types: * UUID * String -##### RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictGetOrDefault` statement if and only if the user has **dictGet** privilege on that dictionary, either directly or through a role. -##### RQ.SRS-006.RBAC.dictHas.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictHas.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictHas` statement if and only if the user has **dictGet** privilege, either directly or through a role. -##### RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictGetHierarchy` statement if and only if the user has **dictGet** privilege, either directly or through a role. -##### RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege +#### RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege version: 1.0 [ClickHouse] SHALL successfully execute `dictIsIn` statement if and only if the user has **dictGet** privilege, either directly or through a role. -#### Introspection +### Introspection -##### RQ.SRS-006.RBAC.Privileges.Introspection +#### RQ.SRS-006.RBAC.Privileges.Introspection version: 1.0 [ClickHouse] SHALL successfully grant `INTROSPECTION` privilege when the user is granted `INTROSPECTION` or `INTROSPECTION FUNCTIONS`. -##### RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine +#### RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine version: 1.0 [ClickHouse] SHALL successfully execute `addressToLine` statement if and only if the user has **introspection** privilege, either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol +#### RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol version: 1.0 [ClickHouse] SHALL successfully execute `addressToSymbol` statement if and only if the user has **introspection** privilege, either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Introspection.demangle +#### RQ.SRS-006.RBAC.Privileges.Introspection.demangle version: 1.0 [ClickHouse] SHALL successfully execute `demangle` statement if and only if the user has **introspection** privilege, either directly or through a role. -#### System +### System -##### RQ.SRS-006.RBAC.Privileges.System.Shutdown +#### RQ.SRS-006.RBAC.Privileges.System.Shutdown version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM SHUTDOWN` privilege when the user is granted `SYSTEM`, `SYSTEM SHUTDOWN`, `SHUTDOWN`,or `SYSTEM KILL`. -##### RQ.SRS-006.RBAC.Privileges.System.DropCache +#### RQ.SRS-006.RBAC.Privileges.System.DropCache version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM DROP CACHE` privilege when the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, or `DROP CACHE`. -##### RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS +#### RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM DROP DNS CACHE` privilege when the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP DNS CACHE`, `SYSTEM DROP DNS`, `DROP DNS CACHE`, or `DROP DNS`. -##### RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark +#### RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM DROP MARK CACHE` privilege when the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP MARK CACHE`, `SYSTEM DROP MARK`, `DROP MARK CACHE`, or `DROP MARKS`. -##### RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed +#### RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM DROP UNCOMPRESSED CACHE` privilege when the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP UNCOMPRESSED CACHE`, `SYSTEM DROP UNCOMPRESSED`, `DROP UNCOMPRESSED CACHE`, or `DROP UNCOMPRESSED`. -##### RQ.SRS-006.RBAC.Privileges.System.Reload +#### RQ.SRS-006.RBAC.Privileges.System.Reload version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RELOAD` privilege when the user is granted `SYSTEM` or `SYSTEM RELOAD`. -##### RQ.SRS-006.RBAC.Privileges.System.Reload.Config +#### RQ.SRS-006.RBAC.Privileges.System.Reload.Config version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RELOAD CONFIG` privilege when the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD CONFIG`, or `RELOAD CONFIG`. -##### RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary +#### RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RELOAD DICTIONARY` privilege when the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARIES`, `RELOAD DICTIONARIES`, or `RELOAD DICTIONARY`. -##### RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries +#### RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RELOAD DICTIONARIES` privilege when the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARIES`, `RELOAD DICTIONARIES`, or `RELOAD DICTIONARY`. -##### RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries +#### RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RELOAD EMBEDDED DICTIONARIES` privilege when the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARY ON *.*`, or `SYSTEM RELOAD EMBEDDED DICTIONARIES`. -##### RQ.SRS-006.RBAC.Privileges.System.Merges +#### RQ.SRS-006.RBAC.Privileges.System.Merges version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM MERGES` privilege when the user is granted `SYSTEM`, `SYSTEM MERGES`, `SYSTEM STOP MERGES`, `SYSTEM START MERGES`, `STOP MERGES`, or `START MERGES`. -##### RQ.SRS-006.RBAC.Privileges.System.TTLMerges +#### RQ.SRS-006.RBAC.Privileges.System.TTLMerges version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM TTL MERGES` privilege when the user is granted `SYSTEM`, `SYSTEM TTL MERGES`, `SYSTEM STOP TTL MERGES`, `SYSTEM START TTL MERGES`, `STOP TTL MERGES`, or `START TTL MERGES`. -##### RQ.SRS-006.RBAC.Privileges.System.Fetches +#### RQ.SRS-006.RBAC.Privileges.System.Fetches version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM FETCHES` privilege when the user is granted `SYSTEM`, `SYSTEM FETCHES`, `SYSTEM STOP FETCHES`, `SYSTEM START FETCHES`, `STOP FETCHES`, or `START FETCHES`. -##### RQ.SRS-006.RBAC.Privileges.System.Moves +#### RQ.SRS-006.RBAC.Privileges.System.Moves version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM MOVES` privilege when the user is granted `SYSTEM`, `SYSTEM MOVES`, `SYSTEM STOP MOVES`, `SYSTEM START MOVES`, `STOP MOVES`, or `START MOVES`. -##### RQ.SRS-006.RBAC.Privileges.System.Sends +#### RQ.SRS-006.RBAC.Privileges.System.Sends version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM SENDS` privilege when the user is granted `SYSTEM`, `SYSTEM SENDS`, `SYSTEM STOP SENDS`, `SYSTEM START SENDS`, `STOP SENDS`, or `START SENDS`. -##### RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed +#### RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM DISTRIBUTED SENDS` privilege when the user is granted `SYSTEM`, `SYSTEM DISTRIBUTED SENDS`, `SYSTEM STOP DISTRIBUTED SENDS`, `SYSTEM START DISTRIBUTED SENDS`, `STOP DISTRIBUTED SENDS`, or `START DISTRIBUTED SENDS`. -##### RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated +#### RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM REPLICATED SENDS` privilege when the user is granted `SYSTEM`, `SYSTEM REPLICATED SENDS`, `SYSTEM STOP REPLICATED SENDS`, `SYSTEM START REPLICATED SENDS`, `STOP REPLICATED SENDS`, or `START REPLICATED SENDS`. -##### RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues +#### RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM REPLICATION QUEUES` privilege when the user is granted `SYSTEM`, `SYSTEM REPLICATION QUEUES`, `SYSTEM STOP REPLICATION QUEUES`, `SYSTEM START REPLICATION QUEUES`, `STOP REPLICATION QUEUES`, or `START REPLICATION QUEUES`. -##### RQ.SRS-006.RBAC.Privileges.System.SyncReplica +#### RQ.SRS-006.RBAC.Privileges.System.SyncReplica version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM SYNC REPLICA` privilege when the user is granted `SYSTEM`, `SYSTEM SYNC REPLICA`, or `SYNC REPLICA`. -##### RQ.SRS-006.RBAC.Privileges.System.RestartReplica +#### RQ.SRS-006.RBAC.Privileges.System.RestartReplica version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM RESTART REPLICA` privilege when the user is granted `SYSTEM`, `SYSTEM RESTART REPLICA`, or `RESTART REPLICA`. -##### RQ.SRS-006.RBAC.Privileges.System.Flush +#### RQ.SRS-006.RBAC.Privileges.System.Flush version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM FLUSH` privilege when the user is granted `SYSTEM` or `SYSTEM FLUSH`. -##### RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed +#### RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM FLUSH DISTRIBUTED` privilege when the user is granted `SYSTEM`, `SYSTEM FLUSH DISTRIBUTED`, or `FLUSH DISTRIBUTED`. -##### RQ.SRS-006.RBAC.Privileges.System.Flush.Logs +#### RQ.SRS-006.RBAC.Privileges.System.Flush.Logs version: 1.0 [ClickHouse] SHALL successfully grant `SYSTEM FLUSH LOGS` privilege when the user is granted `SYSTEM`, `SYSTEM FLUSH LOGS`, or `FLUSH LOGS`. -#### Sources +### Sources -##### RQ.SRS-006.RBAC.Privileges.Sources +#### RQ.SRS-006.RBAC.Privileges.Sources version: 1.0 [ClickHouse] SHALL support granting or revoking `SOURCES` privilege from the user, either directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.File +#### RQ.SRS-006.RBAC.Privileges.Sources.File version: 1.0 [ClickHouse] SHALL support the use of `FILE` source by a user if and only if the user has `FILE` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.URL +#### RQ.SRS-006.RBAC.Privileges.Sources.URL version: 1.0 [ClickHouse] SHALL support the use of `URL` source by a user if and only if the user has `URL` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.Remote +#### RQ.SRS-006.RBAC.Privileges.Sources.Remote version: 1.0 [ClickHouse] SHALL support the use of `REMOTE` source by a user if and only if the user has `REMOTE` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.MySQL +#### RQ.SRS-006.RBAC.Privileges.Sources.MySQL version: 1.0 [ClickHouse] SHALL support the use of `MySQL` source by a user if and only if the user has `MySQL` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.ODBC +#### RQ.SRS-006.RBAC.Privileges.Sources.ODBC version: 1.0 [ClickHouse] SHALL support the use of `ODBC` source by a user if and only if the user has `ODBC` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.JDBC +#### RQ.SRS-006.RBAC.Privileges.Sources.JDBC version: 1.0 [ClickHouse] SHALL support the use of `JDBC` source by a user if and only if the user has `JDBC` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.HDFS +#### RQ.SRS-006.RBAC.Privileges.Sources.HDFS version: 1.0 [ClickHouse] SHALL support the use of `HDFS` source by a user if and only if the user has `HDFS` or `SOURCES` privileges granted to them directly or through a role. -##### RQ.SRS-006.RBAC.Privileges.Sources.S3 +#### RQ.SRS-006.RBAC.Privileges.Sources.S3 version: 1.0 [ClickHouse] SHALL support the use of `S3` source by a user if and only if the user has `S3` or `SOURCES` privileges granted to them directly or through a role. -#### RQ.SRS-006.RBAC.Privileges.GrantOption +### RQ.SRS-006.RBAC.Privileges.GrantOption version: 1.0 [ClickHouse] SHALL successfully execute `GRANT` or `REVOKE` privilege statements by a user if and only if the user has that privilege with `GRANT OPTION`, either directly or through a role. -#### RQ.SRS-006.RBAC.Privileges.All +### RQ.SRS-006.RBAC.Privileges.All version: 1.0 -[ClickHouse] SHALL support granting or revoking `ALL` privilege. +[ClickHouse] SHALL support granting or revoking `ALL` privilege +using `GRANT ALL ON *.* TO user`. -#### RQ.SRS-006.RBAC.Privileges.AdminOption +### RQ.SRS-006.RBAC.Privileges.RoleAll +version: 1.0 + +[ClickHouse] SHALL support granting a role named `ALL` using `GRANT ALL TO user`. +This shall only grant the user the privileges that have been granted to the role. + +### RQ.SRS-006.RBAC.Privileges.None +version: 1.0 + +[ClickHouse] SHALL support granting or revoking `NONE` privilege +using `GRANT NONE TO user` or `GRANT USAGE ON *.* TO user`. + +### RQ.SRS-006.RBAC.Privileges.AdminOption version: 1.0 [ClickHouse] SHALL support a user granting or revoking a role if and only if @@ -4451,7845 +14497,3 @@ the user has that role with `ADMIN OPTION` privilege. [MySQL]: https://dev.mysql.com/doc/refman/8.0/en/account-management-statements.html [PostgreSQL]: https://www.postgresql.org/docs/12/user-manag.html ''') - -RQ_SRS_006_RBAC = Requirement( - name='RQ.SRS-006.RBAC', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support role based access control.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Login = Requirement( - name='RQ.SRS-006.RBAC.Login', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only allow access to the server for a given\n' - 'user only when correct username and password are used during\n' - 'the connection to the server.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Login_DefaultUser = Requirement( - name='RQ.SRS-006.RBAC.Login.DefaultUser', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL use the **default user** when no username and password\n' - 'are specified during the connection to the server.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User = Requirement( - name='RQ.SRS-006.RBAC.User', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creation and manipulation of\n' - 'one or more **user** accounts to which roles, privileges,\n' - 'settings profile, quotas and row policies can be assigned.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Roles = Requirement( - name='RQ.SRS-006.RBAC.User.Roles', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more **roles**\n' - 'to a **user**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Privileges = Requirement( - name='RQ.SRS-006.RBAC.User.Privileges', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more privileges to a **user**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Variables = Requirement( - name='RQ.SRS-006.RBAC.User.Variables', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more variables to a **user**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Variables_Constraints = Requirement( - name='RQ.SRS-006.RBAC.User.Variables.Constraints', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning min, max and read-only constraints\n' - 'for the variables that can be set and read by the **user**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_SettingsProfile = Requirement( - name='RQ.SRS-006.RBAC.User.SettingsProfile', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more **settings profiles**\n' - 'to a **user**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Quotas = Requirement( - name='RQ.SRS-006.RBAC.User.Quotas', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more **quotas** to a **user**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_RowPolicies = Requirement( - name='RQ.SRS-006.RBAC.User.RowPolicies', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more **row policies** to a **user**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_AccountLock = Requirement( - name='RQ.SRS-006.RBAC.User.AccountLock', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support locking and unlocking of **user** accounts.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_AccountLock_DenyAccess = Requirement( - name='RQ.SRS-006.RBAC.User.AccountLock.DenyAccess', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL deny access to the user whose account is locked.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_DefaultRole = Requirement( - name='RQ.SRS-006.RBAC.User.DefaultRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning a default role to a **user**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_RoleSelection = Requirement( - name='RQ.SRS-006.RBAC.User.RoleSelection', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support selection of one or more **roles** from the available roles\n' - 'that are assigned to a **user**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_ShowCreate = Requirement( - name='RQ.SRS-006.RBAC.User.ShowCreate', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the command of how **user** account was created.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_ShowPrivileges = Requirement( - name='RQ.SRS-006.RBAC.User.ShowPrivileges', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support listing the privileges of the **user**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role = Requirement( - name='RQ.SRS-006.RBAC.Role', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClikHouse] SHALL support creation and manipulation of **roles**\n' - 'to which privileges, settings profile, quotas and row policies can be\n' - 'assigned.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Privileges = Requirement( - name='RQ.SRS-006.RBAC.Role.Privileges', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more privileges to a **role**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Variables = Requirement( - name='RQ.SRS-006.RBAC.Role.Variables', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more variables to a **role**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_SettingsProfile = Requirement( - name='RQ.SRS-006.RBAC.Role.SettingsProfile', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more **settings profiles**\n' - 'to a **role**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Quotas = Requirement( - name='RQ.SRS-006.RBAC.Role.Quotas', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more **quotas** to a **role**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_RowPolicies = Requirement( - name='RQ.SRS-006.RBAC.Role.RowPolicies', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning one or more **row policies** to a **role**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_PartialRevokes = Requirement( - name='RQ.SRS-006.RBAC.PartialRevokes', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support partial revoking of privileges granted\n' - 'to a **user** or a **role**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creation and manipulation of **settings profiles**\n' - 'that can include value definition for one or more variables and can\n' - 'can be assigned to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Constraints = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Constraints', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning min, max and read-only constraints\n' - 'for the variables specified in the **settings profile**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_ShowCreate = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.ShowCreate', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the command of how **setting profile** was created.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quotas = Requirement( - name='RQ.SRS-006.RBAC.Quotas', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creation and manipulation of **quotas**\n' - 'that can be used to limit resource usage by a **user** or a **role**\n' - 'over a period of time.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quotas_Keyed = Requirement( - name='RQ.SRS-006.RBAC.Quotas.Keyed', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creating **quotas** that are keyed\n' - 'so that a quota is tracked separately for each key value.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quotas_Queries = Requirement( - name='RQ.SRS-006.RBAC.Quotas.Queries', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting **queries** quota to limit the total number of requests.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quotas_Errors = Requirement( - name='RQ.SRS-006.RBAC.Quotas.Errors', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting **errors** quota to limit the number of queries that threw an exception.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quotas_ResultRows = Requirement( - name='RQ.SRS-006.RBAC.Quotas.ResultRows', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting **result rows** quota to limit the\n' - 'the total number of rows given as the result.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quotas_ReadRows = Requirement( - name='RQ.SRS-006.RBAC.Quotas.ReadRows', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting **read rows** quota to limit the total\n' - 'number of source rows read from tables for running the query on all remote servers.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quotas_ResultBytes = Requirement( - name='RQ.SRS-006.RBAC.Quotas.ResultBytes', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting **result bytes** quota to limit the total number\n' - 'of bytes that can be returned as the result.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quotas_ReadBytes = Requirement( - name='RQ.SRS-006.RBAC.Quotas.ReadBytes', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting **read bytes** quota to limit the total number\n' - 'of source bytes read from tables for running the query on all remote servers.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quotas_ExecutionTime = Requirement( - name='RQ.SRS-006.RBAC.Quotas.ExecutionTime', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting **execution time** quota to limit the maximum\n' - 'query execution time.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quotas_ShowCreate = Requirement( - name='RQ.SRS-006.RBAC.Quotas.ShowCreate', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the command of how **quota** was created.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creation and manipulation of table **row policies**\n' - 'that can be used to limit access to the table contents for a **user** or a **role**\n' - 'using a specified **condition**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Condition = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Condition', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support row policy **conditions** that can be any SQL\n' - 'expression that returns a boolean.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_ShowCreate = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.ShowCreate', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the command of how **row policy** was created.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Use_DefaultRole = Requirement( - name='RQ.SRS-006.RBAC.User.Use.DefaultRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL by default use default role or roles assigned\n' - 'to the user if specified.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Use_AllRolesWhenNoDefaultRole = Requirement( - name='RQ.SRS-006.RBAC.User.Use.AllRolesWhenNoDefaultRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL by default use all the roles assigned to the user\n' - 'if no default role or roles are specified for the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create = Requirement( - name='RQ.SRS-006.RBAC.User.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creating **user** accounts using `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_IfNotExists = Requirement( - name='RQ.SRS-006.RBAC.User.Create.IfNotExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `IF NOT EXISTS` clause in the `CREATE USER` statement\n' - 'to skip raising an exception if a user with the same **name** already exists.\n' - 'If the `IF NOT EXISTS` clause is not specified then an exception SHALL be\n' - 'raised if a user with the same **name** already exists.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Replace = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Replace', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `OR REPLACE` clause in the `CREATE USER` statement\n' - 'to replace existing user account if already exists.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_NoPassword = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.NoPassword', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying no password when creating\n' - 'user account using `IDENTIFIED WITH NO_PASSWORD` clause .\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_NoPassword_Login = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.NoPassword.Login', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL use no password for the user when connecting to the server\n' - 'when an account was created with `IDENTIFIED WITH NO_PASSWORD` clause.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_PlainText = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.PlainText', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying plaintext password when creating\n' - 'user account using `IDENTIFIED WITH PLAINTEXT_PASSWORD BY` clause.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_PlainText_Login = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.PlainText.Login', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL use the plaintext password passed by the user when connecting to the server\n' - 'when an account was created with `IDENTIFIED WITH PLAINTEXT_PASSWORD` clause\n' - 'and compare the password with the one used in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_Sha256Password = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Password', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying the result of applying SHA256\n' - 'to some password when creating user account using `IDENTIFIED WITH SHA256_PASSWORD BY` or `IDENTIFIED BY`\n' - 'clause.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_Sha256Password_Login = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Password.Login', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL calculate `SHA256` of the password passed by the user when connecting to the server\n' - "when an account was created with `IDENTIFIED WITH SHA256_PASSWORD` or with 'IDENTIFIED BY' clause\n" - 'and compare the calculated hash to the one used in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_Sha256Hash = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying the result of applying SHA256\n' - 'to some already calculated hash when creating user account using `IDENTIFIED WITH SHA256_HASH`\n' - 'clause.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_Sha256Hash_Login = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.Sha256Hash.Login', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL calculate `SHA256` of the already calculated hash passed by\n' - 'the user when connecting to the server\n' - 'when an account was created with `IDENTIFIED WITH SHA256_HASH` clause\n' - 'and compare the calculated hash to the one used in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Password = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying the result of applying SHA1 two times\n' - 'to a password when creating user account using `IDENTIFIED WITH DOUBLE_SHA1_PASSWORD`\n' - 'clause.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Password_Login = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Password.Login', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL calculate `SHA1` two times over the password passed by\n' - 'the user when connecting to the server\n' - 'when an account was created with `IDENTIFIED WITH DOUBLE_SHA1_PASSWORD` clause\n' - 'and compare the calculated value to the one used in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Hash = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying the result of applying SHA1 two times\n' - 'to a hash when creating user account using `IDENTIFIED WITH DOUBLE_SHA1_HASH`\n' - 'clause.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Hash_Login = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Password.DoubleSha1Hash.Login', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL calculate `SHA1` two times over the hash passed by\n' - 'the user when connecting to the server\n' - 'when an account was created with `IDENTIFIED WITH DOUBLE_SHA1_HASH` clause\n' - 'and compare the calculated value to the one used in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Host_Name = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Host.Name', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying one or more hostnames from\n' - 'which user can access the server using the `HOST NAME` clause\n' - 'in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Host_Regexp = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Host.Regexp', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying one or more regular expressions\n' - 'to match hostnames from which user can access the server\n' - 'using the `HOST REGEXP` clause in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Host_IP = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Host.IP', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying one or more IP address or subnet from\n' - 'which user can access the server using the `HOST IP` clause in the\n' - '`CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Host_Any = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Host.Any', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying `HOST ANY` clause in the `CREATE USER` statement\n' - 'to indicate that user can access the server from any host.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Host_None = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Host.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support fobidding access from any host using `HOST NONE` clause in the\n' - '`CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Host_Local = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Host.Local', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting user access to local only using `HOST LOCAL` clause in the\n' - '`CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Host_Like = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Host.Like', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying host using `LIKE` command syntax using the\n' - '`HOST LIKE` clause in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Host_Default = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Host.Default', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support user access to server from any host\n' - 'if no `HOST` clause is specified in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_DefaultRole = Requirement( - name='RQ.SRS-006.RBAC.User.Create.DefaultRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying one or more default roles\n' - 'using `DEFAULT ROLE` clause in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_DefaultRole_None = Requirement( - name='RQ.SRS-006.RBAC.User.Create.DefaultRole.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying no default roles\n' - 'using `DEFAULT ROLE NONE` clause in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_DefaultRole_All = Requirement( - name='RQ.SRS-006.RBAC.User.Create.DefaultRole.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying all roles to be used as default\n' - 'using `DEFAULT ROLE ALL` clause in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Settings = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Settings', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying settings and profile\n' - 'using `SETTINGS` clause in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_OnCluster = Requirement( - name='RQ.SRS-006.RBAC.User.Create.OnCluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying cluster on which the user\n' - 'will be created using `ON CLUSTER` clause in the `CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Create_Syntax = Requirement( - name='RQ.SRS-006.RBAC.User.Create.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for `CREATE USER` statement.\n' - '\n' - '```sql\n' - 'CREATE USER [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name]\n' - " [IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH}] BY {'password'|'hash'}]\n" - " [HOST {LOCAL | NAME 'name' | NAME REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]\n" - ' [DEFAULT ROLE role [,...]]\n' - " [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]\n" - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter = Requirement( - name='RQ.SRS-006.RBAC.User.Alter', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering **user** accounts using `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_OrderOfEvaluation = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.OrderOfEvaluation', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support evaluating `ALTER USER` statement from left to right\n' - 'where things defined on the right override anything that was previously defined on\n' - 'the left.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_IfExists = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.IfExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `IF EXISTS` clause in the `ALTER USER` statement\n' - 'to skip raising an exception (producing a warning instead) if a user with the specified **name** does not exist. If the `IF EXISTS` clause is not specified then an exception SHALL be raised if a user with the **name** does not exist.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Cluster = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying the cluster the user is on\n' - 'when altering user account using `ON CLUSTER` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Rename = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Rename', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying a new name for the user when\n' - 'altering user account using `RENAME` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Password_PlainText = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Password.PlainText', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying plaintext password when altering\n' - 'user account using `IDENTIFIED WITH PLAINTEXT_PASSWORD BY` or\n' - 'using shorthand `IDENTIFIED BY` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Password_Sha256Password = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Password.Sha256Password', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying the result of applying SHA256\n' - 'to some password as identification when altering user account using\n' - '`IDENTIFIED WITH SHA256_PASSWORD` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Password_DoubleSha1Password = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Password.DoubleSha1Password', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying the result of applying Double SHA1\n' - 'to some password as identification when altering user account using\n' - '`IDENTIFIED WITH DOUBLE_SHA1_PASSWORD` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Host_AddDrop = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Host.AddDrop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering user by adding and dropping access to hosts with the `ADD HOST` or the `DROP HOST`in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Host_Local = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Host.Local', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting user access to local only using `HOST LOCAL` clause in the\n' - '`ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Host_Name = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Host.Name', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying one or more hostnames from\n' - 'which user can access the server using the `HOST NAME` clause\n' - 'in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Host_Regexp = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Host.Regexp', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying one or more regular expressions\n' - 'to match hostnames from which user can access the server\n' - 'using the `HOST REGEXP` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Host_IP = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Host.IP', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying one or more IP address or subnet from\n' - 'which user can access the server using the `HOST IP` clause in the\n' - '`ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Host_Like = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Host.Like', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying sone or more similar hosts using `LIKE` command syntax using the `HOST LIKE` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Host_Any = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Host.Any', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying `HOST ANY` clause in the `ALTER USER` statement\n' - 'to indicate that user can access the server from any host.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Host_None = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Host.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support fobidding access from any host using `HOST NONE` clause in the\n' - '`ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_DefaultRole = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.DefaultRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying one or more default roles\n' - 'using `DEFAULT ROLE` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_DefaultRole_All = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.DefaultRole.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying all roles to be used as default\n' - 'using `DEFAULT ROLE ALL` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_DefaultRole_AllExcept = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.DefaultRole.AllExcept', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying one or more roles which will not be used as default\n' - 'using `DEFAULT ROLE ALL EXCEPT` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Settings = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Settings', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying one or more variables\n' - 'using `SETTINGS` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Settings_Min = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Settings.Min', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying a minimum value for the variable specifed using `SETTINGS` with `MIN` clause in the `ALTER USER` statement.\n' - '\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Settings_Max = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Settings.Max', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying a maximum value for the variable specifed using `SETTINGS` with `MAX` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Settings_Profile = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Settings.Profile', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying the name of a profile for the variable specifed using `SETTINGS` with `PROFILE` clause in the `ALTER USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Alter_Syntax = Requirement( - name='RQ.SRS-006.RBAC.User.Alter.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `ALTER USER` statement.\n' - '\n' - '```sql\n' - 'ALTER USER [IF EXISTS] name [ON CLUSTER cluster_name]\n' - ' [RENAME TO new_name]\n' - " [IDENTIFIED [WITH {PLAINTEXT_PASSWORD|SHA256_PASSWORD|DOUBLE_SHA1_PASSWORD}] BY {'password'|'hash'}]\n" - " [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]\n" - ' [DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]\n' - " [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]\n" - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetDefaultRole = Requirement( - name='RQ.SRS-006.RBAC.SetDefaultRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting or changing granted roles to default for one or more\n' - 'users using `SET DEFAULT ROLE` statement which\n' - 'SHALL permanently change the default roles for the user or users if successful.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetDefaultRole_CurrentUser = Requirement( - name='RQ.SRS-006.RBAC.SetDefaultRole.CurrentUser', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting or changing granted roles to default for\n' - 'the current user using `CURRENT_USER` clause in the `SET DEFAULT ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetDefaultRole_All = Requirement( - name='RQ.SRS-006.RBAC.SetDefaultRole.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting or changing all granted roles to default\n' - 'for one or more users using `ALL` clause in the `SET DEFAULT ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetDefaultRole_AllExcept = Requirement( - name='RQ.SRS-006.RBAC.SetDefaultRole.AllExcept', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting or changing all granted roles except those specified\n' - 'to default for one or more users using `ALL EXCEPT` clause in the `SET DEFAULT ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetDefaultRole_None = Requirement( - name='RQ.SRS-006.RBAC.SetDefaultRole.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support removing all granted roles from default\n' - 'for one or more users using `NONE` clause in the `SET DEFAULT ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetDefaultRole_Syntax = Requirement( - name='RQ.SRS-006.RBAC.SetDefaultRole.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `SET DEFAULT ROLE` statement.\n' - '\n' - '```sql\n' - 'SET DEFAULT ROLE\n' - ' {NONE | role [,...] | ALL | ALL EXCEPT role [,...]}\n' - ' TO {user|CURRENT_USER} [,...]\n' - '\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetRole = Requirement( - name='RQ.SRS-006.RBAC.SetRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support activating role or roles for the current user\n' - 'using `SET ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetRole_Default = Requirement( - name='RQ.SRS-006.RBAC.SetRole.Default', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support activating default roles for the current user\n' - 'using `DEFAULT` clause in the `SET ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetRole_None = Requirement( - name='RQ.SRS-006.RBAC.SetRole.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support activating no roles for the current user\n' - 'using `NONE` clause in the `SET ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetRole_All = Requirement( - name='RQ.SRS-006.RBAC.SetRole.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support activating all roles for the current user\n' - 'using `ALL` clause in the `SET ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetRole_AllExcept = Requirement( - name='RQ.SRS-006.RBAC.SetRole.AllExcept', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support activating all roles except those specified\n' - 'for the current user using `ALL EXCEPT` clause in the `SET ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SetRole_Syntax = Requirement( - name='RQ.SRS-006.RBAC.SetRole.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '```sql\n' - 'SET ROLE {DEFAULT | NONE | role [,...] | ALL | ALL EXCEPT role [,...]}\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_ShowCreateUser = Requirement( - name='RQ.SRS-006.RBAC.User.ShowCreateUser', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the `CREATE USER` statement used to create the current user object\n' - 'using the `SHOW CREATE USER` statement with `CURRENT_USER` or no argument.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_ShowCreateUser_For = Requirement( - name='RQ.SRS-006.RBAC.User.ShowCreateUser.For', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the `CREATE USER` statement used to create the specified user object\n' - 'using the `FOR` clause in the `SHOW CREATE USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_ShowCreateUser_Syntax = Requirement( - name='RQ.SRS-006.RBAC.User.ShowCreateUser.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the following syntax for `SHOW CREATE USER` statement.\n' - '\n' - '```sql\n' - 'SHOW CREATE USER [name | CURRENT_USER]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Drop = Requirement( - name='RQ.SRS-006.RBAC.User.Drop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support removing a user account using `DROP USER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Drop_IfExists = Requirement( - name='RQ.SRS-006.RBAC.User.Drop.IfExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support using `IF EXISTS` clause in the `DROP USER` statement\n' - 'to skip raising an exception if the user account does not exist.\n' - 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' - 'raised if a user does not exist.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Drop_OnCluster = Requirement( - name='RQ.SRS-006.RBAC.User.Drop.OnCluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support using `ON CLUSTER` clause in the `DROP USER` statement\n' - 'to specify the name of the cluster the user should be dropped from.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_User_Drop_Syntax = Requirement( - name='RQ.SRS-006.RBAC.User.Drop.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for `DROP USER` statement\n' - '\n' - '```sql\n' - 'DROP USER [IF EXISTS] name [,...] [ON CLUSTER cluster_name]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Create = Requirement( - name='RQ.SRS-006.RBAC.Role.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creating a **role** using `CREATE ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Create_IfNotExists = Requirement( - name='RQ.SRS-006.RBAC.Role.Create.IfNotExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `IF NOT EXISTS` clause in the `CREATE ROLE` statement\n' - 'to raising an exception if a role with the same **name** already exists.\n' - 'If the `IF NOT EXISTS` clause is not specified then an exception SHALL be\n' - 'raised if a role with the same **name** already exists.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Create_Replace = Requirement( - name='RQ.SRS-006.RBAC.Role.Create.Replace', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `OR REPLACE` clause in the `CREATE ROLE` statement\n' - 'to replace existing role if it already exists.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Create_Settings = Requirement( - name='RQ.SRS-006.RBAC.Role.Create.Settings', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying settings and profile using `SETTINGS`\n' - 'clause in the `CREATE ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Create_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Role.Create.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `CREATE ROLE` statement\n' - '\n' - '``` sql\n' - 'CREATE ROLE [IF NOT EXISTS | OR REPLACE] name\n' - " [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]\n" - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Alter = Requirement( - name='RQ.SRS-006.RBAC.Role.Alter', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering one **role** using `ALTER ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Alter_IfExists = Requirement( - name='RQ.SRS-006.RBAC.Role.Alter.IfExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering one **role** using `ALTER ROLE IF EXISTS` statement, where no exception\n' - 'will be thrown if the role does not exist.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Alter_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Role.Alter.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering one **role** using `ALTER ROLE role ON CLUSTER` statement to specify the\n' - 'cluster location of the specified role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Alter_Rename = Requirement( - name='RQ.SRS-006.RBAC.Role.Alter.Rename', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering one **role** using `ALTER ROLE role RENAME TO` statement which renames the\n' - 'role to a specified new name. If the new name already exists, that an exception SHALL be raised unless the\n' - '`IF EXISTS` clause is specified, by which no exception will be raised and nothing will change.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Alter_Settings = Requirement( - name='RQ.SRS-006.RBAC.Role.Alter.Settings', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering the settings of one **role** using `ALTER ROLE role SETTINGS ...` statement.\n' - 'Altering variable values, creating max and min values, specifying readonly or writable, and specifying the\n' - 'profiles for which this alter change shall be applied to, are all supported, using the following syntax.\n' - '\n' - '```sql\n' - "[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]\n" - '```\n' - '\n' - 'One or more variables and profiles may be specified as shown above.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Alter_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Role.Alter.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '```sql\n' - 'ALTER ROLE [IF EXISTS] name [ON CLUSTER cluster_name]\n' - ' [RENAME TO new_name]\n' - " [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]\n" - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Drop = Requirement( - name='RQ.SRS-006.RBAC.Role.Drop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support removing one or more roles using `DROP ROLE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Drop_IfExists = Requirement( - name='RQ.SRS-006.RBAC.Role.Drop.IfExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support using `IF EXISTS` clause in the `DROP ROLE` statement\n' - 'to skip raising an exception if the role does not exist.\n' - 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' - 'raised if a role does not exist.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Drop_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Role.Drop.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support using `ON CLUSTER` clause in the `DROP ROLE` statement to specify the cluster from which to drop the specified role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_Drop_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Role.Drop.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `DROP ROLE` statement\n' - '\n' - '``` sql\n' - 'DROP ROLE [IF EXISTS] name [,...] [ON CLUSTER cluster_name]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_ShowCreate = Requirement( - name='RQ.SRS-006.RBAC.Role.ShowCreate', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support viewing the settings for a role upon creation with the `SHOW CREATE ROLE`\n' - 'statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Role_ShowCreate_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Role.ShowCreate.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `SHOW CREATE ROLE` command.\n' - '\n' - '```sql\n' - 'SHOW CREATE ROLE name\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_To = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.To', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting privileges to one or more users or roles using `TO` clause\n' - 'in the `GRANT PRIVILEGE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_ToCurrentUser = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.ToCurrentUser', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting privileges to current user using `TO CURRENT_USER` clause\n' - 'in the `GRANT PRIVILEGE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Select = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Select', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **select** privilege to one or more users or roles\n' - 'for a database or a table using the `GRANT SELECT` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Insert = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Insert', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **insert** privilege to one or more users or roles\n' - 'for a database or a table using the `GRANT INSERT` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Alter = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Alter', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **alter** privilege to one or more users or roles\n' - 'for a database or a table using the `GRANT ALTER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Create = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **create** privilege to one or more users or roles\n' - 'using the `GRANT CREATE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Drop = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Drop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **drop** privilege to one or more users or roles\n' - 'using the `GRANT DROP` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Truncate = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Truncate', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **truncate** privilege to one or more users or roles\n' - 'for a database or a table using `GRANT TRUNCATE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Optimize = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Optimize', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **optimize** privilege to one or more users or roles\n' - 'for a database or a table using `GRANT OPTIMIZE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Show = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Show', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **show** privilege to one or more users or roles\n' - 'for a database or a table using `GRANT SHOW` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_KillQuery = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.KillQuery', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **kill query** privilege to one or more users or roles\n' - 'for a database or a table using `GRANT KILL QUERY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_AccessManagement = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.AccessManagement', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **access management** privileges to one or more users or roles\n' - 'for a database or a table using `GRANT ACCESS MANAGEMENT` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_System = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.System', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **system** privileges to one or more users or roles\n' - 'for a database or a table using `GRANT SYSTEM` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Introspection = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Introspection', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **introspection** privileges to one or more users or roles\n' - 'for a database or a table using `GRANT INTROSPECTION` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Sources = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Sources', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **sources** privileges to one or more users or roles\n' - 'for a database or a table using `GRANT SOURCES` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_DictGet = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.DictGet', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **dictGet** privilege to one or more users or roles\n' - 'for a database or a table using `GRANT dictGet` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_None = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting no privileges to one or more users or roles\n' - 'for a database or a table using `GRANT NONE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_All = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **all** privileges to one or more users or roles\n' - 'for a database or a table using the `GRANT ALL` or `GRANT ALL PRIVILEGES` statements.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_GrantOption = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.GrantOption', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the **grant option** privilege to one or more users or roles\n' - 'for a database or a table using the `WITH GRANT OPTION` clause in the `GRANT` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_On = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.On', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the `ON` clause in the `GRANT` privilege statement\n' - 'which SHALL allow to specify one or more tables to which the privilege SHALL\n' - 'be granted using the following patterns\n' - '\n' - '* `*.*` any table in any database\n' - '* `database.*` any table in the specified database\n' - '* `database.table` specific table in the specified database\n' - '* `*` any table in the current database\n' - '* `table` specific table in the current database\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_PrivilegeColumns = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.PrivilegeColumns', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting the privilege **some_privilege** to one or more users or roles\n' - 'for a database or a table using the `GRANT some_privilege(column)` statement for one column.\n' - 'Multiple columns will be supported with `GRANT some_privilege(column1, column2...)` statement.\n' - 'The privileges will be granted for only the specified columns.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_OnCluster = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.OnCluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying cluster on which to grant privileges using the `ON CLUSTER`\n' - 'clause in the `GRANT PRIVILEGE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Privilege_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Grant.Privilege.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `GRANT` statement that\n' - 'grants explicit privileges to a user or a role.\n' - '\n' - '```sql\n' - 'GRANT [ON CLUSTER cluster_name] privilege[(column_name [,...])] [,...]\n' - ' ON {db.table|db.*|*.*|table|*}\n' - ' TO {user | role | CURRENT_USER} [,...]\n' - ' [WITH GRANT OPTION]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking privileges to one or more users or roles\n' - 'for a database or a table on some specific cluster using the `REVOKE ON CLUSTER cluster_name` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Any = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Any', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking ANY privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE some_privilege` statement.\n' - '**some_privilege** refers to any Clickhouse defined privilege, whose hierarchy includes\n' - 'SELECT, INSERT, ALTER, CREATE, DROP, TRUNCATE, OPTIMIZE, SHOW, KILL QUERY, ACCESS MANAGEMENT,\n' - 'SYSTEM, INTROSPECTION, SOURCES, dictGet and all of their sub-privileges.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Select = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Select', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **select** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE SELECT` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Insert = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Insert', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **insert** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE INSERT` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Alter = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Alter', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **alter** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE ALTER` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Create = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **create** privilege to one or more users or roles\n' - 'using the `REVOKE CREATE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Drop = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Drop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **drop** privilege to one or more users or roles\n' - 'using the `REVOKE DROP` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Truncate = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Truncate', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **truncate** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE TRUNCATE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Optimize = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Optimize', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **optimize** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE OPTIMIZE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Show = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Show', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **show** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE SHOW` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_KillQuery = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.KillQuery', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **kill query** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE KILL QUERY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_AccessManagement = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.AccessManagement', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **access management** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE ACCESS MANAGEMENT` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_System = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.System', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **system** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE SYSTEM` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Introspection = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Introspection', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **introspection** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE INTROSPECTION` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Sources = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Sources', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **sources** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE SOURCES` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_DictGet = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.DictGet', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the **dictGet** privilege to one or more users or roles\n' - 'for a database or a table using the `REVOKE dictGet` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_PrivelegeColumns = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.PrivelegeColumns', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking the privilege **some_privilege** to one or more users or roles\n' - 'for a database or a table using the `REVOKE some_privilege(column)` statement for one column.\n' - 'Multiple columns will be supported with `REVOKE some_privilege(column1, column2...)` statement.\n' - 'The privileges will be revoked for only the specified columns.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Multiple = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Multiple', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking MULTIPLE **privileges** to one or more users or roles\n' - 'for a database or a table using the `REVOKE privilege1, privilege2...` statement.\n' - '**privileges** refers to any set of Clickhouse defined privilege, whose hierarchy includes\n' - 'SELECT, INSERT, ALTER, CREATE, DROP, TRUNCATE, OPTIMIZE, SHOW, KILL QUERY, ACCESS MANAGEMENT,\n' - 'SYSTEM, INTROSPECTION, SOURCES, dictGet and all of their sub-privileges.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_All = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **all** privileges to one or more users or roles\n' - 'for a database or a table using the `REVOKE ALL` or `REVOKE ALL PRIVILEGES` statements.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_None = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **no** privileges to one or more users or roles\n' - 'for a database or a table using the `REVOKE NONE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_On = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.On', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the `ON` clause in the `REVOKE` privilege statement\n' - 'which SHALL allow to specify one or more tables to which the privilege SHALL\n' - 'be revoked using the following patterns\n' - '\n' - '* `db.table` specific table in the specified database\n' - '* `db.*` any table in the specified database\n' - '* `*.*` any table in any database\n' - '* `table` specific table in the current database\n' - '* `*` any table in the current database\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_From = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.From', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the `FROM` clause in the `REVOKE` privilege statement\n' - 'which SHALL allow to specify one or more users to which the privilege SHALL\n' - 'be revoked using the following patterns\n' - '\n' - '* `{user | CURRENT_USER} [,...]` some combination of users by name, which may include the current user\n' - '* `ALL` all users\n' - '* `ALL EXCEPT {user | CURRENT_USER} [,...]` the logical reverse of the first pattern\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Privilege_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Privilege.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `REVOKE` statement that\n' - 'revokes explicit privileges of a user or a role.\n' - '\n' - '```sql\n' - 'REVOKE [ON CLUSTER cluster_name] privilege\n' - ' [(column_name [,...])] [,...]\n' - ' ON {db.table|db.*|*.*|table|*}\n' - ' FROM {user | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user | CURRENT_USER} [,...]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_PartialRevoke_Syntax = Requirement( - name='RQ.SRS-006.RBAC.PartialRevoke.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support partial revokes by using `partial_revokes` variable\n' - 'that can be set or unset using the following syntax.\n' - '\n' - 'To disable partial revokes the `partial_revokes` variable SHALL be set to `0`\n' - '\n' - '```sql\n' - 'SET partial_revokes = 0\n' - '```\n' - '\n' - 'To enable partial revokes the `partial revokes` variable SHALL be set to `1`\n' - '\n' - '```sql\n' - 'SET partial_revokes = 1\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Role = Requirement( - name='RQ.SRS-006.RBAC.Grant.Role', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting one or more roles to\n' - 'one or more users or roles using the `GRANT` role statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Role_CurrentUser = Requirement( - name='RQ.SRS-006.RBAC.Grant.Role.CurrentUser', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting one or more roles to current user using\n' - '`TO CURRENT_USER` clause in the `GRANT` role statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Role_AdminOption = Requirement( - name='RQ.SRS-006.RBAC.Grant.Role.AdminOption', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting `admin option` privilege\n' - 'to one or more users or roles using the `WITH ADMIN OPTION` clause\n' - 'in the `GRANT` role statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Role_OnCluster = Requirement( - name='RQ.SRS-006.RBAC.Grant.Role.OnCluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying cluster on which the user is to be granted one or more roles\n' - 'using `ON CLUSTER` clause in the `GRANT` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Grant_Role_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Grant.Role.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for `GRANT` role statement\n' - '\n' - '``` sql\n' - 'GRANT\n' - ' ON CLUSTER cluster_name\n' - ' role [, role ...]\n' - ' TO {user | role | CURRENT_USER} [,...]\n' - ' [WITH ADMIN OPTION]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Role = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Role', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking one or more roles from\n' - 'one or more users or roles using the `REVOKE` role statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Role_Keywords = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Role.Keywords', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking one or more roles from\n' - 'special groupings of one or more users or roles with the `ALL`, `ALL EXCEPT`,\n' - 'and `CURRENT_USER` keywords.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Role_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Role.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking one or more roles from\n' - 'one or more users or roles from one or more clusters\n' - 'using the `REVOKE ON CLUSTER` role statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_AdminOption = Requirement( - name='RQ.SRS-006.RBAC.Revoke.AdminOption', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking `admin option` privilege\n' - 'in one or more users or roles using the `ADMIN OPTION FOR` clause\n' - 'in the `REVOKE` role statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Revoke_Role_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Revoke.Role.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `REVOKE` role statement\n' - '\n' - '```sql\n' - 'REVOKE [ON CLUSTER cluster_name] [ADMIN OPTION FOR]\n' - ' role [,...]\n' - ' FROM {user | role | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user_name | role_name | CURRENT_USER} [,...]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Show_Grants = Requirement( - name='RQ.SRS-006.RBAC.Show.Grants', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support listing all the privileges granted to current user and role\n' - 'using the `SHOW GRANTS` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Show_Grants_For = Requirement( - name='RQ.SRS-006.RBAC.Show.Grants.For', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support listing all the privileges granted to a user or a role\n' - 'using the `FOR` clause in the `SHOW GRANTS` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Show_Grants_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Show.Grants.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[Clickhouse] SHALL use the following syntax for the `SHOW GRANTS` statement\n' - '\n' - '``` sql\n' - 'SHOW GRANTS [FOR user_or_role]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creating settings profile using the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_IfNotExists = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.IfNotExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `IF NOT EXISTS` clause in the `CREATE SETTINGS PROFILE` statement\n' - 'to skip raising an exception if a settings profile with the same **name** already exists.\n' - 'If `IF NOT EXISTS` clause is not specified then an exception SHALL be raised if\n' - 'a settings profile with the same **name** already exists.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_Replace = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.Replace', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `OR REPLACE` clause in the `CREATE SETTINGS PROFILE` statement\n' - 'to replace existing settings profile if it already exists.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_Variables = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.Variables', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning values and constraints to one or more\n' - 'variables in the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Value = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Value', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning variable value in the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.Variables.Constraints', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support setting `MIN`, `MAX`, `READONLY`, and `WRITABLE`\n' - 'constraints for the variables in the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning settings profile to one or more users\n' - 'or roles in the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_None = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning settings profile to no users or roles using\n' - '`TO NONE` clause in the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_All = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning settings profile to all current users and roles\n' - 'using `TO ALL` clause in the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_AllExcept = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.Assignment.AllExcept', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support excluding assignment to one or more users or roles using\n' - 'the `ALL EXCEPT` clause in the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_Inherit = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.Inherit', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support inheriting profile settings from indicated profile using\n' - 'the `INHERIT` clause in the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_OnCluster = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.OnCluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying what cluster to create settings profile on\n' - 'using `ON CLUSTER` clause in the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Create_Syntax = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Create.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `CREATE SETTINGS PROFILE` statement.\n' - '\n' - '``` sql\n' - 'CREATE SETTINGS PROFILE [IF NOT EXISTS | OR REPLACE] name\n' - ' [ON CLUSTER cluster_name]\n' - " [SET varname [= value] [MIN min] [MAX max] [READONLY|WRITABLE] | [INHERIT 'profile_name'] [,...]]\n" - ' [TO {user_or_role [,...] | NONE | ALL | ALL EXCEPT user_or_role [,...]}]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering settings profile using the `ALTER STETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_IfExists = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.IfExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `IF EXISTS` clause in the `ALTER SETTINGS PROFILE` statement\n' - 'to not raise exception if a settings profile does not exist.\n' - 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' - 'raised if a settings profile does not exist.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Rename = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Rename', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support renaming settings profile using the `RANAME TO` clause\n' - 'in the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering values and constraints of one or more\n' - 'variables in the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Value', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering value of the variable in the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Variables.Constraints', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering `MIN`, `MAX`, `READONLY`, and `WRITABLE`\n' - 'constraints for the variables in the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support reassigning settings profile to one or more users\n' - 'or roles using the `TO` clause in the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_None = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support reassigning settings profile to no users or roles using the\n' - '`TO NONE` clause in the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_All = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support reassigning settings profile to all current users and roles\n' - 'using the `TO ALL` clause in the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_AllExcept = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.AllExcept', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support excluding assignment to one or more users or roles using\n' - 'the `TO ALL EXCEPT` clause in the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_Inherit = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.Inherit', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering the settings profile by inheriting settings from\n' - 'specified profile using `INHERIT` clause in the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_OnCluster = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Assignment.OnCluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering the settings profile on a specified cluster using\n' - '`ON CLUSTER` clause in the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Alter_Syntax = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Alter.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `ALTER SETTINGS PROFILE` statement.\n' - '\n' - '``` sql\n' - 'ALTER SETTINGS PROFILE [IF EXISTS] name\n' - ' [ON CLUSTER cluster_name]\n' - ' [RENAME TO new_name]\n' - " [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | INHERIT 'profile_name'] [,...]\n" - ' [TO {user_or_role [,...] | NONE | ALL | ALL EXCEPT user_or_role [,...]]}\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Drop = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Drop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support removing one or more settings profiles using the `DROP SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Drop_IfExists = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Drop.IfExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support using `IF EXISTS` clause in the `DROP SETTINGS PROFILE` statement\n' - 'to skip raising an exception if the settings profile does not exist.\n' - 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' - 'raised if a settings profile does not exist.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Drop_OnCluster = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Drop.OnCluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support dropping one or more settings profiles on specified cluster using\n' - '`ON CLUSTER` clause in the `DROP SETTINGS PROFILE` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_Drop_Syntax = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.Drop.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `DROP SETTINGS PROFILE` statement\n' - '\n' - '``` sql\n' - 'DROP SETTINGS PROFILE [IF EXISTS] name [,name,...]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_SettingsProfile_ShowCreateSettingsProfile = Requirement( - name='RQ.SRS-006.RBAC.SettingsProfile.ShowCreateSettingsProfile', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the `CREATE SETTINGS PROFILE` statement used to create the settings profile\n' - 'using the `SHOW CREATE SETTINGS PROFILE` statement with the following syntax\n' - '\n' - '``` sql\n' - 'SHOW CREATE SETTINGS PROFILE name\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creating quotas using the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_IfNotExists = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.IfNotExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `IF NOT EXISTS` clause in the `CREATE QUOTA` statement\n' - 'to skip raising an exception if a quota with the same **name** already exists.\n' - 'If `IF NOT EXISTS` clause is not specified then an exception SHALL be raised if\n' - 'a quota with the same **name** already exists.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Replace = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Replace', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `OR REPLACE` clause in the `CREATE QUOTA` statement\n' - 'to replace existing quota if it already exists.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creating quotas on a specific cluster with the\n' - '`ON CLUSTER` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Interval = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Interval', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support defining the quota interval that specifies\n' - 'a period of time over for which the quota SHALL apply using the\n' - '`FOR INTERVAL` clause in the `CREATE QUOTA` statement.\n' - '\n' - 'This statement SHALL also support a number and a time period which will be one\n' - 'of `{SECOND | MINUTE | HOUR | DAY | MONTH}`. Thus, the complete syntax SHALL be:\n' - '\n' - '`FOR INTERVAL number {SECOND | MINUTE | HOUR | DAY}` where number is some real number\n' - 'to define the interval.\n' - '\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Interval_Randomized = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Interval.Randomized', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support defining the quota randomized interval that specifies\n' - 'a period of time over for which the quota SHALL apply using the\n' - '`FOR RANDOMIZED INTERVAL` clause in the `CREATE QUOTA` statement.\n' - '\n' - 'This statement SHALL also support a number and a time period which will be one\n' - 'of `{SECOND | MINUTE | HOUR | DAY | MONTH}`. Thus, the complete syntax SHALL be:\n' - '\n' - '`FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}` where number is some\n' - 'real number to define the interval.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Queries = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Queries', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting number of requests over a period of time\n' - 'using the `QUERIES` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Errors = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Errors', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting number of queries that threw an exception\n' - 'using the `ERRORS` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_ResultRows = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.ResultRows', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting the total number of rows given as the result\n' - 'using the `RESULT ROWS` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_ReadRows = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.ReadRows', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting the total number of source rows read from tables\n' - 'for running the query on all remote servers\n' - 'using the `READ ROWS` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_ResultBytes = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.ResultBytes', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting the total number of bytes that can be returned as the result\n' - 'using the `RESULT BYTES` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_ReadBytes = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.ReadBytes', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting the total number of source bytes read from tables\n' - 'for running the query on all remote servers\n' - 'using the `READ BYTES` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_ExecutionTime = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.ExecutionTime', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting the maximum query execution time\n' - 'using the `EXECUTION TIME` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_NoLimits = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.NoLimits', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting the maximum query execution time\n' - 'using the `NO LIMITS` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_TrackingOnly = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.TrackingOnly', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting the maximum query execution time\n' - 'using the `TRACKING ONLY` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_KeyedBy = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.KeyedBy', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support to track quota for some key\n' - 'following the `KEYED BY` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_KeyedByOptions = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.KeyedByOptions', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support to track quota separately for some parameter\n' - "using the `KEYED BY 'parameter'` clause in the `CREATE QUOTA` statement.\n" - '\n' - "'parameter' can be one of:\n" - "`{'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}`\n" - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Assignment = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Assignment', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning quota to one or more users\n' - 'or roles using the `TO` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Assignment_None = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Assignment.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning quota to no users or roles using\n' - '`TO NONE` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Assignment_All = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Assignment.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning quota to all current users and roles\n' - 'using `TO ALL` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Assignment_Except = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Assignment.Except', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support excluding assignment of quota to one or more users or roles using\n' - 'the `EXCEPT` clause in the `CREATE QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Create_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Quota.Create.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `CREATE QUOTA` statement\n' - '\n' - '```sql\n' - 'CREATE QUOTA [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name]\n' - " [KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]\n" - ' [FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}\n' - ' {MAX { {QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = number } [,...] |\n' - ' NO LIMITS | TRACKING ONLY} [,...]]\n' - ' [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering quotas using the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_IfExists = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.IfExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `IF EXISTS` clause in the `ALTER QUOTA` statement\n' - 'to skip raising an exception if a quota does not exist.\n' - 'If the `IF EXISTS` clause is not specified then an exception SHALL be raised if\n' - 'a quota does not exist.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Rename = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Rename', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `RENAME TO` clause in the `ALTER QUOTA` statement\n' - 'to rename the quota to the specified name.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering quotas on a specific cluster with the\n' - '`ON CLUSTER` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Interval = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Interval', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support redefining the quota interval that specifies\n' - 'a period of time over for which the quota SHALL apply using the\n' - '`FOR INTERVAL` clause in the `ALTER QUOTA` statement.\n' - '\n' - 'This statement SHALL also support a number and a time period which will be one\n' - 'of `{SECOND | MINUTE | HOUR | DAY | MONTH}`. Thus, the complete syntax SHALL be:\n' - '\n' - '`FOR INTERVAL number {SECOND | MINUTE | HOUR | DAY}` where number is some real number\n' - 'to define the interval.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Interval_Randomized = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Interval.Randomized', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support redefining the quota randomized interval that specifies\n' - 'a period of time over for which the quota SHALL apply using the\n' - '`FOR RANDOMIZED INTERVAL` clause in the `ALTER QUOTA` statement.\n' - '\n' - 'This statement SHALL also support a number and a time period which will be one\n' - 'of `{SECOND | MINUTE | HOUR | DAY | MONTH}`. Thus, the complete syntax SHALL be:\n' - '\n' - '`FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}` where number is some\n' - 'real number to define the interval.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Queries = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Queries', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering the limit of number of requests over a period of time\n' - 'using the `QUERIES` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Errors = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Errors', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering the limit of number of queries that threw an exception\n' - 'using the `ERRORS` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_ResultRows = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.ResultRows', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering the limit of the total number of rows given as the result\n' - 'using the `RESULT ROWS` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_ReadRows = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.ReadRows', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering the limit of the total number of source rows read from tables\n' - 'for running the query on all remote servers\n' - 'using the `READ ROWS` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_ALter_ResultBytes = Requirement( - name='RQ.SRS-006.RBAC.Quota.ALter.ResultBytes', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering the limit of the total number of bytes that can be returned as the result\n' - 'using the `RESULT BYTES` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_ReadBytes = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.ReadBytes', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering the limit of the total number of source bytes read from tables\n' - 'for running the query on all remote servers\n' - 'using the `READ BYTES` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_ExecutionTime = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.ExecutionTime', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering the limit of the maximum query execution time\n' - 'using the `EXECUTION TIME` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_NoLimits = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.NoLimits', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting the maximum query execution time\n' - 'using the `NO LIMITS` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_TrackingOnly = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.TrackingOnly', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support limiting the maximum query execution time\n' - 'using the `TRACKING ONLY` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_KeyedBy = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.KeyedBy', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering quota to track quota separately for some key\n' - 'following the `KEYED BY` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_KeyedByOptions = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.KeyedByOptions', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering quota to track quota separately for some parameter\n' - "using the `KEYED BY 'parameter'` clause in the `ALTER QUOTA` statement.\n" - '\n' - "'parameter' can be one of:\n" - "`{'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}`\n" - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Assignment = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Assignment', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support reassigning quota to one or more users\n' - 'or roles using the `TO` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Assignment_None = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Assignment.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support reassigning quota to no users or roles using\n' - '`TO NONE` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Assignment_All = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Assignment.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support reassigning quota to all current users and roles\n' - 'using `TO ALL` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Assignment_Except = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Assignment.Except', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support excluding assignment of quota to one or more users or roles using\n' - 'the `EXCEPT` clause in the `ALTER QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Alter_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Quota.Alter.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `ALTER QUOTA` statement\n' - '\n' - '``` sql\n' - 'ALTER QUOTA [IF EXIST] name\n' - ' {{{QUERIES | ERRORS | RESULT ROWS | READ ROWS | RESULT BYTES | READ BYTES | EXECUTION TIME} number} [, ...] FOR INTERVAL number time_unit} [, ...]\n' - ' [KEYED BY USERNAME | KEYED BY IP | NOT KEYED] [ALLOW CUSTOM KEY | DISALLOW CUSTOM KEY]\n' - ' [TO {user_or_role [,...] | NONE | ALL} [EXCEPT user_or_role [,...]]]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Drop = Requirement( - name='RQ.SRS-006.RBAC.Quota.Drop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support removing one or more quotas using the `DROP QUOTA` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Drop_IfExists = Requirement( - name='RQ.SRS-006.RBAC.Quota.Drop.IfExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support using `IF EXISTS` clause in the `DROP QUOTA` statement\n' - 'to skip raising an exception when the quota does not exist.\n' - 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' - 'raised if the quota does not exist.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Drop_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Quota.Drop.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support using `ON CLUSTER` clause in the `DROP QUOTA` statement\n' - 'to indicate the cluster the quota to be dropped is located on.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_Drop_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Quota.Drop.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `DROP QUOTA` statement\n' - '\n' - '``` sql\n' - 'DROP QUOTA [IF EXISTS] name [,name...]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_ShowQuotas = Requirement( - name='RQ.SRS-006.RBAC.Quota.ShowQuotas', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing all of the current quotas\n' - 'using the `SHOW QUOTAS` statement with the following syntax\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_ShowQuotas_IntoOutfile = Requirement( - name='RQ.SRS-006.RBAC.Quota.ShowQuotas.IntoOutfile', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the `INTO OUTFILE` clause in the `SHOW QUOTAS` statement to define an outfile by some given string literal.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_ShowQuotas_Format = Requirement( - name='RQ.SRS-006.RBAC.Quota.ShowQuotas.Format', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the `FORMAT` clause in the `SHOW QUOTAS` statement to define a format for the output quota list.\n' - '\n' - 'The types of valid formats are many, listed in output column:\n' - 'https://clickhouse.tech/docs/en/interfaces/formats/\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_ShowQuotas_Settings = Requirement( - name='RQ.SRS-006.RBAC.Quota.ShowQuotas.Settings', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the `SETTINGS` clause in the `SHOW QUOTAS` statement to define settings in the showing of all quotas.\n' - '\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_ShowQuotas_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Quota.ShowQuotas.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support using the `SHOW QUOTAS` statement\n' - 'with the following syntax\n' - '``` sql\n' - 'SHOW QUOTAS\n' - '```\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Name = Requirement( - name='RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Name', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the `CREATE QUOTA` statement used to create the quota with some given name\n' - 'using the `SHOW CREATE QUOTA` statement with the following syntax\n' - '\n' - '``` sql\n' - 'SHOW CREATE QUOTA name\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Current = Requirement( - name='RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Current', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the `CREATE QUOTA` statement used to create the CURRENT quota\n' - 'using the `SHOW CREATE QUOTA CURRENT` statement or the shorthand form\n' - '`SHOW CREATE QUOTA`\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Syntax = Requirement( - name='RQ.SRS-006.RBAC.Quota.ShowCreateQuota.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax when\n' - 'using the `SHOW CREATE QUOTA` statement.\n' - '\n' - '```sql\n' - 'SHOW CREATE QUOTA [name | CURRENT]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support creating row policy using the `CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_IfNotExists = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.IfNotExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `IF NOT EXISTS` clause in the `CREATE ROW POLICY` statement\n' - 'to skip raising an exception if a row policy with the same **name** already exists.\n' - 'If the `IF NOT EXISTS` clause is not specified then an exception SHALL be raised if\n' - 'a row policy with the same **name** already exists.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_Replace = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.Replace', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support `OR REPLACE` clause in the `CREATE ROW POLICY` statement\n' - 'to replace existing row policy if it already exists.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_OnCluster = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.OnCluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying cluster on which to create the role policy\n' - 'using the `ON CLUSTER` clause in the `CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_On = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.On', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying table on which to create the role policy\n' - 'using the `ON` clause in the `CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_Access = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.Access', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support allowing or restricting access to rows using the\n' - '`AS` clause in the `CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_Access_Permissive = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.Access.Permissive', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support allowing access to rows using the\n' - '`AS PERMISSIVE` clause in the `CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_Access_Restrictive = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.Access.Restrictive', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support restricting access to rows using the\n' - '`AS RESTRICTIVE` clause in the `CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_ForSelect = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.ForSelect', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying which rows are affected\n' - 'using the `FOR SELECT` clause in the `CREATE ROW POLICY` statement.\n' - 'REQUIRES CONFIRMATION\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_Condition = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.Condition', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying a condition that\n' - 'that can be any SQL expression which returns a boolean using the `USING`\n' - 'clause in the `CREATE ROW POLOCY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_Assignment = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning row policy to one or more users\n' - 'or roles using the `TO` clause in the `CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_None = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning row policy to no users or roles using\n' - 'the `TO NONE` clause in the `CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_All = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support assigning row policy to all current users and roles\n' - 'using `TO ALL` clause in the `CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_AllExcept = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.Assignment.AllExcept', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support excluding assignment of row policy to one or more users or roles using\n' - 'the `ALL EXCEPT` clause in the `CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Create_Syntax = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Create.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `CRETE ROW POLICY` statement\n' - '\n' - '``` sql\n' - 'CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name [ON CLUSTER cluster_name] ON [db.]table\n' - ' [AS {PERMISSIVE | RESTRICTIVE}]\n' - ' [FOR SELECT]\n' - ' [USING condition]\n' - ' [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering row policy using the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_IfExists = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.IfExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the `IF EXISTS` clause in the `ALTER ROW POLICY` statement\n' - 'to skip raising an exception if a row policy does not exist.\n' - 'If the `IF EXISTS` clause is not specified then an exception SHALL be raised if\n' - 'a row policy does not exist.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_ForSelect = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.ForSelect', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support modifying rows on which to apply the row policy\n' - 'using the `FOR SELECT` clause in the `ALTER ROW POLICY` statement.\n' - 'REQUIRES FUNCTION CONFIRMATION.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_OnCluster = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.OnCluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying cluster on which to alter the row policy\n' - 'using the `ON CLUSTER` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_On = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.On', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support specifying table on which to alter the row policy\n' - 'using the `ON` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Rename = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Rename', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support renaming the row policy using the `RENAME` clause\n' - 'in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Access = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Access', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support altering access to rows using the\n' - '`AS` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Permissive = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Permissive', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support permitting access to rows using the\n' - '`AS PERMISSIVE` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Restrictive = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Access.Restrictive', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support restricting access to rows using the\n' - '`AS RESTRICTIVE` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Condition = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Condition', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support re-specifying the row policy condition\n' - 'using the `USING` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Condition_None = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Condition.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support removing the row policy condition\n' - 'using the `USING NONE` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support reassigning row policy to one or more users\n' - 'or roles using the `TO` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_None = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.None', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support reassigning row policy to no users or roles using\n' - 'the `TO NONE` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_All = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support reassigning row policy to all current users and roles\n' - 'using the `TO ALL` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_AllExcept = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Assignment.AllExcept', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support excluding assignment of row policy to one or more users or roles using\n' - 'the `ALL EXCEPT` clause in the `ALTER ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Alter_Syntax = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Alter.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `ALTER ROW POLICY` statement\n' - '\n' - '``` sql\n' - 'ALTER [ROW] POLICY [IF EXISTS] name [ON CLUSTER cluster_name] ON [database.]table\n' - ' [RENAME TO new_name]\n' - ' [AS {PERMISSIVE | RESTRICTIVE}]\n' - ' [FOR SELECT]\n' - ' [USING {condition | NONE}][,...]\n' - ' [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Drop = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Drop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support removing one or more row policies using the `DROP ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Drop_IfExists = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Drop.IfExists', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support using the `IF EXISTS` clause in the `DROP ROW POLICY` statement\n' - 'to skip raising an exception when the row policy does not exist.\n' - 'If the `IF EXISTS` clause is not specified then an exception SHALL be\n' - 'raised if the row policy does not exist.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Drop_On = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Drop.On', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support removing row policy from one or more specified tables\n' - 'using the `ON` clause in the `DROP ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Drop_OnCluster = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Drop.OnCluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support removing row policy from specified cluster\n' - 'using the `ON CLUSTER` clause in the `DROP ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_Drop_Syntax = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.Drop.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for the `DROP ROW POLICY` statement.\n' - '\n' - '``` sql\n' - 'DROP [ROW] POLICY [IF EXISTS] name [,...] ON [database.]table [,...] [ON CLUSTER cluster_name]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing the `CREATE ROW POLICY` statement used to create the row policy\n' - 'using the `SHOW CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy_On = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.On', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing statement used to create row policy on specific table\n' - 'using the `ON` in the `SHOW CREATE ROW POLICY` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy_Syntax = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.ShowCreateRowPolicy.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for `SHOW CREATE ROW POLICY`.\n' - '\n' - '``` sql\n' - 'SHOW CREATE [ROW] POLICY name ON [database.]table\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing row policies using the `SHOW ROW POLICIES` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_On = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.On', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support showing row policies on a specific table\n' - 'using the `ON` clause in the `SHOW ROW POLICIES` statement.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_Syntax = Requirement( - name='RQ.SRS-006.RBAC.RowPolicy.ShowRowPolicies.Syntax', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the following syntax for `SHOW ROW POLICIES`.\n' - '\n' - '```sql\n' - 'SHOW [ROW] POLICIES [ON [database.]table]\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Table_PublicTables = Requirement( - name='RQ.SRS-006.RBAC.Table.PublicTables', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support that a user without any privileges will be able to access the following tables\n' - '\n' - '* system.one\n' - '* system.numbers\n' - '* system.contributors\n' - '* system.functions\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Table_SensitiveTables = Requirement( - name='RQ.SRS-006.RBAC.Table.SensitiveTables', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL not support a user with no privileges accessing the following `system` tables:\n' - '\n' - '* processes\n' - '* query_log\n' - '* query_thread_log\n' - '* clusters\n' - '* events\n' - '* graphite_retentions\n' - '* stack_trace\n' - '* trace_log\n' - '* user_directories\n' - '* zookeeper\n' - '* macros\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_DistributedTable_Create = Requirement( - name='RQ.SRS-006.RBAC.DistributedTable.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully `CREATE` a distributed table if and only if\n' - 'the user has **create table** privilege on the table and **remote** privilege on *.*\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_DistributedTable_Select = Requirement( - name='RQ.SRS-006.RBAC.DistributedTable.Select', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully `SELECT` from a distributed table if and only if\n' - 'the user has **select** privilege on the table and on the remote table specified in the `CREATE` query of the distributed table.\n' - '\n' - 'Does not require **select** privilege for the remote table if the remote table does not exist on the same server as the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_DistributedTable_Insert = Requirement( - name='RQ.SRS-006.RBAC.DistributedTable.Insert', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully `INSERT` into a distributed table if and only if\n' - 'the user has **insert** privilege on the table and on the remote table specified in the `CREATE` query of the distributed table.\n' - '\n' - 'Does not require **insert** privilege for the remote table if the remote table does not exist on the same server as the user,\n' - 'insert executes into the remote table on a different server.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_DistributedTable_SpecialTables = Requirement( - name='RQ.SRS-006.RBAC.DistributedTable.SpecialTables', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute a query using a distributed table that uses one of the special tables if and only if\n' - 'the user has the necessary privileges to interact with that special table, either granted directly or through a role.\n' - 'Special tables include:\n' - '* materialized view\n' - '* distributed table\n' - '* source table of a materialized view\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_DistributedTable_LocalUser = Requirement( - name='RQ.SRS-006.RBAC.DistributedTable.LocalUser', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute a query using a distributed table from\n' - 'a user present locally, but not remotely.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_DistributedTable_SameUserDifferentNodesDifferentPrivileges = Requirement( - name='RQ.SRS-006.RBAC.DistributedTable.SameUserDifferentNodesDifferentPrivileges', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute a query using a distributed table by a user that exists on multiple nodes\n' - 'if and only if the user has the required privileges on the node the query is being executed from.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_View = Requirement( - name='RQ.SRS-006.RBAC.View', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to **create**, **select** and **drop**\n' - 'privileges for a view for users or roles.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_View_Create = Requirement( - name='RQ.SRS-006.RBAC.View.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully execute a `CREATE VIEW` command if and only if\n' - 'the user has **create view** privilege either explicitly or through roles.\n' - '\n' - 'If the stored query includes one or more source tables, the user must have **select** privilege\n' - 'on all the source tables either explicitly or through a role.\n' - 'For example,\n' - '```sql\n' - 'CREATE VIEW view AS SELECT * FROM source_table\n' - 'CREATE VIEW view AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' - 'CREATE VIEW view AS SELECT * FROM table0 JOIN table1 USING column\n' - 'CREATE VIEW view AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' - 'CREATE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' - 'CREATE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_View_Select = Requirement( - name='RQ.SRS-006.RBAC.View.Select', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully `SELECT` from a view if and only if\n' - 'the user has **select** privilege for that view either explicitly or through a role.\n' - '\n' - 'If the stored query includes one or more source tables, the user must have **select** privilege\n' - 'on all the source tables either explicitly or through a role.\n' - 'For example,\n' - '```sql\n' - 'CREATE VIEW view AS SELECT * FROM source_table\n' - 'CREATE VIEW view AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' - 'CREATE VIEW view AS SELECT * FROM table0 JOIN table1 USING column\n' - 'CREATE VIEW view AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' - 'CREATE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' - 'CREATE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' - '\n' - 'SELECT * FROM view\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_View_Drop = Requirement( - name='RQ.SRS-006.RBAC.View.Drop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if\n' - 'the user has **drop view** privilege on that view either explicitly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_MaterializedView = Requirement( - name='RQ.SRS-006.RBAC.MaterializedView', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to **create**, **select**, **alter** and **drop**\n' - 'privileges for a materialized view for users or roles.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_MaterializedView_Create = Requirement( - name='RQ.SRS-006.RBAC.MaterializedView.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully execute a `CREATE MATERIALIZED VIEW` command if and only if\n' - 'the user has **create view** privilege either explicitly or through roles.\n' - '\n' - 'If `POPULATE` is specified, the user must have `INSERT` privilege on the view,\n' - 'either explicitly or through roles.\n' - 'For example,\n' - '```sql\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory POPULATE AS SELECT * FROM source_table\n' - '```\n' - '\n' - 'If the stored query includes one or more source tables, the user must have **select** privilege\n' - 'on all the source tables either explicitly or through a role.\n' - 'For example,\n' - '```sql\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM source_table\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 JOIN table1 USING column\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' - 'CREATE MATERIALIZED VIEW view0 ENGINE = Memory AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' - '```\n' - '\n' - 'If the materialized view has a target table explicitly declared in the `TO` clause, the user must have\n' - '**insert** and **select** privilege on the target table.\n' - 'For example,\n' - '```sql\n' - 'CREATE MATERIALIZED VIEW view TO target_table AS SELECT * FROM source_table\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_MaterializedView_Select = Requirement( - name='RQ.SRS-006.RBAC.MaterializedView.Select', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully `SELECT` from a materialized view if and only if\n' - 'the user has **select** privilege for that view either explicitly or through a role.\n' - '\n' - 'If the stored query includes one or more source tables, the user must have **select** privilege\n' - 'on all the source tables either explicitly or through a role.\n' - 'For example,\n' - '```sql\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM source_table\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 JOIN table1 USING column\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' - 'CREATE MATERIALIZED VIEW view ENGINE = Memory AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' - 'CREATE MATERIALIZED VIEW view0 ENGINE = Memory AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' - '\n' - 'SELECT * FROM view\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_MaterializedView_Select_TargetTable = Requirement( - name='RQ.SRS-006.RBAC.MaterializedView.Select.TargetTable', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully `SELECT` from the target table, implicit or explicit, of a materialized view if and only if\n' - 'the user has `SELECT` privilege for the table, either explicitly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_MaterializedView_Select_SourceTable = Requirement( - name='RQ.SRS-006.RBAC.MaterializedView.Select.SourceTable', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully `SELECT` from the source table of a materialized view if and only if\n' - 'the user has `SELECT` privilege for the table, either explicitly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_MaterializedView_Drop = Requirement( - name='RQ.SRS-006.RBAC.MaterializedView.Drop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if\n' - 'the user has **drop view** privilege on that view either explicitly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_MaterializedView_ModifyQuery = Requirement( - name='RQ.SRS-006.RBAC.MaterializedView.ModifyQuery', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully execute a `MODIFY QUERY` command if and only if\n' - 'the user has **modify query** privilege on that view either explicitly or through a role.\n' - '\n' - 'If the new query includes one or more source tables, the user must have **select** privilege\n' - 'on all the source tables either explicitly or through a role.\n' - 'For example,\n' - '```sql\n' - 'ALTER TABLE view MODIFY QUERY SELECT * FROM source_table\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_MaterializedView_Insert = Requirement( - name='RQ.SRS-006.RBAC.MaterializedView.Insert', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only succesfully `INSERT` into a materialized view if and only if\n' - 'the user has `INSERT` privilege on the view, either explicitly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_MaterializedView_Insert_SourceTable = Requirement( - name='RQ.SRS-006.RBAC.MaterializedView.Insert.SourceTable', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only succesfully `INSERT` into a source table of a materialized view if and only if\n' - 'the user has `INSERT` privilege on the source table, either explicitly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_MaterializedView_Insert_TargetTable = Requirement( - name='RQ.SRS-006.RBAC.MaterializedView.Insert.TargetTable', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only succesfully `INSERT` into a target table of a materialized view if and only if\n' - 'the user has `INSERT` privelege on the target table, either explicitly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_LiveView = Requirement( - name='RQ.SRS-006.RBAC.LiveView', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to **create**, **select**, **alter** and **drop**\n' - 'privileges for a live view for users or roles.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_LiveView_Create = Requirement( - name='RQ.SRS-006.RBAC.LiveView.Create', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully execute a `CREATE LIVE VIEW` command if and only if\n' - 'the user has **create view** privilege either explicitly or through roles.\n' - '\n' - 'If the stored query includes one or more source tables, the user must have **select** privilege\n' - 'on all the source tables either explicitly or through a role.\n' - 'For example,\n' - '```sql\n' - 'CREATE LIVE VIEW view AS SELECT * FROM source_table\n' - 'CREATE LIVE VIEW view AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' - 'CREATE LIVE VIEW view AS SELECT * FROM table0 JOIN table1 USING column\n' - 'CREATE LIVE VIEW view AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' - 'CREATE LIVE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' - 'CREATE LIVE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_LiveView_Select = Requirement( - name='RQ.SRS-006.RBAC.LiveView.Select', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully `SELECT` from a live view if and only if\n' - 'the user has **select** privilege for that view either explicitly or through a role.\n' - '\n' - 'If the stored query includes one or more source tables, the user must have **select** privilege\n' - 'on all the source tables either explicitly or through a role.\n' - 'For example,\n' - '```sql\n' - 'CREATE LIVE VIEW view AS SELECT * FROM source_table\n' - 'CREATE LIVE VIEW view AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' - 'CREATE LIVE VIEW view AS SELECT * FROM table0 JOIN table1 USING column\n' - 'CREATE LIVE VIEW view AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' - 'CREATE LIVE VIEW view AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' - 'CREATE LIVE VIEW view0 AS SELECT column FROM view1 UNION ALL SELECT column FROM view2\n' - '\n' - 'SELECT * FROM view\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_LiveView_Drop = Requirement( - name='RQ.SRS-006.RBAC.LiveView.Drop', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully execute a `DROP VIEW` command if and only if\n' - 'the user has **drop view** privilege on that view either explicitly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_LiveView_Refresh = Requirement( - name='RQ.SRS-006.RBAC.LiveView.Refresh', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully execute an `ALTER LIVE VIEW REFRESH` command if and only if\n' - 'the user has **refresh** privilege on that view either explicitly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Select = Requirement( - name='RQ.SRS-006.RBAC.Select', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL execute `SELECT` if and only if the user\n' - 'has the **select** privilege for the destination table\n' - 'either because of the explicit grant or through one of the roles assigned to the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Select_Column = Requirement( - name='RQ.SRS-006.RBAC.Select.Column', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking **select** privilege\n' - 'for one or more specified columns in a table to one or more **users** or **roles**.\n' - 'Any `SELECT` statements SHALL not to be executed, unless the user\n' - 'has the **select** privilege for the destination column\n' - 'either because of the explicit grant or through one of the roles assigned to the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Select_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Select.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking **select** privilege\n' - 'on a specified cluster to one or more **users** or **roles**.\n' - 'Any `SELECT` statements SHALL succeed only on nodes where\n' - 'the table exists and privilege was granted.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Select_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Select.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **select** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '* ReplacingMergeTree\n' - '* SummingMergeTree\n' - '* AggregatingMergeTree\n' - '* CollapsingMergeTree\n' - '* VersionedCollapsingMergeTree\n' - '* GraphiteMergeTree\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Insert = Requirement( - name='RQ.SRS-006.RBAC.Insert', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL execute `INSERT INTO` if and only if the user\n' - 'has the **insert** privilege for the destination table\n' - 'either because of the explicit grant or through one of the roles assigned to the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Insert_Column = Requirement( - name='RQ.SRS-006.RBAC.Insert.Column', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking **insert** privilege\n' - 'for one or more specified columns in a table to one or more **users** or **roles**.\n' - 'Any `INSERT INTO` statements SHALL not to be executed, unless the user\n' - 'has the **insert** privilege for the destination column\n' - 'either because of the explicit grant or through one of the roles assigned to the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Insert_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Insert.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking **insert** privilege\n' - 'on a specified cluster to one or more **users** or **roles**.\n' - 'Any `INSERT INTO` statements SHALL succeed only on nodes where\n' - 'the table exists and privilege was granted.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Insert_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Insert.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **insert** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '* ReplacingMergeTree\n' - '* SummingMergeTree\n' - '* AggregatingMergeTree\n' - '* CollapsingMergeTree\n' - '* VersionedCollapsingMergeTree\n' - '* GraphiteMergeTree\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterColumn = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterColumn', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter column** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN` statements SHALL\n' - 'return an error, unless the user has the **alter column** privilege for\n' - 'the destination table either because of the explicit grant or through one of\n' - 'the roles assigned to the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterColumn_Grant = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Grant', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting **alter column** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterColumn_Revoke = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Revoke', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **alter column** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterColumn_Column = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Column', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking **alter column** privilege\n' - 'for one or more specified columns in a table to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN` statements SHALL return an error,\n' - 'unless the user has the **alter column** privilege for the destination column\n' - 'either because of the explicit grant or through one of the roles assigned to the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterColumn_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterColumn.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking **alter column** privilege\n' - 'on a specified cluster to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN`\n' - 'statements SHALL succeed only on nodes where the table exists and privilege was granted.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterColumn_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterColumn.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter column** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '* ReplacingMergeTree\n' - '* SummingMergeTree\n' - '* AggregatingMergeTree\n' - '* CollapsingMergeTree\n' - '* VersionedCollapsingMergeTree\n' - '* GraphiteMergeTree\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterIndex = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterIndex', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter index** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... ORDER BY | ADD|DROP|MATERIALIZE|CLEAR INDEX` statements SHALL\n' - 'return an error, unless the user has the **alter index** privilege for\n' - 'the destination table either because of the explicit grant or through one of\n' - 'the roles assigned to the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterIndex_Grant = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterIndex.Grant', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting **alter index** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterIndex_Revoke = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterIndex.Revoke', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **alter index** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterIndex_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterIndex.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking **alter index** privilege\n' - 'on a specified cluster to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... ORDER BY | ADD|DROP|MATERIALIZE|CLEAR INDEX`\n' - 'statements SHALL succeed only on nodes where the table exists and privilege was granted.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterIndex_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterIndex.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter index** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '* ReplacingMergeTree\n' - '* SummingMergeTree\n' - '* AggregatingMergeTree\n' - '* CollapsingMergeTree\n' - '* VersionedCollapsingMergeTree\n' - '* GraphiteMergeTree\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterConstraint = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterConstraint', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter constraint** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... ADD|CREATE CONSTRAINT` statements SHALL\n' - 'return an error, unless the user has the **alter constraint** privilege for\n' - 'the destination table either because of the explicit grant or through one of\n' - 'the roles assigned to the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterConstraint_Grant = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.Grant', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting **alter constraint** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterConstraint_Revoke = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.Revoke', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **alter constraint** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterConstraint_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking **alter constraint** privilege\n' - 'on a specified cluster to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... ADD|DROP CONSTRAINT`\n' - 'statements SHALL succeed only on nodes where the table exists and privilege was granted.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterConstraint_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterConstraint.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter constraint** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '* ReplacingMergeTree\n' - '* SummingMergeTree\n' - '* AggregatingMergeTree\n' - '* CollapsingMergeTree\n' - '* VersionedCollapsingMergeTree\n' - '* GraphiteMergeTree\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterTTL = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterTTL', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter ttl** or **alter materialize ttl** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... ALTER TTL | ALTER MATERIALIZE TTL` statements SHALL\n' - 'return an error, unless the user has the **alter ttl** or **alter materialize ttl** privilege for\n' - 'the destination table either because of the explicit grant or through one of\n' - 'the roles assigned to the user.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterTTL_Grant = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterTTL.Grant', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting **alter ttl** or **alter materialize ttl** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterTTL_Revoke = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterTTL.Revoke', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **alter ttl** or **alter materialize ttl** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterTTL_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterTTL.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking **alter ttl** or **alter materialize ttl** privilege\n' - 'on a specified cluster to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... ALTER TTL | ALTER MATERIALIZE TTL`\n' - 'statements SHALL succeed only on nodes where the table exists and privilege was granted.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterTTL_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterTTL.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter ttl** or **alter materialize ttl** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterSettings = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterSettings', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter settings** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... MODIFY SETTING setting` statements SHALL\n' - 'return an error, unless the user has the **alter settings** privilege for\n' - 'the destination table either because of the explicit grant or through one of\n' - 'the roles assigned to the user. The **alter settings** privilege allows\n' - 'modifying table engine settings. It doesn’t affect settings or server configuration parameters.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterSettings_Grant = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterSettings.Grant', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting **alter settings** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterSettings_Revoke = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterSettings.Revoke', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **alter settings** privilege\n' - 'for a database or a specific table to one or more **users** or **roles**\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterSettings_Cluster = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterSettings.Cluster', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking **alter settings** privilege\n' - 'on a specified cluster to one or more **users** or **roles**.\n' - 'Any `ALTER TABLE ... MODIFY SETTING setting`\n' - 'statements SHALL succeed only on nodes where the table exists and privilege was granted.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterSettings_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterSettings.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter settings** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '* ReplacingMergeTree\n' - '* SummingMergeTree\n' - '* AggregatingMergeTree\n' - '* CollapsingMergeTree\n' - '* VersionedCollapsingMergeTree\n' - '* GraphiteMergeTree\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterUpdate = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterUpdate', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ALTER UPDATE` statement if and only if the user has **alter update** privilege for that column,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterUpdate_Grant = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterUpdate.Grant', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting **alter update** privilege on a column level\n' - 'to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterUpdate_Revoke = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterUpdate.Revoke', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **alter update** privilege on a column level\n' - 'from one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterUpdate_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterUpdate.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter update** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '* ReplacingMergeTree\n' - '* SummingMergeTree\n' - '* AggregatingMergeTree\n' - '* CollapsingMergeTree\n' - '* VersionedCollapsingMergeTree\n' - '* GraphiteMergeTree\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterDelete = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterDelete', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ALTER DELETE` statement if and only if the user has **alter delete** privilege for that table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterDelete_Grant = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterDelete.Grant', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting **alter delete** privilege on a column level\n' - 'to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterDelete_Revoke = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterDelete.Revoke', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **alter delete** privilege on a column level\n' - 'from one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterDelete_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterDelete.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter delete** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '* ReplacingMergeTree\n' - '* SummingMergeTree\n' - '* AggregatingMergeTree\n' - '* CollapsingMergeTree\n' - '* VersionedCollapsingMergeTree\n' - '* GraphiteMergeTree\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterFreeze = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterFreeze', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ALTER FREEZE` statement if and only if the user has **alter freeze** privilege for that table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterFreeze_Grant = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterFreeze.Grant', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting **alter freeze** privilege on a column level\n' - 'to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterFreeze_Revoke = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterFreeze.Revoke', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **alter freeze** privilege on a column level\n' - 'from one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterFreeze_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterFreeze.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter freeze** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '* ReplacingMergeTree\n' - '* SummingMergeTree\n' - '* AggregatingMergeTree\n' - '* CollapsingMergeTree\n' - '* VersionedCollapsingMergeTree\n' - '* GraphiteMergeTree\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterFetch = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterFetch', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ALTER FETCH` statement if and only if the user has **alter fetch** privilege for that table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterFetch_Grant = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterFetch.Grant', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting **alter fetch** privilege on a column level\n' - 'to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterFetch_Revoke = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterFetch.Revoke', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **alter fetch** privilege on a column level\n' - 'from one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterFetch_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterFetch.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter fetch** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterMove = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterMove', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ALTER MOVE` statement if and only if the user has **alter move**, **select**, and **alter delete** privilege on the source table\n' - 'and **insert** privilege on the target table, either directly or through a role.\n' - 'For example,\n' - '```sql\n' - 'ALTER TABLE source_table MOVE PARTITION 1 TO target_table\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterMove_Grant = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterMove.Grant', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting **alter move** privilege on a column level\n' - 'to one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterMove_Revoke = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterMove.Revoke', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support revoking **alter move** privilege on a column level\n' - 'from one or more **users** or **roles**.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterMove_TableEngines = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterMove.TableEngines', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support controlling access to the **alter move** privilege\n' - 'on tables created using the following engines\n' - '\n' - '* MergeTree\n' - '* ReplacingMergeTree\n' - '* SummingMergeTree\n' - '* AggregatingMergeTree\n' - '* CollapsingMergeTree\n' - '* VersionedCollapsingMergeTree\n' - '* GraphiteMergeTree\n' - '* ReplicatedMergeTree\n' - '* ReplicatedSummingMergeTree\n' - '* ReplicatedReplacingMergeTree\n' - '* ReplicatedAggregatingMergeTree\n' - '* ReplicatedCollapsingMergeTree\n' - '* ReplicatedVersionedCollapsingMergeTree\n' - '* ReplicatedGraphiteMergeTree\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_CreateTable = Requirement( - name='RQ.SRS-006.RBAC.Privileges.CreateTable', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL only successfully execute a `CREATE TABLE` command if and only if\n' - 'the user has **create table** privilege either explicitly or through roles.\n' - '\n' - 'If the stored query includes one or more source tables, the user must have **select** privilege\n' - "on all the source tables and **insert** for the table they're trying to create either explicitly or through a role.\n" - 'For example,\n' - '```sql\n' - 'CREATE TABLE table AS SELECT * FROM source_table\n' - 'CREATE TABLE table AS SELECT * FROM table0 WHERE column IN (SELECT column FROM table1 WHERE column IN (SELECT column FROM table2 WHERE expression))\n' - 'CREATE TABLE table AS SELECT * FROM table0 JOIN table1 USING column\n' - 'CREATE TABLE table AS SELECT * FROM table0 UNION ALL SELECT * FROM table1 UNION ALL SELECT * FROM table2\n' - 'CREATE TABLE table AS SELECT column FROM table0 JOIN table1 USING column UNION ALL SELECT column FROM table2 WHERE column IN (SELECT column FROM table3 WHERE column IN (SELECT column FROM table4 WHERE expression))\n' - 'CREATE TABLE table0 AS SELECT column FROM table1 UNION ALL SELECT column FROM table2\n' - '```\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_CreateDatabase = Requirement( - name='RQ.SRS-006.RBAC.Privileges.CreateDatabase', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `CREATE DATABASE` statement if and only if the user has **create database** privilege on the database,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_CreateDictionary = Requirement( - name='RQ.SRS-006.RBAC.Privileges.CreateDictionary', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `CREATE DICTIONARY` statement if and only if the user has **create dictionary** privilege on the dictionary,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_CreateTemporaryTable = Requirement( - name='RQ.SRS-006.RBAC.Privileges.CreateTemporaryTable', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `CREATE TEMPORARY TABLE` statement if and only if the user has **create temporary table** privilege on the table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AttachDatabase = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AttachDatabase', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ATTACH DATABASE` statement if and only if the user has **create database** privilege on the database,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AttachDictionary = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AttachDictionary', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ATTACH DICTIONARY` statement if and only if the user has **create dictionary** privilege on the dictionary,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AttachTemporaryTable = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AttachTemporaryTable', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ATTACH TEMPORARY TABLE` statement if and only if the user has **create temporary table** privilege on the table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AttachTable = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AttachTable', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ATTACH TABLE` statement if and only if the user has **create table** privilege on the table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DropTable = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DropTable', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DROP TABLE` statement if and only if the user has **drop table** privilege on the table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DropDatabase = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DropDatabase', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DROP DATABASE` statement if and only if the user has **drop database** privilege on the database,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DropDictionary = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DropDictionary', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DROP DICTIONARY` statement if and only if the user has **drop dictionary** privilege on the dictionary,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DetachTable = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DetachTable', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DETACH TABLE` statement if and only if the user has **drop table** privilege on the table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DetachView = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DetachView', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DETACH VIEW` statement if and only if the user has **drop view** privilege on the view,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DetachDatabase = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DetachDatabase', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DETACH DATABASE` statement if and only if the user has **drop database** privilege on the database,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DetachDictionary = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DetachDictionary', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DETACH DICTIONARY` statement if and only if the user has **drop dictionary** privilege on the dictionary,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Truncate = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Truncate', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `TRUNCATE TABLE` statement if and only if the user has **truncate table** privilege on the table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Optimize = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Optimize', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `OPTIMIZE TABLE` statement if and only if the user has **optimize table** privilege on the table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_KillQuery = Requirement( - name='RQ.SRS-006.RBAC.Privileges.KillQuery', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `KILL QUERY` statement if and only if the user has **kill query** privilege,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_KillMutation = Requirement( - name='RQ.SRS-006.RBAC.Privileges.KillMutation', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `KILL MUTATION` statement if and only if\n' - 'the user has the privilege that created the mutation, either directly or through a role.\n' - 'For example, to `KILL MUTATION` after `ALTER UPDATE` query, the user needs `ALTER UPDATE` privilege.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_KillMutation_AlterUpdate = Requirement( - name='RQ.SRS-006.RBAC.Privileges.KillMutation.AlterUpdate', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER UPDATE` mutation if and only if\n' - 'the user has `ALTER UPDATE` privilege on the table where the mutation was created, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_KillMutation_AlterDelete = Requirement( - name='RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDelete', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER DELETE` mutation if and only if\n' - 'the user has `ALTER DELETE` privilege on the table where the mutation was created, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_KillMutation_AlterDropColumn = Requirement( - name='RQ.SRS-006.RBAC.Privileges.KillMutation.AlterDropColumn', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `KILL MUTATION` query on an `ALTER DROP COLUMN` mutation if and only if\n' - 'the user has `ALTER DROP COLUMN` privilege on the table where the mutation was created, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowTables_Privilege = Requirement( - name='RQ.SRS-006.RBAC.ShowTables.Privilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL grant **show tables** privilege on a table to a user if that user has recieved any grant,\n' - 'including `SHOW TABLES`, on that table, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowTables_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowTables.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW TABLES` statement if and only if the user has **show tables** privilege,\n' - 'or any privilege on the table either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ExistsTable_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ExistsTable.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `EXISTS table` statement if and only if the user has **show tables** privilege,\n' - 'or any privilege on the table either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_CheckTable_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.CheckTable.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `CHECK table` statement if and only if the user has **show tables** privilege,\n' - 'or any privilege on the table either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowDatabases_Privilege = Requirement( - name='RQ.SRS-006.RBAC.ShowDatabases.Privilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL grant **show databases** privilege on a database to a user if that user has recieved any grant,\n' - 'including `SHOW DATABASES`, on that table, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowDatabases_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowDatabases.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW DATABASES` statement if and only if the user has **show databases** privilege,\n' - 'or any privilege on the database either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowCreateDatabase_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowCreateDatabase.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW CREATE DATABASE` statement if and only if the user has **show databases** privilege,\n' - 'or any privilege on the database either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_UseDatabase_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.UseDatabase.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `USE database` statement if and only if the user has **show databases** privilege,\n' - 'or any privilege on the database either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowColumns_Privilege = Requirement( - name='RQ.SRS-006.RBAC.ShowColumns.Privilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking the `SHOW COLUMNS` privilege.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowCreateTable_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowCreateTable.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW CREATE TABLE` statement if and only if the user has **show columns** privilege on that table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_DescribeTable_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.DescribeTable.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DESCRIBE table` statement if and only if the user has **show columns** privilege on that table,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowDictionaries_Privilege = Requirement( - name='RQ.SRS-006.RBAC.ShowDictionaries.Privilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL grant **show dictionaries** privilege on a dictionary to a user if that user has recieved any grant,\n' - 'including `SHOW DICTIONARIES`, on that dictionary, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowDictionaries_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowDictionaries.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW DICTIONARIES` statement if and only if the user has **show dictionaries** privilege,\n' - 'or any privilege on the dictionary either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowCreateDictionary_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowCreateDictionary.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW CREATE DICTIONARY` statement if and only if the user has **show dictionaries** privilege,\n' - 'or any privilege on the dictionary either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ExistsDictionary_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ExistsDictionary.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `EXISTS dictionary` statement if and only if the user has **show dictionaries** privilege,\n' - 'or any privilege on the dictionary either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_CreateUser = Requirement( - name='RQ.SRS-006.RBAC.Privileges.CreateUser', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `CREATE USER` statement if and only if the user has **create user** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_CreateUser_DefaultRole = Requirement( - name='RQ.SRS-006.RBAC.Privileges.CreateUser.DefaultRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `CREATE USER` statement with `DEFAULT ROLE ` clause if and only if\n' - 'the user has **create user** privilege and the role with **admin option**, or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterUser = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterUser', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ALTER USER` statement if and only if the user has **alter user** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DropUser = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DropUser', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DROP USER` statement if and only if the user has **drop user** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_CreateRole = Requirement( - name='RQ.SRS-006.RBAC.Privileges.CreateRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `CREATE ROLE` statement if and only if the user has **create role** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterRole = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ALTER ROLE` statement if and only if the user has **alter role** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DropRole = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DropRole', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DROP ROLE` statement if and only if the user has **drop role** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_CreateRowPolicy = Requirement( - name='RQ.SRS-006.RBAC.Privileges.CreateRowPolicy', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `CREATE ROW POLICY` statement if and only if the user has **create row policy** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterRowPolicy = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterRowPolicy', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ALTER ROW POLICY` statement if and only if the user has **alter row policy** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DropRowPolicy = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DropRowPolicy', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DROP ROW POLICY` statement if and only if the user has **drop row policy** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_CreateQuota = Requirement( - name='RQ.SRS-006.RBAC.Privileges.CreateQuota', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `CREATE QUOTA` statement if and only if the user has **create quota** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterQuota = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterQuota', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ALTER QUOTA` statement if and only if the user has **alter quota** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DropQuota = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DropQuota', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DROP QUOTA` statement if and only if the user has **drop quota** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_CreateSettingsProfile = Requirement( - name='RQ.SRS-006.RBAC.Privileges.CreateSettingsProfile', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `CREATE SETTINGS PROFILE` statement if and only if the user has **create settings profile** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AlterSettingsProfile = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AlterSettingsProfile', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `ALTER SETTINGS PROFILE` statement if and only if the user has **alter settings profile** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_DropSettingsProfile = Requirement( - name='RQ.SRS-006.RBAC.Privileges.DropSettingsProfile', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `DROP SETTINGS PROFILE` statement if and only if the user has **drop settings profile** privilege,\n' - 'or either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_RoleAdmin = Requirement( - name='RQ.SRS-006.RBAC.Privileges.RoleAdmin', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute any role grant or revoke by a user with `ROLE ADMIN` privilege.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowUsers_Privilege = Requirement( - name='RQ.SRS-006.RBAC.ShowUsers.Privilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SHOW USERS` privilege when\n' - 'the user is granted `SHOW USERS`, `SHOW CREATE USER`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowUsers_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowUsers.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW USERS` statement if and only if the user has **show users** privilege,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowCreateUser_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowCreateUser.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW CREATE USER` statement if and only if the user has **show users** privilege,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowRoles_Privilege = Requirement( - name='RQ.SRS-006.RBAC.ShowRoles.Privilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SHOW ROLES` privilege when\n' - 'the user is granted `SHOW ROLES`, `SHOW CREATE ROLE`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowRoles_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowRoles.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW ROLES` statement if and only if the user has **show roles** privilege,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowCreateRole_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowCreateRole.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW CREATE ROLE` statement if and only if the user has **show roles** privilege,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowRowPolicies_Privilege = Requirement( - name='RQ.SRS-006.RBAC.ShowRowPolicies.Privilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SHOW ROW POLICIES` privilege when\n' - 'the user is granted `SHOW ROW POLICIES`, `SHOW POLICIES`, `SHOW CREATE ROW POLICY`,\n' - '`SHOW CREATE POLICY`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowRowPolicies_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowRowPolicies.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW ROW POLICIES` or `SHOW POLICIES` statement if and only if\n' - 'the user has **show row policies** privilege, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowCreateRowPolicy_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowCreateRowPolicy.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW CREATE ROW POLICY` or `SHOW CREATE POLICY` statement\n' - 'if and only if the user has **show row policies** privilege,either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowQuotas_Privilege = Requirement( - name='RQ.SRS-006.RBAC.ShowQuotas.Privilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SHOW QUOTAS` privilege when\n' - 'the user is granted `SHOW QUOTAS`, `SHOW CREATE QUOTA`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowQuotas_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowQuotas.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW QUOTAS` statement if and only if the user has **show quotas** privilege,\n' - 'either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowCreateQuota_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowCreateQuota.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW CREATE QUOTA` statement if and only if\n' - 'the user has **show quotas** privilege, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowSettingsProfiles_Privilege = Requirement( - name='RQ.SRS-006.RBAC.ShowSettingsProfiles.Privilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SHOW SETTINGS PROFILES` privilege when\n' - 'the user is granted `SHOW SETTINGS PROFILES`, `SHOW PROFILES`, `SHOW CREATE SETTINGS PROFILE`,\n' - '`SHOW SETTINGS PROFILE`, `SHOW ACCESS`, or `ACCESS MANAGEMENT`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowSettingsProfiles_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowSettingsProfiles.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW SETTINGS PROFILES` or `SHOW PROFILES` statement\n' - 'if and only if the user has **show settings profiles** privilege, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_ShowCreateSettingsProfile_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.ShowCreateSettingsProfile.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `SHOW CREATE SETTINGS PROFILE` or `SHOW CREATE PROFILE` statement\n' - 'if and only if the user has **show settings profiles** privilege, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_dictGet_Privilege = Requirement( - name='RQ.SRS-006.RBAC.dictGet.Privilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `dictGet` privilege when\n' - 'the user is granted `dictGet`, `dictHas`, `dictGetHierarchy`, or `dictIsIn`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_dictGet_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.dictGet.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `dictGet` statement\n' - 'if and only if the user has **dictGet** privilege on that dictionary, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_dictGet_Type_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.dictGet.Type.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `dictGet[TYPE]` statement\n' - 'if and only if the user has **dictGet** privilege on that dictionary, either directly or through a role.\n' - 'Available types:\n' - '\n' - '* Int8\n' - '* Int16\n' - '* Int32\n' - '* Int64\n' - '* UInt8\n' - '* UInt16\n' - '* UInt32\n' - '* UInt64\n' - '* Float32\n' - '* Float64\n' - '* Date\n' - '* DateTime\n' - '* UUID\n' - '* String\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_dictGet_OrDefault_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.dictGet.OrDefault.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `dictGetOrDefault` statement\n' - 'if and only if the user has **dictGet** privilege on that dictionary, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_dictHas_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.dictHas.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `dictHas` statement\n' - 'if and only if the user has **dictGet** privilege, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_dictGetHierarchy_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.dictGetHierarchy.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `dictGetHierarchy` statement\n' - 'if and only if the user has **dictGet** privilege, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_dictIsIn_RequiredPrivilege = Requirement( - name='RQ.SRS-006.RBAC.dictIsIn.RequiredPrivilege', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `dictIsIn` statement\n' - 'if and only if the user has **dictGet** privilege, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Introspection = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Introspection', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `INTROSPECTION` privilege when\n' - 'the user is granted `INTROSPECTION` or `INTROSPECTION FUNCTIONS`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Introspection_addressToLine = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Introspection.addressToLine', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `addressToLine` statement if and only if\n' - 'the user has **introspection** privilege, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Introspection_addressToSymbol = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Introspection.addressToSymbol', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `addressToSymbol` statement if and only if\n' - 'the user has **introspection** privilege, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Introspection_demangle = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Introspection.demangle', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `demangle` statement if and only if\n' - 'the user has **introspection** privilege, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Shutdown = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Shutdown', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM SHUTDOWN` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM SHUTDOWN`, `SHUTDOWN`,or `SYSTEM KILL`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_DropCache = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.DropCache', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM DROP CACHE` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, or `DROP CACHE`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_DropCache_DNS = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.DropCache.DNS', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM DROP DNS CACHE` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP DNS CACHE`,\n' - '`SYSTEM DROP DNS`, `DROP DNS CACHE`, or `DROP DNS`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_DropCache_Mark = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.DropCache.Mark', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM DROP MARK CACHE` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP MARK CACHE`,\n' - '`SYSTEM DROP MARK`, `DROP MARK CACHE`, or `DROP MARKS`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_DropCache_Uncompressed = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.DropCache.Uncompressed', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM DROP UNCOMPRESSED CACHE` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM DROP CACHE`, `DROP CACHE`, `SYSTEM DROP UNCOMPRESSED CACHE`,\n' - '`SYSTEM DROP UNCOMPRESSED`, `DROP UNCOMPRESSED CACHE`, or `DROP UNCOMPRESSED`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Reload = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Reload', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM RELOAD` privilege when\n' - 'the user is granted `SYSTEM` or `SYSTEM RELOAD`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Reload_Config = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Reload.Config', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM RELOAD CONFIG` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD CONFIG`, or `RELOAD CONFIG`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Reload_Dictionary = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionary', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM RELOAD DICTIONARY` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARIES`, `RELOAD DICTIONARIES`, or `RELOAD DICTIONARY`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Reload_Dictionaries = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Reload.Dictionaries', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM RELOAD DICTIONARIES` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARIES`, `RELOAD DICTIONARIES`, or `RELOAD DICTIONARY`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Reload_EmbeddedDictionaries = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Reload.EmbeddedDictionaries', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM RELOAD EMBEDDED DICTIONARIES` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM RELOAD`, `SYSTEM RELOAD DICTIONARY ON *.*`, or `SYSTEM RELOAD EMBEDDED DICTIONARIES`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Merges = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Merges', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM MERGES` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM MERGES`, `SYSTEM STOP MERGES`, `SYSTEM START MERGES`, `STOP MERGES`, or `START MERGES`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_TTLMerges = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.TTLMerges', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM TTL MERGES` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM TTL MERGES`, `SYSTEM STOP TTL MERGES`, `SYSTEM START TTL MERGES`, `STOP TTL MERGES`, or `START TTL MERGES`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Fetches = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Fetches', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM FETCHES` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM FETCHES`, `SYSTEM STOP FETCHES`, `SYSTEM START FETCHES`, `STOP FETCHES`, or `START FETCHES`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Moves = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Moves', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM MOVES` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM MOVES`, `SYSTEM STOP MOVES`, `SYSTEM START MOVES`, `STOP MOVES`, or `START MOVES`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Sends = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Sends', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM SENDS` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM SENDS`, `SYSTEM STOP SENDS`, `SYSTEM START SENDS`, `STOP SENDS`, or `START SENDS`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Sends_Distributed = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Sends.Distributed', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM DISTRIBUTED SENDS` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM DISTRIBUTED SENDS`, `SYSTEM STOP DISTRIBUTED SENDS`,\n' - '`SYSTEM START DISTRIBUTED SENDS`, `STOP DISTRIBUTED SENDS`, or `START DISTRIBUTED SENDS`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Sends_Replicated = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Sends.Replicated', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM REPLICATED SENDS` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM REPLICATED SENDS`, `SYSTEM STOP REPLICATED SENDS`,\n' - '`SYSTEM START REPLICATED SENDS`, `STOP REPLICATED SENDS`, or `START REPLICATED SENDS`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_ReplicationQueues = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.ReplicationQueues', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM REPLICATION QUEUES` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM REPLICATION QUEUES`, `SYSTEM STOP REPLICATION QUEUES`,\n' - '`SYSTEM START REPLICATION QUEUES`, `STOP REPLICATION QUEUES`, or `START REPLICATION QUEUES`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_SyncReplica = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.SyncReplica', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM SYNC REPLICA` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM SYNC REPLICA`, or `SYNC REPLICA`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_RestartReplica = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.RestartReplica', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM RESTART REPLICA` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM RESTART REPLICA`, or `RESTART REPLICA`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Flush = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Flush', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM FLUSH` privilege when\n' - 'the user is granted `SYSTEM` or `SYSTEM FLUSH`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Flush_Distributed = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Flush.Distributed', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM FLUSH DISTRIBUTED` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM FLUSH DISTRIBUTED`, or `FLUSH DISTRIBUTED`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_System_Flush_Logs = Requirement( - name='RQ.SRS-006.RBAC.Privileges.System.Flush.Logs', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully grant `SYSTEM FLUSH LOGS` privilege when\n' - 'the user is granted `SYSTEM`, `SYSTEM FLUSH LOGS`, or `FLUSH LOGS`.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Sources = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Sources', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking `SOURCES` privilege from\n' - 'the user, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Sources_File = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Sources.File', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the use of `FILE` source by a user if and only if\n' - 'the user has `FILE` or `SOURCES` privileges granted to them directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Sources_URL = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Sources.URL', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the use of `URL` source by a user if and only if\n' - 'the user has `URL` or `SOURCES` privileges granted to them directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Sources_Remote = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Sources.Remote', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the use of `REMOTE` source by a user if and only if\n' - 'the user has `REMOTE` or `SOURCES` privileges granted to them directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Sources_MySQL = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Sources.MySQL', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the use of `MySQL` source by a user if and only if\n' - 'the user has `MySQL` or `SOURCES` privileges granted to them directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Sources_ODBC = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Sources.ODBC', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the use of `ODBC` source by a user if and only if\n' - 'the user has `ODBC` or `SOURCES` privileges granted to them directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Sources_JDBC = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Sources.JDBC', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the use of `JDBC` source by a user if and only if\n' - 'the user has `JDBC` or `SOURCES` privileges granted to them directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Sources_HDFS = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Sources.HDFS', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the use of `HDFS` source by a user if and only if\n' - 'the user has `HDFS` or `SOURCES` privileges granted to them directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_Sources_S3 = Requirement( - name='RQ.SRS-006.RBAC.Privileges.Sources.S3', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support the use of `S3` source by a user if and only if\n' - 'the user has `S3` or `SOURCES` privileges granted to them directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_GrantOption = Requirement( - name='RQ.SRS-006.RBAC.Privileges.GrantOption', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL successfully execute `GRANT` or `REVOKE` privilege statements by a user if and only if\n' - 'the user has that privilege with `GRANT OPTION`, either directly or through a role.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_All = Requirement( - name='RQ.SRS-006.RBAC.Privileges.All', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support granting or revoking `ALL` privilege.\n' - '\n' - ), - link=None) - -RQ_SRS_006_RBAC_Privileges_AdminOption = Requirement( - name='RQ.SRS-006.RBAC.Privileges.AdminOption', - version='1.0', - priority=None, - group=None, - type=None, - uid=None, - description=( - '[ClickHouse] SHALL support a user granting or revoking a role if and only if\n' - 'the user has that role with `ADMIN OPTION` privilege.\n' - '\n' - ), - link=None) diff --git a/tests/testflows/rbac/tests/privileges/admin_option.py b/tests/testflows/rbac/tests/privileges/admin_option.py index 88dadc8522c..f6115839bf5 100644 --- a/tests/testflows/rbac/tests/privileges/admin_option.py +++ b/tests/testflows/rbac/tests/privileges/admin_option.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(test=grant_role, flags=TE)(grant_target_name=user_name, user_name=user_name) + Suite(test=grant_role)(grant_target_name=user_name, user_name=user_name) @TestSuite def privileges_granted_via_role(self, node=None): @@ -35,7 +35,7 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(test=grant_role, flags=TE)(grant_target_name=role_name, user_name=user_name) + Suite(test=grant_role)(grant_target_name=role_name, user_name=user_name) @TestSuite def grant_role(self, grant_target_name, user_name, node=None): @@ -52,7 +52,13 @@ def grant_role(self, grant_target_name, user_name, node=None): with user(node, target_user_name), role(node, grant_role_name): - with When("I check the user can't grant a role"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't grant a role"): node.query(f"GRANT {grant_role_name} TO {target_user_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -109,6 +115,7 @@ def grant_role(self, grant_target_name, user_name, node=None): @Name("admin option") @Requirements( RQ_SRS_006_RBAC_Privileges_AdminOption("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of ADMIN OPTION. diff --git a/tests/testflows/rbac/tests/privileges/all_role.py b/tests/testflows/rbac/tests/privileges/all_role.py new file mode 100644 index 00000000000..629848a2746 --- /dev/null +++ b/tests/testflows/rbac/tests/privileges/all_role.py @@ -0,0 +1,37 @@ +from testflows.core import * +from testflows.asserts import error + +from rbac.requirements import * +from rbac.helper.common import * +import rbac.helper.errors as errors + +@TestScenario +def privilege_check(self, node=None): + '''Check that a role named ALL only grants privileges that it already has. + ''' + + user_name = f"user_{getuid()}" + + if node is None: + node = self.context.node + + with user(node, f"{user_name}"), role(node, "ALL"): + + with When("I grant the ALL role to the user"): + node.query(f"GRANT ALL TO {user_name}") + + with Then("I check the user doesn't have any privileges"): + output = node.query("SHOW TABLES", settings=[("user",user_name)]).output + assert output == '', error() + +@TestFeature +@Name("all role") +@Requirements( + RQ_SRS_006_RBAC_Privileges_RoleAll("1.0"), +) +def feature(self, node="clickhouse1"): + """Check the RBAC functionality of the role 'ALL'. + """ + self.context.node = self.context.cluster.node(node) + + Scenario(run=privilege_check, setup=instrument_clickhouse_server_log) diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_column.py b/tests/testflows/rbac/tests/privileges/alter/alter_column.py index 430872029b5..fe767ec15fa 100755 --- a/tests/testflows/rbac/tests/privileges/alter/alter_column.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_column.py @@ -354,6 +354,10 @@ def check_add_column_when_privilege_is_not_granted(table, user, node, column=Non node.query(f"ALTER TABLE {table} ADD COLUMN {column} String", settings = [("user", user)], exitcode=exitcode, message=message) + with Then("I try to ADD COLUMN"): + node.query(f"ALTER TABLE {table} ADD COLUMN {column} String", + settings = [("user", user)], exitcode=exitcode, message=message) + def check_clear_column_when_privilege_is_not_granted(table, user, node, column=None): """Ensures CLEAR COLUMN errors as expected without the required privilege for the specified user. @@ -366,6 +370,13 @@ def check_clear_column_when_privilege_is_not_granted(table, user, node, column=N node.query(f"ALTER TABLE {table} CLEAR COLUMN {column}", settings = [("user", user)], exitcode=exitcode, message=message) + with And(f"I grant NONE to the user"): + node.query(f"GRANT NONE TO {user}") + + with Then("I try to CLEAR COLUMN"): + node.query(f"ALTER TABLE {table} CLEAR COLUMN {column}", + settings = [("user", user)], exitcode=exitcode, message=message) + def check_modify_column_when_privilege_is_not_granted(table, user, node, column=None): """Ensures MODIFY COLUMN errors as expected without the required privilege for the specified user. @@ -378,6 +389,13 @@ def check_modify_column_when_privilege_is_not_granted(table, user, node, column= node.query(f"ALTER TABLE {table} MODIFY COLUMN {column} String", settings = [("user", user)], exitcode=exitcode, message=message) + with And(f"I grant NONE to the user"): + node.query(f"GRANT NONE TO {user}") + + with Then("I try to MODIFY COLUMN"): + node.query(f"ALTER TABLE {table} MODIFY COLUMN {column} String", + settings = [("user", user)], exitcode=exitcode, message=message) + def check_rename_column_when_privilege_is_not_granted(table, user, node, column=None): """Ensures RENAME COLUMN errors as expected without the required privilege for the specified user. @@ -392,6 +410,13 @@ def check_rename_column_when_privilege_is_not_granted(table, user, node, column= node.query(f"ALTER TABLE {table} RENAME COLUMN {column} TO {new_column}", settings = [("user", user)], exitcode=exitcode, message=message) + with And(f"I grant NONE to the user"): + node.query(f"GRANT NONE TO {user}") + + with Then("I try to RENAME COLUMN"): + node.query(f"ALTER TABLE {table} RENAME COLUMN {column} TO {new_column}", + settings = [("user", user)], exitcode=exitcode, message=message) + def check_comment_column_when_privilege_is_not_granted(table, user, node, column=None): """Ensures COMMENT COLUMN errors as expected without the required privilege for the specified user. @@ -404,6 +429,13 @@ def check_comment_column_when_privilege_is_not_granted(table, user, node, column node.query(f"ALTER TABLE {table} COMMENT COLUMN {column} 'This is a comment.'", settings = [("user", user)], exitcode=exitcode, message=message) + with And(f"I grant NONE to the user"): + node.query(f"GRANT NONE TO {user}") + + with When("I try to COMMENT COLUMN"): + node.query(f"ALTER TABLE {table} COMMENT COLUMN {column} 'This is a comment.'", + settings = [("user", user)], exitcode=exitcode, message=message) + def check_drop_column_when_privilege_is_not_granted(table, user, node, column=None): """Ensures DROP COLUMN errors as expected without the required privilege for the specified user. @@ -416,6 +448,13 @@ def check_drop_column_when_privilege_is_not_granted(table, user, node, column=No node.query(f"ALTER TABLE {table} DROP COLUMN {column}", settings = [("user", user)], exitcode=exitcode, message=message) + with And(f"I grant NONE to the user"): + node.query(f"GRANT NONE TO {user}") + + with Then("I try to DROP COLUMN"): + node.query(f"ALTER TABLE {table} DROP COLUMN {column}", + settings = [("user", user)], exitcode=exitcode, message=message) + @TestScenario def user_with_some_privileges(self, permutation, table_type, node=None): """Check that user with some privileges of ALTER COLUMN is able @@ -676,7 +715,8 @@ def scenario_parallelization(self, table_type, permutation): @Requirements( RQ_SRS_006_RBAC_Privileges_AlterColumn("1.0"), RQ_SRS_006_RBAC_Privileges_AlterColumn_TableEngines("1.0"), - RQ_SRS_006_RBAC_Privileges_All("1.0") + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_constraint.py b/tests/testflows/rbac/tests/privileges/alter/alter_constraint.py index 59ff1828222..58f4349459c 100755 --- a/tests/testflows/rbac/tests/privileges/alter/alter_constraint.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_constraint.py @@ -275,7 +275,8 @@ def user_with_privileges_on_cluster(self, table_type, node=None): @Requirements( RQ_SRS_006_RBAC_Privileges_AlterConstraint("1.0"), RQ_SRS_006_RBAC_Privileges_AlterConstraint_TableEngines("1.0"), - RQ_SRS_006_RBAC_Privileges_All("1.0") + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_delete.py b/tests/testflows/rbac/tests/privileges/alter/alter_delete.py index 9f46e6cdb3d..93d520f91bd 100644 --- a/tests/testflows/rbac/tests/privileges/alter/alter_delete.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_delete.py @@ -1,5 +1,3 @@ -from multiprocessing.dummy import Pool - from testflows.core import * from testflows.asserts import error @@ -11,7 +9,8 @@ aliases = {"ALTER DELETE", "DELETE", "ALL"} @TestSuite def privilege_granted_directly_or_via_role(self, table_type, privilege, node=None): - """Check that user is only able to execute ALTER DELETE when they have required privilege, either directly or via role. + """Check that user is only able to execute ALTER DELETE when they have required privilege, + either directly or via role. """ role_name = f"role_{getuid()}" user_name = f"user_{getuid()}" @@ -21,13 +20,16 @@ def privilege_granted_directly_or_via_role(self, table_type, privilege, node=Non with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): with user(node, user_name): + with When(f"I run checks that {user_name} is only able to execute ALTER DELETE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, table_type=table_type, privilege=privilege, node=node) with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): with user(node, user_name), role(node, role_name): + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") + with And(f"I run checks that {user_name} with {role_name} is only able to execute ALTER DELETE with required privileges"): privilege_check(grant_target_name=role_name, user_name=user_name, table_type=table_type, privilege=privilege, node=node) @@ -38,26 +40,41 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No with Scenario("user without privilege", setup=instrument_clickhouse_server_log): table_name = f"merge_tree_{getuid()}" + with table(node, table_name, table_type): - with When("I attempt to delete columns without privilege"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to delete columns without privilege"): node.query(f"ALTER TABLE {table_name} DELETE WHERE 1", settings = [("user", user_name)], exitcode=exitcode, message=message) with Scenario("user with privilege", setup=instrument_clickhouse_server_log): table_name = f"merge_tree_{getuid()}" + with table(node, table_name, table_type): + with When("I grant the delete privilege"): node.query(f"GRANT {privilege} ON {table_name} TO {grant_target_name}") + with Then("I attempt to delete columns"): node.query(f"ALTER TABLE {table_name} DELETE WHERE 1", settings = [("user", user_name)]) with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): table_name = f"merge_tree_{getuid()}" + with table(node, table_name, table_type): + with When("I grant the delete privilege"): node.query(f"GRANT {privilege} ON {table_name} TO {grant_target_name}") + with And("I revoke the delete privilege"): node.query(f"REVOKE {privilege} ON {table_name} FROM {grant_target_name}") + with Then("I attempt to delete columns"): node.query(f"ALTER TABLE {table_name} DELETE WHERE 1", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -65,7 +82,8 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AlterDelete("1.0"), - RQ_SRS_006_RBAC_Privileges_All("1.0") + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_fetch.py b/tests/testflows/rbac/tests/privileges/alter/alter_fetch.py index 56f2d48e7d2..b4ff0b65fd4 100644 --- a/tests/testflows/rbac/tests/privileges/alter/alter_fetch.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_fetch.py @@ -1,5 +1,3 @@ -from multiprocessing.dummy import Pool - from testflows.core import * from testflows.asserts import error @@ -41,9 +39,16 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No with Scenario("user without privilege", setup=instrument_clickhouse_server_log): table_name = f"merge_tree_{getuid()}" + with table(node, table_name, table_type): - with When("I attempt to fetch a partition without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to fetch a partition without privilege"): node.query(f"ALTER TABLE {table_name} FETCH PARTITION 1 FROM '/clickhouse/'", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -75,7 +80,8 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AlterFetch("1.0"), - RQ_SRS_006_RBAC_Privileges_All("1.0") + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type",[ ("ReplicatedMergeTree-sharded_cluster",), diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_freeze.py b/tests/testflows/rbac/tests/privileges/alter/alter_freeze.py index 32bd4602044..775e2be270d 100644 --- a/tests/testflows/rbac/tests/privileges/alter/alter_freeze.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_freeze.py @@ -1,5 +1,3 @@ -from multiprocessing.dummy import Pool - from testflows.core import * from testflows.asserts import error @@ -38,14 +36,22 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No with Scenario("user without privilege", setup=instrument_clickhouse_server_log): table_name = f"merge_tree_{getuid()}" + with table(node, table_name, table_type): - with When("I attempt to freeze partitions without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to freeze partitions without privilege"): node.query(f"ALTER TABLE {table_name} FREEZE", settings = [("user", user_name)], exitcode=exitcode, message=message) with Scenario("user with privilege", setup=instrument_clickhouse_server_log): table_name = f"merge_tree_{getuid()}" + with table(node, table_name, table_type): with When("I grant the freeze privilege"): @@ -56,6 +62,7 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): table_name = f"merge_tree_{getuid()}" + with table(node, table_name, table_type): with When("I grant the freeze privilege"): @@ -70,7 +77,8 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AlterFreeze("1.0"), - RQ_SRS_006_RBAC_Privileges_All("1.0") + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_index.py b/tests/testflows/rbac/tests/privileges/alter/alter_index.py index cd2729f5641..eeb126e95a5 100755 --- a/tests/testflows/rbac/tests/privileges/alter/alter_index.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_index.py @@ -26,7 +26,7 @@ aliases = { "MATERIALIZE INDEX" : ["ALTER MATERIALIZE INDEX", "MATERIALIZE INDEX"], "CLEAR INDEX": ["ALTER CLEAR INDEX", "CLEAR INDEX"], "DROP INDEX": ["ALTER DROP INDEX", "DROP INDEX"], - "ALTER INDEX": ["ALTER INDEX", "INDEX"] # super-privilege + "ALTER INDEX": ["ALTER INDEX", "INDEX", "ALL"] # super-privilege } # Extra permutation is for 'ALTER INDEX' super-privilege @@ -302,7 +302,6 @@ def check_drop_index_when_privilege_is_not_granted(table, user, node): settings = [("user", user)], exitcode=exitcode, message=message) @TestScenario -@Flags(TE) def user_with_some_privileges(self, table_type, node=None): """Check that user with any permutation of ALTER INDEX subprivileges is able to alter the table for privileges granted, and not for privileges not granted. @@ -325,7 +324,6 @@ def user_with_some_privileges(self, table_type, node=None): alter_index_privilege_handler(permutation, table_name, user_name, node) @TestScenario -@Flags(TE) @Requirements( RQ_SRS_006_RBAC_Privileges_AlterIndex_Revoke("1.0"), ) @@ -355,7 +353,6 @@ def user_with_revoked_privileges(self, table_type, node=None): alter_index_privilege_handler(0, table_name, user_name, node) @TestScenario -@Flags(TE) @Requirements( RQ_SRS_006_RBAC_Privileges_AlterIndex_Grant("1.0"), ) @@ -385,7 +382,6 @@ def role_with_some_privileges(self, table_type, node=None): alter_index_privilege_handler(permutation, table_name, user_name, node) @TestScenario -@Flags(TE) def user_with_revoked_role(self, table_type, node=None): """Check that user with a role that has ALTER INDEX privilege on a table is unable to ALTER INDEX from that table after the role with privilege has been revoked from the user. @@ -416,7 +412,6 @@ def user_with_revoked_role(self, table_type, node=None): alter_index_privilege_handler(0, table_name, user_name, node) @TestScenario -@Flags(TE) @Requirements( RQ_SRS_006_RBAC_Privileges_AlterIndex_Cluster("1.0"), ) @@ -451,12 +446,13 @@ def user_with_privileges_on_cluster(self, table_type, node=None): @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AlterIndex("1.0"), - RQ_SRS_006_RBAC_Privileges_AlterIndex_TableEngines("1.0") + RQ_SRS_006_RBAC_Privileges_AlterIndex_TableEngines("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() ]) -@Flags(TE) @Name("alter index") def feature(self, node="clickhouse1", stress=None, parallel=None): self.context.node = self.context.cluster.node(node) diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_move.py b/tests/testflows/rbac/tests/privileges/alter/alter_move.py index b53375434fe..d370edc35de 100644 --- a/tests/testflows/rbac/tests/privileges/alter/alter_move.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_move.py @@ -7,7 +7,7 @@ from rbac.requirements import * from rbac.helper.common import * import rbac.helper.errors as errors -aliases = {"ALTER MOVE PARTITION", "ALTER MOVE PART", "MOVE PARTITION", "MOVE PART"} +aliases = {"ALTER MOVE PARTITION", "ALTER MOVE PART", "MOVE PARTITION", "MOVE PART", "ALL"} @TestSuite def privilege_granted_directly_or_via_role(self, table_type, privilege, node=None): @@ -45,7 +45,13 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No with table(node, f"{source_table_name},{target_table_name}", table_type): - with When("I attempt to move partition without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to move partition without privilege"): node.query(f"ALTER TABLE {source_table_name} MOVE PARTITION 1 TO TABLE {target_table_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -151,6 +157,8 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AlterMove("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_quota.py b/tests/testflows/rbac/tests/privileges/alter/alter_quota.py index 4d0d55c86de..faad7c001f4 100644 --- a/tests/testflows/rbac/tests/privileges/alter/alter_quota.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_quota.py @@ -31,7 +31,7 @@ def alter_quota_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=alter_quota, flags=TE, + Suite(run=alter_quota, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in alter_quota.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -52,13 +52,14 @@ def alter_quota_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=alter_quota, flags=TE, + Suite(run=alter_quota, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in alter_quota.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("ALTER QUOTA",), ]) @@ -75,7 +76,13 @@ def alter_quota(self, privilege, grant_target_name, user_name, node=None): with quota(node, alter_quota_name): - with When("I check the user can't alter a quota"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't alter a quota"): node.query(f"ALTER QUOTA {alter_quota_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -127,6 +134,8 @@ def alter_quota(self, privilege, grant_target_name, user_name, node=None): @Name("alter quota") @Requirements( RQ_SRS_006_RBAC_Privileges_AlterQuota("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of ALTER QUOTA. diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_role.py b/tests/testflows/rbac/tests/privileges/alter/alter_role.py index cf98d66a689..49e8baa191b 100644 --- a/tests/testflows/rbac/tests/privileges/alter/alter_role.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_role.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=alter_role, flags=TE, + Suite(run=alter_role, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in alter_role.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=alter_role, flags=TE, + Suite(run=alter_role, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in alter_role.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("ALTER ROLE",), ]) @@ -58,14 +59,22 @@ def alter_role(self, privilege, grant_target_name, user_name, node=None): with Scenario("ALTER ROLE without privilege"): alter_role_name = f"alter_role_{getuid()}" + with role(node, alter_role_name): - with When("I check the user can't alter a role"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't alter a role"): node.query(f"ALTER ROLE {alter_role_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) with Scenario("ALTER ROLE with privilege"): alter_role_name = f"alter_role_{getuid()}" + with role(node, alter_role_name): with When(f"I grant {privilege}"): @@ -93,6 +102,7 @@ def alter_role(self, privilege, grant_target_name, user_name, node=None): with Scenario("ALTER ROLE with revoked privilege"): alter_role_name = f"alter_role_{getuid()}" + with role(node, alter_role_name): with When(f"I grant {privilege} on the database"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -108,6 +118,8 @@ def alter_role(self, privilege, grant_target_name, user_name, node=None): @Name("alter role") @Requirements( RQ_SRS_006_RBAC_Privileges_AlterRole("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of ALTER ROLE. diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_row_policy.py b/tests/testflows/rbac/tests/privileges/alter/alter_row_policy.py index 6d13d30b823..a0d1e4271bc 100644 --- a/tests/testflows/rbac/tests/privileges/alter/alter_row_policy.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_row_policy.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=alter_row_policy, flags=TE, + Suite(run=alter_row_policy, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in alter_row_policy.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=alter_row_policy, flags=TE, + Suite(run=alter_row_policy, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in alter_row_policy.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("ALTER ROW POLICY",), ("ALTER POLICY",), @@ -65,7 +66,13 @@ def alter_row_policy(self, privilege, grant_target_name, user_name, node=None): with Given("I have a row policy"): node.query(f"CREATE ROW POLICY {alter_row_policy_name} ON {table_name}") - with When("I check the user can't alter a row policy"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't alter a row policy"): node.query(f"ALTER ROW POLICY {alter_row_policy_name} ON {table_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -130,15 +137,986 @@ def alter_row_policy(self, privilege, grant_target_name, user_name, node=None): with Finally("I drop the row policy"): node.query(f"DROP ROW POLICY IF EXISTS {alter_row_policy_name} ON {table_name}") +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Restriction("1.0") +) +def no_grants(self, node=None): + """Check that user is unable to select from a table without a row policy + after a row policy has been altered to have a condition. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + with When("I alter the row policy to have a condition"): + node.query(f"ALTER POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Permissive("1.0"), +) +def permissive(self, node=None): + """Check that user is able to see from a table when they have a PERMISSIVE policy. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1), (2)") + + with When("I alter a row policy to be permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO default") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output and '2' not in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Restrictive("1.0") +) +def restrictive(self, node=None): + """Check that user is able to see values they have a RESTRICTIVE policy for. + """ + + table_name = f"table_{getuid()}" + perm_pol_name = f"perm_pol_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("I have a second row policy"): + row_policy(name=perm_pol_name, table=table_name) + + with And("I alter a row policy to be permissive"): + node.query(f"ALTER ROW POLICY {perm_pol_name} ON {table_name} FOR SELECT USING y=1 OR y=2 TO default") + + with And("I alter a row policy to be restrictive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} AS RESTRICTIVE FOR SELECT USING y=1 TO default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1), (2)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output and '2' not in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_ForSelect("1.0"), +) +def for_select(self, node=None): + """Check that user is able to see values allowed by the row policy condition in the FOR SELECT clause. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with Given("I alter therow policy to use FOR SELECT"): + node.query(f"Alter ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1 TO default") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_Condition("1.0") +) +def condition(self, node=None): + """Check that user is able to see values allowed by the row policy condition. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with When("I alter a row policy to be permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_Condition_None("1.0") +) +def remove_condition(self, node=None): + """Check that user is able to see the table after row policy condition has been removed. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The row policy has a condition"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with When("I alter a row policy to not have a condition"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING NONE") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_IfExists("1.0") +) +def if_exists(self, node=None): + """Check that a row policy altered using IF EXISTS restricts rows as expected. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with When("I have alter a row policy to be permissive using IF EXISTS clause"): + node.query(f"ALTER ROW POLICY IF EXISTS {pol_name} ON {table_name} FOR SELECT USING 1 TO default") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_Rename("1.0") +) +def rename(self, node=None): + """Check that a row policy altered using RENAME restricts rows as expected. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + pol_new_name = f"pol_new_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with And("The row policy is permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with When("I have alter a row policy by renaming it"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} RENAME TO {pol_new_name}") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_new_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_OnCluster("1.0") +) +def on_cluster(self, node=None): + """Check that a row policy altered using ON CLUSTER applies to the nodes of the cluster correctly. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + node2 = self.context.node2 + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy on a cluster on that table"): + node.query(f"CREATE ROW POLICY {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("The table has some values on the first node"): + node.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with And("The table has some values on the second node"): + node2.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with When("I alter the row policy to have a condition"): + node.query(f"ALTER ROW POLICY {pol_name} ON CLUSTER sharded_cluster ON {table_name} FOR SELECT USING 1") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + + with And("I select from another node on the cluster"): + output = node2.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE {table_name} ON CLUSTER sharded_cluster") + +@TestScenario +def diff_policies_on_diff_nodes(self, node=None): + """Check that a row policy altered on a node, does not effect row policy on a different node. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + node2 = self.context.node2 + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy on the cluster"): + node.query(f"CREATE ROW POLICY {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("The table has some values on the first node"): + node.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with And("The table has some values on the second node"): + node2.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with When("I alter the row policy on the first node"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + + with And("I select from another node on the cluster"): + output = node2.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE {table_name} ON CLUSTER sharded_cluster") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment("1.0"), +) +def assignment(self, node=None): + """Check that user is able to see rows from a table when they have PERMISSIVE policy assigned to them. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The row policy is permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with When("I alter a row policy to be assigned to default"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} TO default") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_None("1.0"), +) +def assignment_none(self, node=None): + """Check that no one is affected when a row policy is altered to be assigned to NONE. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The row policy is permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with When("I alter a row policy to be assigned to NONE"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} TO NONE") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_All("1.0"), +) +def assignment_all(self, node=None): + """Check that everyone is effected with a row policy is altered to be assigned to ALL. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The row policy is permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with When("I alter a row policy to be assigned to ALL"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} TO ALL") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_AllExcept("1.0"), +) +def assignment_all_except(self, node=None): + """Check that everyone is except the specified user is effect by a row policy is altered to be assigned to ALL EXCEPT. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The row policy is permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with When("I alter a row policy to be assigned to ALL EXCEPT default"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} TO ALL EXCEPT default") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def nested_view(self, node=None): + """Check that if a user has a row policy on a table and a view is altered to use a condition on that table, + the user is only able to access the rows specified by the assigned policies. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + + try: + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with And("There is a view on the table"): + node.query(f"CREATE VIEW {view_name} AS SELECT * FROM {table_name}") + + with When("I alter the row policy to be permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def nested_live_view_before_policy(self, node=None): + """Check that if a live view exists on a table and then a row policy is created, + the user is only able to select rows specified by the assigned policies from the view. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I add allow_experimental_live_view to the default query settings"): + default_query_settings = getsattr(current().context, "default_query_settings", []) + default_query_settings.append(("allow_experimental_live_view", 1)) + + with And("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with And("There exists a live view on the table"): + node.query(f"CREATE LIVE VIEW {view_name} AS SELECT * FROM {table_name}") + + with When("I alter the row policy to be permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the live view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + + with And("I remove allow_experimental_live_view from the default query settings", flags=TE): + if default_query_settings: + try: + default_query_settings.pop(default_query_settings.index(("allow_experimental_live_view", 1))) + except ValueError: + pass + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def nested_live_view_after_policy(self, node=None): + """Check that if a user has a row policy on a table and a materialized view is created on that table, + the user is only able to select rows specified by the assigned policies from the view. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I add allow_experimental_live_view to the default query settings"): + default_query_settings = getsattr(current().context, "default_query_settings", []) + default_query_settings.append(("allow_experimental_live_view", 1)) + + with And("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with When("I alter the row policy to be permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with And("I create a live view on the table"): + node.query(f"CREATE LIVE VIEW {view_name} AS SELECT * FROM {table_name}") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the live view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + + with And("I remove allow_experimental_live_view from the default query settings", flags=TE): + if default_query_settings: + try: + default_query_settings.pop(default_query_settings.index(("allow_experimental_live_view", 1))) + except ValueError: + pass + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def nested_mat_view_before_policy(self, node=None): + """Check that if a materialized view exists on a table and then a row policy is created, + the user is only able to select rows specified by the assigned policies from the view. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("There exists a mat view on the table"): + node.query(f"CREATE MATERIALIZED VIEW {view_name} ENGINE = Memory AS SELECT * FROM {table_name}") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with When("I alter the row policy"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the materialized view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def nested_mat_view_after_policy(self, node=None): + """Check that if a user has a row policy on a table and a materialized view is created on that table, + the user is only able to select rows specified by the assigned policies from the view. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("I alter the row policy"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with When("I create a mat view on the table"): + node.query(f"CREATE MATERIALIZED VIEW {view_name} ENGINE = Memory AS SELECT * FROM {table_name}") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the materialized view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def populate_mat_view(self, node=None): + """Check that if a user has a row policy on a table and a materialized view is created using POPULATE from that table, + the user can only select the rows from the materialized view specified in the row policy. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("I alter a row policy on the table"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with When("I create a mat view populated by the table"): + node.query(f"CREATE MATERIALIZED VIEW {view_name} ENGINE = Memory POPULATE AS SELECT * FROM {table_name}") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the materialized view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def dist_table(self, node=None): + """Check that if a user has a row policy on a table and a distributed table is created on that table, + the user is only able to access the rows specified by the assigned policies. + """ + + table_name = f"table_{getuid()}" + dist_table_name = f"dist_table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + node2 = self.context.node2 + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I have a distributed table"): + node.query(f"CREATE TABLE {dist_table_name} (x UInt64) ENGINE = Distributed(sharded_cluster, default, {table_name}, rand())") + + with And("The table has some values on the first node"): + node.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with When("I alter the row policy to be permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} ON CLUSTER sharded_cluster FOR SELECT USING 1") + + with Then("I select from the distributed table"): + output = node.query(f"SELECT * FROM {dist_table_name}").output + assert '' == output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {table_name} ON CLUSTER sharded_cluster") + + with And("I drop the distributed table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {dist_table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def dist_table_diff_policies_on_diff_nodes(self, node=None): + """Check that user is only able to select from the distributed table what is allowed by the row policies on each node. + """ + + table_name = f"table_{getuid()}" + dist_table_name = f"dist_table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + node2 = self.context.node2 + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I have a distributed table"): + node.query(f"CREATE TABLE {dist_table_name} (x UInt64) ENGINE = Distributed(sharded_cluster, default, {table_name}, rand())") + + with And("The table has some values on the first node"): + node.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with And("The table has some values on the second node"): + node2.query(f"INSERT INTO {table_name} (x) VALUES (2)") + + with When("I alter the row policy to be permissive on the first node"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with Then("I select from the distributed table"): + output = node.query(f"SELECT * FROM {dist_table_name}").output + assert '1' not in output and '2' in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name} ON CLUSTER sharded_cluster") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {table_name} ON CLUSTER sharded_cluster") + + with And("I drop the distributed table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {dist_table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def dist_table_on_dist_table(self, node=None): + """Check that if a user has a row policy on a table and a distributed table is created on that table, + and another distributed table is created on top of that, + the user is only able to access rows on any of the tables specified by the assigned policies. + """ + table_name = f"table_{getuid()}" + dist_table_name = f"dist_table_{getuid()}" + dist_table_2_name = f"dist_table_2_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + node2 = self.context.node2 + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I have a distributed table on a cluster"): + node.query(f"CREATE TABLE {dist_table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Distributed(sharded_cluster, default, {table_name}, rand())") + + with And("I have a distributed table on the other distributed table"): + node.query(f"CREATE TABLE {dist_table_2_name} (x UInt64) ENGINE = Distributed(sharded_cluster, default, {dist_table_name}, rand())") + + with And("The table has some values on the first node"): + node.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with When("I alter the row policy to be permissive on the first node"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with Then("I select from the second distributed table"): + output = node.query(f"SELECT * FROM {dist_table_2_name}").output + assert '' == output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {table_name} ON CLUSTER sharded_cluster") + + with And("I drop the distributed table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {dist_table_name} ON CLUSTER sharded_cluster") + + with And("I drop the outer distributed table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {dist_table_2_name}") + +@TestScenario +def policy_before_table(self, node=None): + """Check that if the policy is created and altered before the table, + then it is still applied correctly. + """ + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("I alter the row policy"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with table(node, table_name): + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1), (2)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output and '2' not in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0"), +) +def dict(self, node=None): + """Check that if a user has a row policy on a table and a dictionary is created on that table, + the user is only able to access the rows specified by the assigned policies. + """ + + table_name = f"table_{getuid()}" + dict_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + try: + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("I have a table"): + node.query(f"CREATE TABLE {table_name} (key UInt64, val UInt64 DEFAULT 5) ENGINE = Memory") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (key) VALUES (1),(2)") + + with And("I create a dict on the table"): + node.query(f"CREATE DICTIONARY {dict_name} (key UInt64 DEFAULT 0, val UInt64 DEFAULT 5) PRIMARY KEY key SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE {table_name} PASSWORD '' DB 'default')) LIFETIME(MIN 0 MAX 0) LAYOUT(FLAT())") + + with When("I alter the row policy to be permissive"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING key=1 TO default") + + with Then("I try to select from the dict"): + output = node.query(f"SELECT * FROM {dict_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the materialized view", flags=TE): + node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {table_name}") + + @TestFeature @Name("alter row policy") @Requirements( RQ_SRS_006_RBAC_Privileges_AlterRowPolicy("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of ALTER ROW POLICY. """ self.context.node = self.context.cluster.node(node) + self.context.node2 = self.context.cluster.node("clickhouse2") Suite(run=privileges_granted_directly, setup=instrument_clickhouse_server_log) Suite(run=privileges_granted_via_role, setup=instrument_clickhouse_server_log) + + Scenario(run=no_grants, setup=instrument_clickhouse_server_log) + Scenario(run=permissive, setup=instrument_clickhouse_server_log) + Scenario(run=restrictive, setup=instrument_clickhouse_server_log) + Scenario(run=for_select, setup=instrument_clickhouse_server_log) + Scenario(run=condition, setup=instrument_clickhouse_server_log) + Scenario(run=remove_condition, setup=instrument_clickhouse_server_log) + Scenario(run=if_exists, setup=instrument_clickhouse_server_log) + Scenario(run=rename, setup=instrument_clickhouse_server_log) + Scenario(run=on_cluster, setup=instrument_clickhouse_server_log) + Scenario(run=assignment, setup=instrument_clickhouse_server_log) + Scenario(run=assignment_none, setup=instrument_clickhouse_server_log) + Scenario(run=assignment_all, setup=instrument_clickhouse_server_log) + Scenario(run=assignment_all_except, setup=instrument_clickhouse_server_log) + Scenario(run=nested_view, setup=instrument_clickhouse_server_log) + Scenario(run=nested_live_view_before_policy, setup=instrument_clickhouse_server_log) + Scenario(run=nested_live_view_after_policy, setup=instrument_clickhouse_server_log) + Scenario(run=nested_mat_view_before_policy, setup=instrument_clickhouse_server_log) + Scenario(run=nested_mat_view_after_policy, setup=instrument_clickhouse_server_log) + Scenario(run=populate_mat_view, setup=instrument_clickhouse_server_log) + Scenario(run=dist_table, setup=instrument_clickhouse_server_log) + Scenario(run=dist_table_on_dist_table, setup=instrument_clickhouse_server_log) + Scenario(run=dist_table_diff_policies_on_diff_nodes, setup=instrument_clickhouse_server_log) + Scenario(run=diff_policies_on_diff_nodes, setup=instrument_clickhouse_server_log) + Scenario(run=policy_before_table, setup=instrument_clickhouse_server_log) + Scenario(run=dict, setup=instrument_clickhouse_server_log) diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_settings.py b/tests/testflows/rbac/tests/privileges/alter/alter_settings.py index 6ac482fa33d..c2c2110ddf0 100755 --- a/tests/testflows/rbac/tests/privileges/alter/alter_settings.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_settings.py @@ -1,7 +1,5 @@ import json -from multiprocessing.dummy import Pool - from testflows.core import * from testflows.asserts import error @@ -10,7 +8,7 @@ from rbac.helper.common import * import rbac.helper.errors as errors from rbac.helper.tables import table_types -aliases = {"ALTER SETTINGS", "ALTER SETTING", "ALTER MODIFY SETTING", "MODIFY SETTING"} +aliases = {"ALTER SETTINGS", "ALTER SETTING", "ALTER MODIFY SETTING", "MODIFY SETTING", "ALL"} def check_alter_settings_when_privilege_is_granted(table, user, node): """Ensures ADD SETTINGS runs as expected when the privilege is granted to the specified user @@ -21,7 +19,7 @@ def check_alter_settings_when_privilege_is_granted(table, user, node): with And(f"I modify settings"): node.query(f"ALTER TABLE {table} MODIFY SETTING merge_with_ttl_timeout=5", - settings = [("user", user)]) + settings=[("user", user)]) with Then("I verify that the setting is in the table"): output = json.loads(node.query(f"SHOW CREATE TABLE {table} FORMAT JSONEachRow").output) @@ -30,10 +28,16 @@ def check_alter_settings_when_privilege_is_granted(table, user, node): def check_alter_settings_when_privilege_is_not_granted(table, user, node): """Ensures CLEAR SETTINGS runs as expected when the privilege is granted to the specified user """ - with When("I try to use ALTER SETTING, has not been granted"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {user}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {user}") + + with Then("I try to use ALTER SETTING, has not been granted"): exitcode, message = errors.not_enough_privileges(user) node.query(f"ALTER TABLE {table} MODIFY SETTING merge_with_ttl_timeout=5", - settings = [("user", user)], exitcode=exitcode, message=message) + settings=[("user", user)], exitcode=exitcode, message=message) @TestScenario def user_with_privileges(self, privilege, table_type, node=None): @@ -53,6 +57,7 @@ def user_with_privileges(self, privilege, table_type, node=None): with Then(f"I try to ALTER SETTINGS"): check_alter_settings_when_privilege_is_granted(table_name, user_name, node) + @TestScenario @Requirements( RQ_SRS_006_RBAC_Privileges_AlterSettings_Revoke("1.0"), @@ -180,7 +185,9 @@ def scenario_parallelization(self, table_type, privilege): @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AlterSettings("1.0"), - RQ_SRS_006_RBAC_Privileges_AlterSettings_TableEngines("1.0") + RQ_SRS_006_RBAC_Privileges_AlterSettings_TableEngines("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() @@ -208,7 +215,9 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): tasks = [] try: for alias in aliases: - run_scenario(pool, tasks, Suite(test=scenario_parallelization, name=alias, setup=instrument_clickhouse_server_log), {"table_type": table_type, "privilege": alias}) + run_scenario(pool, tasks, Suite(test=scenario_parallelization, name=alias, + setup=instrument_clickhouse_server_log), + {"table_type": table_type, "privilege": alias}) finally: join(tasks) finally: diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_settings_profile.py b/tests/testflows/rbac/tests/privileges/alter/alter_settings_profile.py index 9212b745544..cd4648305f7 100644 --- a/tests/testflows/rbac/tests/privileges/alter/alter_settings_profile.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_settings_profile.py @@ -31,7 +31,7 @@ def alter_settings_profile_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=alter_settings_profile, flags=TE, + Suite(run=alter_settings_profile, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in alter_settings_profile.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -52,13 +52,14 @@ def alter_settings_profile_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=alter_settings_profile, flags=TE, + Suite(run=alter_settings_profile, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in alter_settings_profile.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("ALTER SETTINGS PROFILE",), ("ALTER PROFILE",), @@ -76,7 +77,13 @@ def alter_settings_profile(self, privilege, grant_target_name, user_name, node=N with settings_profile(node, alter_settings_profile_name): - with When("I check the user can't alter a settings_profile"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't alter a settings_profile"): node.query(f"ALTER SETTINGS PROFILE {alter_settings_profile_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -128,6 +135,8 @@ def alter_settings_profile(self, privilege, grant_target_name, user_name, node=N @Name("alter settings profile") @Requirements( RQ_SRS_006_RBAC_Privileges_AlterSettingsProfile("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of ALTER SETTINGS PROFILE. diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_ttl.py b/tests/testflows/rbac/tests/privileges/alter/alter_ttl.py index 00240f19bb4..8fa7136076e 100755 --- a/tests/testflows/rbac/tests/privileges/alter/alter_ttl.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_ttl.py @@ -16,7 +16,7 @@ subprivileges = { aliases = { "TTL" : ["ALTER TTL", "ALTER MODIFY TTL", "MODIFY TTL"], - "MATERIALIZE TTL": ["ALTER MATERIALIZE TTL", "MATERIALIZE TTL"], + "MATERIALIZE TTL": ["ALTER MATERIALIZE TTL", "MATERIALIZE TTL", "ALL"], } permutation_count = (1 << len(subprivileges)) @@ -250,7 +250,9 @@ def user_with_privileges_on_cluster(self, table_type, node=None): @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AlterTTL("1.0"), - RQ_SRS_006_RBAC_Privileges_AlterTTL_TableEngines("1.0") + RQ_SRS_006_RBAC_Privileges_AlterTTL_TableEngines("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_update.py b/tests/testflows/rbac/tests/privileges/alter/alter_update.py index 3b3e3990497..d205740b901 100644 --- a/tests/testflows/rbac/tests/privileges/alter/alter_update.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_update.py @@ -7,7 +7,7 @@ from rbac.requirements import * from rbac.helper.common import * import rbac.helper.errors as errors -aliases = {"ALTER UPDATE", "UPDATE"} +aliases = {"ALTER UPDATE", "UPDATE", "ALL"} @TestSuite def privilege_granted_directly_or_via_role(self, table_type, privilege, node=None): @@ -38,26 +38,41 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No with Scenario("user without privilege", setup=instrument_clickhouse_server_log): table_name = f"merge_tree_{getuid()}" + with table(node, table_name, table_type): - with When("I attempt to update a column without privilege"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to update a column without privilege"): node.query(f"ALTER TABLE {table_name} UPDATE a = x WHERE 1", settings = [("user", user_name)], exitcode=exitcode, message=message) with Scenario("user with privilege", setup=instrument_clickhouse_server_log): table_name = f"merge_tree_{getuid()}" + with table(node, table_name, table_type): + with When("I grant the update privilege"): node.query(f"GRANT {privilege} ON {table_name} TO {grant_target_name}") + with Then("I attempt to update a column"): node.query(f"ALTER TABLE {table_name} UPDATE a = x WHERE 1", settings = [("user", user_name)]) with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): table_name = f"merge_tree_{getuid()}" + with table(node, table_name, table_type): + with When("I grant the update privilege"): node.query(f"GRANT {privilege} ON {table_name} TO {grant_target_name}") + with And("I revoke the update privilege"): node.query(f"REVOKE {privilege} ON {table_name} FROM {grant_target_name}") + with Then("I attempt to update a column"): node.query(f"ALTER TABLE {table_name} UPDATE a = x WHERE 1", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -65,7 +80,9 @@ def privilege_check(grant_target_name, user_name, table_type, privilege, node=No @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AlterUpdate("1.0"), - RQ_SRS_006_RBAC_Privileges_AlterUpdate_TableEngines("1.0") + RQ_SRS_006_RBAC_Privileges_AlterUpdate_TableEngines("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() diff --git a/tests/testflows/rbac/tests/privileges/alter/alter_user.py b/tests/testflows/rbac/tests/privileges/alter/alter_user.py index 2531f4a3451..bcf3014c9be 100644 --- a/tests/testflows/rbac/tests/privileges/alter/alter_user.py +++ b/tests/testflows/rbac/tests/privileges/alter/alter_user.py @@ -17,7 +17,7 @@ def alter_user_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=alter_user, flags=TE, + Suite(run=alter_user, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in alter_user.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def alter_user_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=alter_user, flags=TE, + Suite(run=alter_user, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in alter_user.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("ALTER USER",), ]) @@ -61,7 +62,13 @@ def alter_user(self, privilege, grant_target_name, user_name, node=None): alter_user_name = f"alter_user_{getuid()}" with user(node, alter_user_name): - with When("I check the user can't alter a user"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't alter a user"): node.query(f"ALTER USER {alter_user_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -108,6 +115,8 @@ def alter_user(self, privilege, grant_target_name, user_name, node=None): @Name("alter user") @Requirements( RQ_SRS_006_RBAC_Privileges_AlterUser("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of ALTER USER. diff --git a/tests/testflows/rbac/tests/privileges/attach/attach_database.py b/tests/testflows/rbac/tests/privileges/attach/attach_database.py index 0f1a9a07975..3fecbe2571f 100644 --- a/tests/testflows/rbac/tests/privileges/attach/attach_database.py +++ b/tests/testflows/rbac/tests/privileges/attach/attach_database.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute CREATE DATABASE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,11 +32,17 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): db_name = f"db_{getuid()}" try: - with When("I attempt to attach a database without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to attach a database without privilege"): node.query(f"ATTACH DATABASE {db_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -44,14 +50,14 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the database"): node.query(f"DROP DATABASE IF EXISTS {db_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): db_name = f"db_{getuid()}" try: with When("I grant create database privilege"): node.query(f"GRANT CREATE DATABASE ON {db_name}.* TO {grant_target_name}") - with Then("I attempt to attach aa database"): + with Then("I attempt to attach a database"): node.query(f"ATTACH DATABASE {db_name}", settings = [("user", user_name)], exitcode=80, message="DB::Exception: Received from localhost:9000. DB::Exception: Database engine must be specified for ATTACH DATABASE query") @@ -59,7 +65,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the database"): node.query(f"DROP DATABASE IF EXISTS {db_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): db_name = f"db_{getuid()}" try: @@ -77,9 +83,44 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the database"): node.query(f"DROP DATABASE IF EXISTS {db_name}") + with Scenario("user with revoked ALL privilege"): + db_name = f"db_{getuid()}" + + try: + with When("I grant the create database privilege"): + node.query(f"GRANT CREATE DATABASE ON {db_name}.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to attach a database"): + node.query(f"ATTACH DATABASE {db_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I drop the database"): + node.query(f"DROP DATABASE IF EXISTS {db_name}") + + with Scenario("user with ALL privilege"): + db_name = f"db_{getuid()}" + + try: + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to attach a database"): + node.query(f"ATTACH DATABASE {db_name}", settings = [("user", user_name)], + exitcode=80, message="DB::Exception: Received from localhost:9000. DB::Exception: Database engine must be specified for ATTACH DATABASE query") + + finally: + with Finally("I drop the database"): + node.query(f"DROP DATABASE IF EXISTS {db_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AttachDatabase("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("attach database") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -92,5 +133,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/attach/attach_dictionary.py b/tests/testflows/rbac/tests/privileges/attach/attach_dictionary.py index 62ff70ac75a..390a7f03aba 100644 --- a/tests/testflows/rbac/tests/privileges/attach/attach_dictionary.py +++ b/tests/testflows/rbac/tests/privileges/attach/attach_dictionary.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute CREATE DICTIONARY with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,11 +32,17 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): dict_name = f"dict_{getuid()}" try: - with When("I attempt to attach a dictionary without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to attach a dictionary without privilege"): node.query(f"ATTACH DICTIONARY {dict_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -44,7 +50,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the dictionary"): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): dict_name = f"dict_{getuid()}" try: @@ -59,7 +65,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the dictionary"): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): dict_name = f"dict_{getuid()}" try: @@ -77,9 +83,44 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the dictionary"): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + with Scenario("user with revoked ALL privilege"): + db_name = f"db_{getuid()}" + + try: + with When("I grant the create database privilege"): + node.query(f"GRANT CREATE DATABASE ON {db_name}.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to attach a database"): + node.query(f"ATTACH DATABASE {db_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I drop the database"): + node.query(f"DROP DATABASE IF EXISTS {db_name}") + + with Scenario("user with ALL privilege"): + dict_name = f"dict_{getuid()}" + + try: + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to attach a dictionary"): + node.query(f"ATTACH DICTIONARY {dict_name}", settings = [("user", user_name)], + exitcode=231, message=f"DB::Exception: Dictionary `{dict_name}` doesn't exist.") + + finally: + with Finally("I drop the dictionary"): + node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AttachDictionary("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("attach dictionary") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -92,5 +133,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/attach/attach_table.py b/tests/testflows/rbac/tests/privileges/attach/attach_table.py index 55c9efd369c..411140506ea 100644 --- a/tests/testflows/rbac/tests/privileges/attach/attach_table.py +++ b/tests/testflows/rbac/tests/privileges/attach/attach_table.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute CREATE TABLE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,12 +32,17 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): table_name = f"table_{getuid()}" try: + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") - with When("I attempt to attach a table without privilege"): + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to attach a table without privilege"): node.query(f"ATTACH TABLE {table_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -45,7 +50,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the table"): node.query(f"DROP TABLE IF EXISTS {table_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): table_name = f"table_{getuid()}" try: @@ -60,7 +65,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the table"): node.query(f"DROP TABLE IF EXISTS {table_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): table_name = f"table_{getuid()}" try: @@ -78,9 +83,44 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the table"): node.query(f"DROP TABLE IF EXISTS {table_name}") + with Scenario("user with revoked ALL privilege"): + table_name = f"table_{getuid()}" + + try: + with When("I grant the create table privilege"): + node.query(f"GRANT CREATE TABLE ON *.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to attach a table"): + node.query(f"ATTACH TABLE {table_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I drop the table"): + node.query(f"DROP TABLE IF EXISTS {table_name}") + + with Scenario("user with ALL privilege"): + table_name = f"table_{getuid()}" + + try: + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to attach a table"): + node.query(f"ATTACH TABLE {table_name}", settings = [("user", user_name)], + exitcode=134, message=f"DB::Exception: Table `{table_name}` doesn't exist.") + + finally: + with Finally("I drop the table"): + node.query(f"DROP TABLE IF EXISTS {table_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AttachTable("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("attach table") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -93,5 +133,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/attach/attach_temp_table.py b/tests/testflows/rbac/tests/privileges/attach/attach_temp_table.py index fad47e71967..2662a24d5a2 100644 --- a/tests/testflows/rbac/tests/privileges/attach/attach_temp_table.py +++ b/tests/testflows/rbac/tests/privileges/attach/attach_temp_table.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute CREATE TEMPORARY TABLE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,10 +32,16 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): temp_table_name = f"temp_table_{getuid()}" try: + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + with When("I attempt to attach a temporary table without privilege"): node.query(f"ATTACH TEMPORARY TABLE {temp_table_name} (x Int8)", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -44,12 +50,13 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the temporary table"): node.query(f"DROP TEMPORARY TABLE IF EXISTS {temp_table_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): temp_table_name = f"temp_table_{getuid()}" try: with When("I grant create temporary table privilege"): node.query(f"GRANT CREATE TEMPORARY TABLE ON *.* TO {grant_target_name}") + with Then("I attempt to attach a temporary table"): node.query(f"ATTACH TEMPORARY TABLE {temp_table_name} (x Int8)", settings = [("user", user_name)]) @@ -57,7 +64,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the temporary table"): node.query(f"DROP TEMPORARY TABLE IF EXISTS {temp_table_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): temp_table_name = f"temp_table_{getuid()}" try: @@ -75,9 +82,43 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the temporary table"): node.query(f"DROP TEMPORARY TABLE IF EXISTS {temp_table_name}") + with Scenario("user with revoked ALL privilege"): + temp_table_name = f"temp_table_{getuid()}" + + try: + with When("I grant the create temporary table privilege"): + node.query(f"GRANT CREATE TEMPORARY TABLE ON *.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to attach a temporary table"): + node.query(f"ATTACH TEMPORARY TABLE {temp_table_name} (x Int8)", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I drop the temporary table"): + node.query(f"DROP TEMPORARY TABLE IF EXISTS {temp_table_name}") + + with Scenario("user with ALL privilege"): + temp_table_name = f"temp_table_{getuid()}" + + try: + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to attach a temporary table"): + node.query(f"ATTACH TEMPORARY TABLE {temp_table_name} (x Int8)", settings = [("user", user_name)]) + + finally: + with Finally("I drop the temporary table"): + node.query(f"DROP TEMPORARY TABLE IF EXISTS {temp_table_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_AttachTemporaryTable("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("attach temporary table") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -90,5 +131,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/create/create_database.py b/tests/testflows/rbac/tests/privileges/create/create_database.py index deefe4b4ce8..8367d49e050 100644 --- a/tests/testflows/rbac/tests/privileges/create/create_database.py +++ b/tests/testflows/rbac/tests/privileges/create/create_database.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute CREATE DATABASE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,11 +32,17 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): db_name = f"db_{getuid()}" try: - with When("I attempt to create a database without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to create a database without privilege"): node.query(f"CREATE DATABASE {db_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -44,7 +50,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the database"): node.query(f"DROP DATABASE IF EXISTS {db_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): db_name = f"db_{getuid()}" try: @@ -58,7 +64,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the database"): node.query(f"DROP DATABASE IF EXISTS {db_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): db_name = f"db_{getuid()}" try: @@ -76,9 +82,43 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the database"): node.query(f"DROP DATABASE IF EXISTS {db_name}") + with Scenario("user with revoked ALL privilege"): + db_name = f"db_{getuid()}" + + try: + with When("I grant the create database privilege"): + node.query(f"GRANT CREATE DATABASE ON {db_name}.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to create a database"): + node.query(f"CREATE DATABASE {db_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I drop the database"): + node.query(f"DROP DATABASE IF EXISTS {db_name}") + + with Scenario("user with ALL privilege"): + db_name = f"db_{getuid()}" + + try: + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to create a database"): + node.query(f"CREATE DATABASE {db_name}", settings = [("user", user_name)]) + + finally: + with Finally("I drop the database"): + node.query(f"DROP DATABASE IF EXISTS {db_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_CreateDatabase("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("create database") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -91,5 +131,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/create/create_dictionary.py b/tests/testflows/rbac/tests/privileges/create/create_dictionary.py index 0dbc3e1f6bb..73734f5d556 100644 --- a/tests/testflows/rbac/tests/privileges/create/create_dictionary.py +++ b/tests/testflows/rbac/tests/privileges/create/create_dictionary.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute CREATE DICTIONARY with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,11 +32,17 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): dict_name = f"dict_{getuid()}" try: - with When("I attempt to create a dictionary without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to create a dictionary without privilege"): node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -44,7 +50,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the dictionary"): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): dict_name = f"dict_{getuid()}" try: @@ -58,7 +64,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the dictionary"): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): dict_name = f"dict_{getuid()}" try: @@ -76,9 +82,44 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the dictionary"): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + + with Scenario("user with revoked ALL privilege"): + dict_name = f"dict_{getuid()}" + + try: + with When("I grant the create dictionary privilege"): + node.query(f"GRANT CREATE DICTIONARY ON {dict_name} TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to create a dictionary"): + node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I drop the dictionary"): + node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + + with Scenario("user with ALL privilege"): + dict_name = f"dict_{getuid()}" + + try: + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to create a dictionary"): + node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)", settings = [("user", user_name)]) + + finally: + with Finally("I drop the dictionary"): + node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_CreateDictionary("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("create dictionary") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -91,5 +132,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/create/create_quota.py b/tests/testflows/rbac/tests/privileges/create/create_quota.py index e7f4f4d5f7c..d6e50ea904e 100644 --- a/tests/testflows/rbac/tests/privileges/create/create_quota.py +++ b/tests/testflows/rbac/tests/privileges/create/create_quota.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=create_quota, flags=TE, + Suite(run=create_quota, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in create_quota.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=create_quota, flags=TE, + Suite(run=create_quota, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in create_quota.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("CREATE QUOTA",), ]) @@ -60,7 +61,13 @@ def create_quota(self, privilege, grant_target_name, user_name, node=None): create_quota_name = f"create_quota_{getuid()}" try: - with When("I check the user can't create a quota"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't create a quota"): node.query(f"CREATE QUOTA {create_quota_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -118,6 +125,8 @@ def create_quota(self, privilege, grant_target_name, user_name, node=None): @Name("create quota") @Requirements( RQ_SRS_006_RBAC_Privileges_CreateQuota("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of CREATE QUOTA. diff --git a/tests/testflows/rbac/tests/privileges/create/create_role.py b/tests/testflows/rbac/tests/privileges/create/create_role.py index 9d8af913893..c442036b625 100644 --- a/tests/testflows/rbac/tests/privileges/create/create_role.py +++ b/tests/testflows/rbac/tests/privileges/create/create_role.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=create_role, flags=TE, + Suite(run=create_role, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in create_role.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=create_role, flags=TE, + Suite(run=create_role, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in create_role.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("CREATE ROLE",), ]) @@ -60,7 +61,13 @@ def create_role(self, privilege, grant_target_name, user_name, node=None): create_role_name = f"create_role_{getuid()}" try: - with When("I check the user can't create a role"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't create a role"): node.query(f"CREATE ROLE {create_role_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -118,6 +125,8 @@ def create_role(self, privilege, grant_target_name, user_name, node=None): @Name("create role") @Requirements( RQ_SRS_006_RBAC_Privileges_CreateRole("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of CREATE ROLE. diff --git a/tests/testflows/rbac/tests/privileges/create/create_row_policy.py b/tests/testflows/rbac/tests/privileges/create/create_row_policy.py index 040cc631cc3..8e670333492 100644 --- a/tests/testflows/rbac/tests/privileges/create/create_row_policy.py +++ b/tests/testflows/rbac/tests/privileges/create/create_row_policy.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=create_row_policy, flags=TE, + Suite(run=create_row_policy, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in create_row_policy.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=create_row_policy, flags=TE, + Suite(run=create_row_policy, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in create_row_policy.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("CREATE ROW POLICY",), ("CREATE POLICY",), @@ -62,7 +63,13 @@ def create_row_policy(self, privilege, grant_target_name, user_name, node=None): table_name = f"table_name_{getuid()}" try: - with When("I check the user can't create a row policy"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't create a row policy"): node.query(f"CREATE ROW POLICY {create_row_policy_name} ON {table_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -119,15 +126,962 @@ def create_row_policy(self, privilege, grant_target_name, user_name, node=None): with Finally("I drop the row policy"): node.query(f"DROP ROW POLICY IF EXISTS {create_row_policy_name} ON {table_name}") +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Restriction("1.0") +) +def no_grants(self, node=None): + """Check that user is unable to select from a table without a row policy + after a row policy with a condition has been created on that table. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name}") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + with When("I create a row policy with a condition"): + node.query(f"CREATE ROW POLICY OR REPLACE {pol_name} ON {table_name} FOR SELECT USING 1") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_Access_Permissive("1.0"), +) +def permissive(self, node=None): + """Check that user is able to see from a table when they have a PERMISSIVE policy. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1), (2)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_Access_Restrictive("1.0") +) +def restrictive(self, node=None): + """Check that user is able to see values they have a RESTRICTIVE policy for. + """ + + table_name = f"table_{getuid()}" + perm_pol_name = f"perm_pol_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a permissive row policy"): + node.query(f"CREATE ROW POLICY {perm_pol_name} ON {table_name} FOR SELECT USING y=1 OR y=2 TO default") + + with And("I have a restrictive row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS RESTRICTIVE FOR SELECT USING y=1 TO default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1), (2)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the restrictive row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + + with And("I drop the permissive row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {perm_pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_ForSelect("1.0"), +) +def for_select(self, node=None): + """Check that user is able to see values allowed by the row policy condition in the FOR SELECT clause. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a restrictive row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1 TO default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_Condition("1.0") +) +def condition(self, node=None): + """Check that user is able to see values allowed by the row policy condition. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a restrictive row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_IfNotExists("1.0") +) +def if_not_exists(self, node=None): + """Check that a row policy created using IF NOT EXISTS does not replace a row policy with the same name. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1 TO default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + with When("I create another row policy with the same name using IF NOT EXISTS"): + node.query(f"CREATE ROW POLICY IF NOT EXISTS {pol_name} ON {table_name}") + + with Then("I select from the table again"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_Replace("1.0") +) +def or_replace(self, node=None): + """Check that a row policy created using OR REPLACE does replace the row policy with the same name. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1 TO default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + with When("I create another row policy with the same name using OR REPLACE"): + node.query(f"CREATE ROW POLICY OR REPLACE {pol_name} ON {table_name} AS RESTRICTIVE FOR SELECT USING 1 TO default") + + with Then("I can no longer select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert output == '', error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_OnCluster("1.0") +) +def on_cluster(self, node=None): + """Check that a row policy created using ON CLUSTER applies to the nodes of the cluster correctly. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + node2 = self.context.node2 + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON CLUSTER sharded_cluster ON {table_name} FOR SELECT USING 1") + + with When("I insert some values into the table on the first node"): + node.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with And("I insert some values into the table on the second node"): + node2.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + + with And("I select from another node on the cluster"): + output = node2.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE {table_name} ON CLUSTER sharded_cluster") + +@TestScenario +def diff_policies_on_diff_nodes(self, node=None): + """Check that a row policy created on a node, does not effect a different node. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + node2 = self.context.node2 + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy on one node"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with When("I insert some values into the table on the first node"): + node.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with And("I insert some values into the table on the second node"): + node2.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + + with And("I select from another node on the cluster"): + output = node2.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE {table_name} ON CLUSTER sharded_cluster") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_Assignment("1.0"), +) +def assignment(self, node=None): + """Check that user is able to see rows from a table when they have PERMISSIVE policy assigned to them. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_None("1.0"), +) +def assignment_none(self, node=None): + """Check that no one is affected when a row policy is assigned to NONE. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO NONE") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_All("1.0"), +) +def assignment_all(self, node=None): + """Check that everyone is effected with a row policy is assigned to ALL. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO ALL") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_AllExcept("1.0"), +) +def assignment_all_except(self, node=None): + """Check that everyone is except the specified user is effect by a row policy assigned to ALL EXCEPT. + """ + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO ALL EXCEPT default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0"), +) +def nested_view(self, node=None): + """Check that if a user has a row policy on a table and a view is created on that table, + the user is only able to select rows specified by the assigned policies from the view. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with And("I create a view on the table"): + node.query(f"CREATE VIEW {view_name} AS SELECT * FROM {table_name}") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + + with And("I drop the view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0"), +) +def nested_live_view_after_policy(self, node=None): + """Check that if a user has a row policy on a table and a live view is created on that table, + the user is only able to select rows specified by the assigned policies from the view. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I add allow_experimental_live_view to the default query settings"): + default_query_settings = getsattr(current().context, "default_query_settings", []) + default_query_settings.append(("allow_experimental_live_view", 1)) + + with And("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO default") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with And("I create a live view on the table"): + node.query(f"CREATE LIVE VIEW {view_name} AS SELECT * FROM {table_name}") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + + with And("I drop the live view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + + with And("I remove allow_experimental_live_view from the default query settings", flags=TE): + if default_query_settings: + try: + default_query_settings.pop(default_query_settings.index(("allow_experimental_live_view", 1))) + except ValueError: + pass + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0"), +) +def nested_live_view_before_policy(self, node=None): + """Check that if a live view exists on a table and then a row policy is created, + the user is only able to select rows specified by the assigned policies from the view. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I add allow_experimental_live_view to the default query settings"): + default_query_settings = getsattr(current().context, "default_query_settings", []) + default_query_settings.append(("allow_experimental_live_view", 1)) + + with And("There is a live view on the table"): + node.query(f"CREATE LIVE VIEW {view_name} AS SELECT * FROM {table_name}") + + with And("There is a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO default") + + with When("I insert values into the table"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + + with And("I drop the live view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + + with And("I remove allow_experimental_live_view from the default query settings", flags=TE): + if default_query_settings: + try: + default_query_settings.pop(default_query_settings.index(("allow_experimental_live_view", 1))) + except ValueError: + pass + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0"), +) +def nested_mat_view_after_policy(self, node=None): + """Check that if a user has a row policy on a table and a materialized view is created on that table, + the user is only able to select rows specified by the assigned policies from the view. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO default") + + with When("I create a view on the table"): + node.query(f"CREATE MATERIALIZED VIEW {view_name} ENGINE = Memory AS SELECT * FROM {table_name}") + + with And("I insert some values on the table"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + + with And("I drop the materialized view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0"), +) +def nested_mat_view_before_policy(self, node=None): + """Check that if a materialized view exists on a table and then a row policy is created, + the user is only able to select rows specified by the assigned policies from the view. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a view on the table"): + node.query(f"CREATE MATERIALIZED VIEW {view_name} ENGINE = Memory AS SELECT * FROM {table_name}") + + with And("I have some values on the table"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with When("I create a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO default") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + + with And("I drop the materialized view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + +@TestScenario +def populate_mat_view(self, node=None): + """Check that if a user has a row policy on a table and a materialized view is created using POPULATE from that table, + the user can only select the rows from the materialized view specified in the row policy. + """ + + table_name = f"table_{getuid()}" + view_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name): + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO default") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with When("I create a mat view with POPULATE from the table"): + node.query(f"CREATE MATERIALIZED VIEW {view_name} ENGINE = Memory POPULATE AS SELECT * FROM {table_name}") + + with Then("I try to select from the view"): + output = node.query(f"SELECT * FROM {view_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + + with And("I drop the materialized view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def dist_table(self, node=None): + """Check that if a user has a row policy on a table and a distributed table is created on that table, + the user is only able to select rows specified by the assigned policies from the distributed table. + """ + + table_name = f"table_{getuid()}" + dist_table_name = f"dist_table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + node2 = self.context.node2 + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON CLUSTER sharded_cluster ON {table_name} FOR SELECT USING 1") + + with And("I have a distributed table"): + node.query(f"CREATE TABLE {dist_table_name} (x UInt64) ENGINE = Distributed(sharded_cluster, default, {table_name}, rand())") + + with When("I insert some values into the table on the first node"): + node.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {dist_table_name}").output + assert '' == output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {table_name} ON CLUSTER sharded_cluster") + + with And("I drop the distributed table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {dist_table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def dist_table_diff_policies_on_diff_nodes(self, node=None): + """Check that the user can only access the rows of the distributed table that are allowed + by row policies on the the source tables. The row policies are different on different nodes. + """ + + table_name = f"table_{getuid()}" + dist_table_name = f"dist_table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + node2 = self.context.node2 + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with And("I have a distributed table"): + node.query(f"CREATE TABLE {dist_table_name} (x UInt64) ENGINE = Distributed(sharded_cluster, default, {table_name}, rand())") + + with When("I insert some values into the table on the first node"): + node.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with And("I insert some values into the table on the second node"): + node2.query(f"INSERT INTO {table_name} (x) VALUES (2)") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {dist_table_name}").output + assert '2' in output and '1' not in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {table_name} ON CLUSTER sharded_cluster") + + with And("I drop the distributed table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {dist_table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0") +) +def dist_table_on_dist_table(self, node=None): + """Check that if a user has a row policy on a table and a distributed table is created on that table, + and another distributed table is created on top of that, + the user is only able to access rows on any of the tables specified by the assigned policies. + """ + table_name = f"table_{getuid()}" + dist_table_name = f"dist_table_{getuid()}" + dist_table_2_name = f"dist_table_2_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + node2 = self.context.node2 + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON CLUSTER sharded_cluster ON {table_name} FOR SELECT USING 1") + + with And("I have a distributed table on a cluster"): + node.query(f"CREATE TABLE {dist_table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Distributed(sharded_cluster, default, {table_name}, rand())") + + with And("I have a distributed table on the other distributed table"): + node.query(f"CREATE TABLE {dist_table_2_name} (x UInt64) ENGINE = Distributed(sharded_cluster, default, {dist_table_name}, rand())") + + with When("I insert some values into the table on the first node"): + node.query(f"INSERT INTO {dist_table_2_name} (x) VALUES (1)") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {dist_table_2_name}").output + assert '' == output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {table_name} ON CLUSTER sharded_cluster") + + with And("I drop the distributed table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {dist_table_name} ON CLUSTER sharded_cluster") + + with And("I drop the outer distributed table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {dist_table_2_name}") + +@TestScenario +def no_table(self, node=None): + """Check that row policy is not created when the table is not specified. + """ + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + with When("I try to create a row policy without a table"): + node.query(f"CREATE ROW POLICY {pol_name}", + exitcode=62, message='Exception: Syntax error') + + with And("I try to create a row policy on a database"): + node.query(f"CREATE ROW POLICY {pol_name} ON default.*", + exitcode=62, message='Exception: Syntax error') + +@TestScenario +def policy_before_table(self, node=None): + """Check that if the policy is created before the table, + then it is still applied correctly. + """ + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING y=1 TO default") + + with table(node, table_name): + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1), (2)") + + with Then("I try to select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the row policy"): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Nesting("1.0"), +) +def dict(self, node=None): + """Check that if a user has a row policy on a table and a dictionary is created on that table, + the user is only able to select rows specified by the assigned policies from the dict. + """ + + table_name = f"table_{getuid()}" + dict_name = f"view_{getuid()}" + pol_name = f"pol_{getuid()}" + + if node is None: + node = self.context.node + + try: + with Given("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON {table_name} AS PERMISSIVE FOR SELECT USING key=1 TO default") + + with And("I have a table"): + node.query(f"CREATE TABLE {table_name} (key UInt64, val UInt64 DEFAULT 5) ENGINE = Memory") + + with When("The table has some values"): + node.query(f"INSERT INTO {table_name} (key) VALUES (1),(2)") + + with And("I create a dict on the table"): + node.query(f"CREATE DICTIONARY {dict_name} (key UInt64 DEFAULT 0, val UInt64 DEFAULT 5) PRIMARY KEY key SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE {table_name} PASSWORD '' DB 'default')) LIFETIME(MIN 0 MAX 0) LAYOUT(FLAT())") + + with Then("I try to select from the dict"): + output = node.query(f"SELECT * FROM {dict_name}").output + assert '1' in output and '2' not in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON {table_name}") + + with And("I drop the materialized view", flags=TE): + node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {table_name}") + @TestFeature @Name("create row policy") @Requirements( RQ_SRS_006_RBAC_Privileges_CreateRowPolicy("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of CREATE ROW POLICY. """ self.context.node = self.context.cluster.node(node) + self.context.node2 = self.context.cluster.node("clickhouse2") Suite(run=privileges_granted_directly, setup=instrument_clickhouse_server_log) Suite(run=privileges_granted_via_role, setup=instrument_clickhouse_server_log) + + Scenario(run=no_grants, setup=instrument_clickhouse_server_log) + Scenario(run=permissive, setup=instrument_clickhouse_server_log) + Scenario(run=restrictive, setup=instrument_clickhouse_server_log) + Scenario(run=for_select, setup=instrument_clickhouse_server_log) + Scenario(run=condition, setup=instrument_clickhouse_server_log) + Scenario(run=if_not_exists, setup=instrument_clickhouse_server_log) + Scenario(run=or_replace, setup=instrument_clickhouse_server_log) + Scenario(run=on_cluster, setup=instrument_clickhouse_server_log) + Scenario(run=assignment, setup=instrument_clickhouse_server_log) + Scenario(run=assignment_none, setup=instrument_clickhouse_server_log) + Scenario(run=assignment_all, setup=instrument_clickhouse_server_log) + Scenario(run=assignment_all_except, setup=instrument_clickhouse_server_log) + Scenario(run=nested_view, setup=instrument_clickhouse_server_log) + Scenario(run=nested_live_view_before_policy, setup=instrument_clickhouse_server_log) + Scenario(run=nested_live_view_after_policy, setup=instrument_clickhouse_server_log) + Scenario(run=nested_mat_view_before_policy, setup=instrument_clickhouse_server_log) + Scenario(run=nested_mat_view_after_policy, setup=instrument_clickhouse_server_log) + Scenario(run=populate_mat_view, setup=instrument_clickhouse_server_log) + Scenario(run=dist_table, setup=instrument_clickhouse_server_log) + Scenario(run=dist_table_on_dist_table, setup=instrument_clickhouse_server_log) + Scenario(run=dist_table_diff_policies_on_diff_nodes, setup=instrument_clickhouse_server_log) + Scenario(run=diff_policies_on_diff_nodes, setup=instrument_clickhouse_server_log) + Scenario(run=no_table, setup=instrument_clickhouse_server_log) + Scenario(run=policy_before_table, setup=instrument_clickhouse_server_log) + Scenario(run=dict, setup=instrument_clickhouse_server_log) diff --git a/tests/testflows/rbac/tests/privileges/create/create_settings_profile.py b/tests/testflows/rbac/tests/privileges/create/create_settings_profile.py index 8b206564647..938de560391 100644 --- a/tests/testflows/rbac/tests/privileges/create/create_settings_profile.py +++ b/tests/testflows/rbac/tests/privileges/create/create_settings_profile.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=create_settings_profile, flags=TE, + Suite(run=create_settings_profile, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in create_settings_profile.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=create_settings_profile, flags=TE, + Suite(run=create_settings_profile, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in create_settings_profile.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("CREATE SETTINGS PROFILE",), ("CREATE PROFILE",), @@ -61,7 +62,13 @@ def create_settings_profile(self, privilege, grant_target_name, user_name, node= create_settings_profile_name = f"create_settings_profile_{getuid()}" try: - with When("I check the user can't create a settings_profile"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't create a settings_profile"): node.query(f"CREATE SETTINGS PROFILE {create_settings_profile_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -119,6 +126,8 @@ def create_settings_profile(self, privilege, grant_target_name, user_name, node= @Name("create settings profile") @Requirements( RQ_SRS_006_RBAC_Privileges_CreateSettingsProfile("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of CREATE SETTINGS PROFILE. diff --git a/tests/testflows/rbac/tests/privileges/create/create_table.py b/tests/testflows/rbac/tests/privileges/create/create_table.py index 919e683f0f1..88d055f2915 100644 --- a/tests/testflows/rbac/tests/privileges/create/create_table.py +++ b/tests/testflows/rbac/tests/privileges/create/create_table.py @@ -6,6 +6,9 @@ from rbac.helper.common import * import rbac.helper.errors as errors @TestScenario +@Requirements( + RQ_SRS_006_RBAC_Privileges_None("1.0") +) def create_without_create_table_privilege(self, node=None): """Check that user is unable to create a table without CREATE TABLE privilege. """ @@ -21,7 +24,13 @@ def create_without_create_table_privilege(self, node=None): with Given("I don't have a table"): node.query(f"DROP TABLE IF EXISTS {table_name}") - with When("I try to create a table without CREATE TABLE privilege as the user"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {user_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {user_name}") + + with Then("I try to create a table without CREATE TABLE privilege as the user"): node.query(f"CREATE TABLE {table_name} (x Int8) ENGINE = Memory", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) @@ -74,6 +83,54 @@ def create_with_create_table_privilege(self, grant_target_name, user_name, node= with Then("I drop the table"): node.query(f"DROP TABLE IF EXISTS {table_name}") +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_Privileges_All("1.0") +) +def create_with_all_privilege_granted_directly_or_via_role(self, node=None): + """Check that user is able to create a table with ALL privilege, either granted directly or through a role. + """ + user_name = f"user_{getuid()}" + role_name = f"role_{getuid()}" + + if node is None: + node = self.context.node + + with user(node, f"{user_name}"): + + Scenario(test=create_with_all_privilege, + name="create with ALL privilege granted directly")(grant_target_name=user_name, user_name=user_name) + + with user(node, f"{user_name}"), role(node, f"{role_name}"): + + with When("I grant the role to the user"): + node.query(f"GRANT {role_name} TO {user_name}") + + Scenario(test=create_with_all_privilege, + name="create with ALL privilege granted through a role")(grant_target_name=role_name, user_name=user_name) + +@TestOutline +def create_with_all_privilege(self, grant_target_name, user_name, node=None): + """Check that user is able to create a table with the granted privileges. + """ + table_name = f"table_{getuid()}" + + if node is None: + node = self.context.node + try: + with Given("I don't have a table"): + node.query(f"DROP TABLE IF EXISTS {table_name}") + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I try to create a table without privilege as the user"): + node.query(f"CREATE TABLE {table_name} (x Int8) ENGINE = Memory", settings = [("user", f"{user_name}")]) + + finally: + with Then("I drop the table"): + node.query(f"DROP TABLE IF EXISTS {table_name}") + @TestScenario def create_with_revoked_create_table_privilege_revoked_directly_or_from_role(self, node=None): """Check that user is unable to create table after the CREATE TABLE privilege is revoked, either directly or from a role. @@ -125,6 +182,57 @@ def create_with_revoked_create_table_privilege(self, grant_target_name, user_nam with Finally("I drop the table"): node.query(f"DROP TABLE IF EXISTS {table_name}") +@TestScenario +def create_with_all_privileges_revoked_directly_or_from_role(self, node=None): + """Check that user is unable to create table after ALL privileges are revoked, either directly or from a role. + """ + user_name = f"user_{getuid()}" + role_name = f"role_{getuid()}" + + if node is None: + node = self.context.node + + with user(node, f"{user_name}"): + + Scenario(test=create_with_revoked_all_privilege, + name="create with all privilege revoked directly")(grant_target_name=user_name, user_name=user_name) + + with user(node, f"{user_name}"), role(node, f"{role_name}"): + + with When("I grant the role to the user"): + node.query(f"GRANT {role_name} TO {user_name}") + + Scenario(test=create_with_revoked_all_privilege, + name="create with all privilege revoked from a role")(grant_target_name=role_name, user_name=user_name) + +@TestOutline +def create_with_revoked_all_privilege(self, grant_target_name, user_name, node=None): + """Revoke ALL privilege and check the user is unable to create a table. + """ + table_name = f"table_{getuid()}" + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") + + if node is None: + node = self.context.node + + try: + with Given("I don't have a table"): + node.query(f"DROP TABLE IF EXISTS {table_name}") + + with When("I grant CREATE TABLE privilege"): + node.query(f"GRANT CREATE TABLE ON {table_name} TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I try to create a table on the table as the user"): + node.query(f"CREATE TABLE {table_name} (x Int8) ENGINE = Memory", settings = [("user", f"{user_name}")], + exitcode=exitcode, message=message) + + finally: + with Finally("I drop the table"): + node.query(f"DROP TABLE IF EXISTS {table_name}") + @TestScenario def create_without_source_table_privilege(self, node=None): """Check that user is unable to create a table without select diff --git a/tests/testflows/rbac/tests/privileges/create/create_temp_table.py b/tests/testflows/rbac/tests/privileges/create/create_temp_table.py index 5dbbcc04732..ac38e0269cf 100644 --- a/tests/testflows/rbac/tests/privileges/create/create_temp_table.py +++ b/tests/testflows/rbac/tests/privileges/create/create_temp_table.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute CREATE TEMPORARY TABLE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,11 +32,17 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): temp_table_name = f"temp_table_{getuid()}" try: - with When("I attempt to create a temporary table without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to create a temporary table without privilege"): node.query(f"CREATE TEMPORARY TABLE {temp_table_name} (x Int8)", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -44,7 +50,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the temporary table"): node.query(f"DROP TEMPORARY TABLE IF EXISTS {temp_table_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): temp_table_name = f"temp_table_{getuid()}" try: @@ -58,7 +64,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the temporary table"): node.query(f"DROP TEMPORARY TABLE IF EXISTS {temp_table_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): temp_table_name = f"temp_table_{getuid()}" try: @@ -76,9 +82,43 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the temporary table"): node.query(f"DROP TEMPORARY TABLE IF EXISTS {temp_table_name}") + with Scenario("user with revoked ALL privilege"): + temp_table_name = f"temp_table_{getuid()}" + + try: + with When("I grant the create temporary table privilege"): + node.query(f"GRANT CREATE TEMPORARY TABLE ON *.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to create a temporary table"): + node.query(f"CREATE TEMPORARY TABLE {temp_table_name} (x Int8)", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I drop the temporary table"): + node.query(f"DROP TEMPORARY TABLE IF EXISTS {temp_table_name}") + + with Scenario("user with ALL privilege"): + temp_table_name = f"temp_table_{getuid()}" + + try: + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to create aa temporary table"): + node.query(f"CREATE TEMPORARY TABLE {temp_table_name} (x Int8)", settings = [("user", user_name)]) + + finally: + with Finally("I drop the temporary table"): + node.query(f"DROP TEMPORARY TABLE IF EXISTS {temp_table_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_CreateTemporaryTable("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("create temporary table") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -91,5 +131,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/create/create_user.py b/tests/testflows/rbac/tests/privileges/create/create_user.py index 02fe238b618..b055deecea2 100644 --- a/tests/testflows/rbac/tests/privileges/create/create_user.py +++ b/tests/testflows/rbac/tests/privileges/create/create_user.py @@ -17,7 +17,7 @@ def create_user_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=create_user, flags=TE, + Suite(run=create_user, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in create_user.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def create_user_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=create_user, flags=TE, + Suite(run=create_user, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in create_user.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("CREATE USER",), ]) @@ -60,7 +61,13 @@ def create_user(self, privilege, grant_target_name, user_name, node=None): create_user_name = f"create_user_{getuid()}" try: - with When("I check the user can't create a user"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't create a user"): node.query(f"CREATE USER {create_user_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -127,7 +134,7 @@ def default_role_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(test=default_role, flags=TE)(grant_target_name=user_name, user_name=user_name) + Suite(test=default_role)(grant_target_name=user_name, user_name=user_name) @TestSuite def default_role_granted_via_role(self, node=None): @@ -145,7 +152,7 @@ def default_role_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(test=default_role, flags=TE)(grant_target_name=role_name, user_name=user_name) + Suite(test=default_role)(grant_target_name=role_name, user_name=user_name) @TestSuite @Requirements( @@ -215,7 +222,7 @@ def default_role(self, grant_target_name, user_name, node=None): settings = [("user", f"{user_name}")]) finally: - with Finally("I drop the user", flags=TE): + with Finally("I drop the user"): node.query(f"DROP USER IF EXISTS {create_user_name} ON CLUSTER sharded_cluster") with And("I drop the role from the cluster"): @@ -264,6 +271,8 @@ def default_role(self, grant_target_name, user_name, node=None): @Name("create user") @Requirements( RQ_SRS_006_RBAC_Privileges_CreateUser("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of CREATE USER. diff --git a/tests/testflows/rbac/tests/privileges/detach/detach_database.py b/tests/testflows/rbac/tests/privileges/detach/detach_database.py index 8f4576c3399..12eeb39aa1b 100644 --- a/tests/testflows/rbac/tests/privileges/detach/detach_database.py +++ b/tests/testflows/rbac/tests/privileges/detach/detach_database.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute DETACH DATABASE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -39,7 +39,13 @@ def privilege_check(grant_target_name, user_name, node=None): with Given("I have a database"): node.query(f"CREATE DATABASE {db_name}") - with When("I attempt to detach the database"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to detach the database"): node.query(f"DETACH DATABASE {db_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) finally: @@ -48,7 +54,7 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the database", flags=TE): node.query(f"DROP DATABASE IF EXISTS {db_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): db_name = f"db_{getuid()}" try: @@ -67,7 +73,7 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the database", flags=TE): node.query(f"DROP DATABASE IF EXISTS {db_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): db_name = f"db_{getuid()}" try: @@ -90,9 +96,53 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the database", flags=TE): node.query(f"DROP DATABASE IF EXISTS {db_name}") + with Scenario("user with revoked ALL privilege"): + db_name = f"db_{getuid()}" + + try: + with Given("I have a database"): + node.query(f"CREATE DATABASE {db_name}") + + with When("I grant the drop database privilege"): + node.query(f"GRANT DROP DATABASE ON {db_name}.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to detach a database"): + node.query(f"DETACH DATABASE {db_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I reattach the database", flags=TE): + node.query(f"ATTACH DATABASE IF NOT EXISTS {db_name}") + with And("I drop the database", flags=TE): + node.query(f"DROP DATABASE IF EXISTS {db_name}") + + with Scenario("user with ALL privilege"): + db_name = f"db_{getuid()}" + + try: + with Given("I have a database"): + node.query(f"CREATE DATABASE {db_name}") + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to detach a database"): + node.query(f"DETACH DATABASE {db_name}", settings = [("user", user_name)]) + + finally: + with Finally("I reattach the database", flags=TE): + node.query(f"ATTACH DATABASE IF NOT EXISTS {db_name}") + with And("I drop the database", flags=TE): + node.query(f"DROP DATABASE IF EXISTS {db_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_DetachDatabase("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("detach database") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -105,5 +155,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/detach/detach_dictionary.py b/tests/testflows/rbac/tests/privileges/detach/detach_dictionary.py index 5ae992e3623..17b37ce6dc0 100644 --- a/tests/testflows/rbac/tests/privileges/detach/detach_dictionary.py +++ b/tests/testflows/rbac/tests/privileges/detach/detach_dictionary.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute DETACH DICTIONARY with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,14 +32,20 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): dict_name = f"dict_{getuid()}" try: with Given("I have a dictionary"): node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)") - with When("I attempt to detach a dictionary without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to detach a dictionary without privilege"): node.query(f"DETACH DICTIONARY {dict_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) finally: @@ -48,7 +54,7 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the dictionary", flags=TE): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): dict_name = f"dict_{getuid()}" try: @@ -67,7 +73,7 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the dictionary", flags=TE): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): dict_name = f"dict_{getuid()}" try: @@ -89,9 +95,52 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the dictionary", flags=TE): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + with Scenario("user with revoked ALL privilege"): + dict_name = f"dict_{getuid()}" + + try: + with Given("I have a dictionary"): + node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)") + + with When("I grant the drop dictionary privilege"): + node.query(f"GRANT DROP DICTIONARY ON {dict_name} TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to detach a dictionary"): + node.query(f"DETACH DICTIONARY {dict_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) + + finally: + with Finally("I reattach the dictionary", flags=TE): + node.query(f"ATTACH DICTIONARY IF NOT EXISTS {dict_name}") + with And("I drop the dictionary", flags=TE): + node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + + with Scenario("user with ALL privilege"): + dict_name = f"dict_{getuid()}" + + try: + with Given("I have a dictionary"): + node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)") + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to detach a dictionary"): + node.query(f"DETACH DICTIONARY {dict_name}", settings = [("user", user_name)]) + + finally: + with Finally("I reattach the dictionary", flags=TE): + node.query(f"ATTACH DICTIONARY IF NOT EXISTS {dict_name}") + with And("I drop the dictionary", flags=TE): + node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_DetachDictionary("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("detach dictionary") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -104,5 +153,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/detach/detach_table.py b/tests/testflows/rbac/tests/privileges/detach/detach_table.py index 38a4a5dfde1..b5a01b361fc 100644 --- a/tests/testflows/rbac/tests/privileges/detach/detach_table.py +++ b/tests/testflows/rbac/tests/privileges/detach/detach_table.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute DETACH TABLE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,13 +32,19 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): table_name = f"table_{getuid()}" try: with Given("I have a table"): node.query(f"CREATE TABLE {table_name} (x Int8) ENGINE=Memory") + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + with When("I attempt to detach a table without privilege"): node.query(f"DETACH TABLE {table_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -49,7 +55,7 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the table", flags=TE): node.query(f"DROP TABLE IF EXISTS {table_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): table_name = f"table_{getuid()}" try: @@ -68,7 +74,7 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the table", flags=TE): node.query(f"DROP TABLE IF EXISTS {table_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): table_name = f"table_{getuid()}" try: @@ -91,9 +97,53 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the table", flags=TE): node.query(f"DROP TABLE IF EXISTS {table_name}") + with Scenario("user with revoked ALL privilege"): + table_name = f"table_{getuid()}" + + try: + with Given("I have a table"): + node.query(f"CREATE TABLE {table_name} (x Int8) ENGINE=Memory") + + with When("I grant the drop table privilege"): + node.query(f"GRANT DROP TABLE ON *.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to detach a table"): + node.query(f"DETACH TABLE {table_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I reattach the table", flags=TE): + node.query(f"ATTACH TABLE IF NOT EXISTS {table_name}") + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {table_name}") + + with Scenario("user with ALL privilege"): + table_name = f"table_{getuid()}" + + try: + with Given("I have a table"): + node.query(f"CREATE TABLE {table_name} (x Int8) ENGINE=Memory") + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to detach a table"): + node.query(f"DETACH TABLE {table_name}", settings = [("user", user_name)]) + + finally: + with Finally("I reattach the table", flags=TE): + node.query(f"ATTACH TABLE IF NOT EXISTS {table_name}") + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {table_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_DetachTable("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("detach table") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -106,5 +156,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/detach/detach_view.py b/tests/testflows/rbac/tests/privileges/detach/detach_view.py index e6e8adad065..c3c9f70a35a 100644 --- a/tests/testflows/rbac/tests/privileges/detach/detach_view.py +++ b/tests/testflows/rbac/tests/privileges/detach/detach_view.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute DETACH VIEW with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,13 +32,19 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): view_name = f"view_{getuid()}" try: with Given("I have a view"): node.query(f"CREATE VIEW {view_name} AS SELECT 1") + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + with When("I attempt to drop a view without privilege"): node.query(f"DETACH VIEW {view_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -49,7 +55,7 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the view", flags=TE): node.query(f"DROP VIEW IF EXISTS {view_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): view_name = f"view_{getuid()}" try: @@ -68,7 +74,7 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the table", flags=TE): node.query(f"DROP VIEW IF EXISTS {view_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): view_name = f"view_{getuid()}" try: @@ -91,9 +97,53 @@ def privilege_check(grant_target_name, user_name, node=None): with And("I drop the view", flags=TE): node.query(f"DROP VIEW IF EXISTS {view_name}") + with Scenario("user with revoked ALL privilege"): + view_name = f"view_{getuid()}" + + try: + with Given("I have a view"): + node.query(f"CREATE VIEW {view_name} AS SELECT 1") + + with When("I grant the drop view privilege"): + node.query(f"GRANT DROP VIEW ON {view_name} TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to drop a view"): + node.query(f"DETACH VIEW {view_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I reattach the view as a table", flags=TE): + node.query(f"ATTACH VIEW IF NOT EXISTS {view_name} AS SELECT 1") + with And("I drop the view", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + + with Scenario("user with ALL privilege"): + view_name = f"view_{getuid()}" + + try: + with Given("I have a view"): + node.query(f"CREATE VIEW {view_name} AS SELECT 1") + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to drop a view"): + node.query(f"DETACH VIEW {view_name}", settings = [("user", user_name)]) + + finally: + with Finally("I reattach the view as a table", flags=TE): + node.query(f"ATTACH VIEW IF NOT EXISTS {view_name} AS SELECT 1") + with And("I drop the table", flags=TE): + node.query(f"DROP VIEW IF EXISTS {view_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_DetachView("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("detach view") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -106,5 +156,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/dictGet.py b/tests/testflows/rbac/tests/privileges/dictGet.py index 532fa798eb2..21de4a36b77 100644 --- a/tests/testflows/rbac/tests/privileges/dictGet.py +++ b/tests/testflows/rbac/tests/privileges/dictGet.py @@ -39,8 +39,8 @@ def dictGet_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=dictGet_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name", [ + Suite(run=dictGet_check, + examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in dictGet_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -60,60 +60,67 @@ def dictGet_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=dictGet_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name", [ + Suite(run=dictGet_check, + examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in dictGet_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) -@Examples("privilege",[ - ("dictGet",), - ("dictHas",), - ("dictGetHierarchy",), - ("dictIsIn",), +@Examples("privilege on",[ + ("ALL", "*.*"), + ("dictGet", "dict"), + ("dictHas", "dict"), + ("dictGetHierarchy", "dict"), + ("dictIsIn", "dict"), ]) @Requirements( RQ_SRS_006_RBAC_dictGet_RequiredPrivilege("1.0") ) -def dictGet_check(self, privilege, grant_target_name, user_name, node=None): +def dictGet_check(self, privilege, on, grant_target_name, user_name, node=None): """Check that user is able to execute `dictGet` if and only if they have the necessary privileges. """ if node is None: node = self.context.node + dict_name = f"dict_{getuid()}" + table_name = f"table_{getuid()}" + + on = on.replace("dict", f"{dict_name}") + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user without privilege"): with dict_setup(node, table_name, dict_name): - with When("I attempt to dictGet without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to dictGet without privilege"): node.query(f"SELECT dictGet ({dict_name},'y',toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user with privilege"): with dict_setup(node, table_name, dict_name): with When(f"I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with Then("I attempt to dictGet with privilege"): node.query(f"SELECT dictGet ({dict_name},'y',toUInt64(1))", settings = [("user", user_name)]) - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" + with Scenario("user with revoked privilege"): with dict_setup(node, table_name, dict_name): with When("I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with And("I revoke privilege"): - node.query(f"REVOKE {privilege} ON {dict_name} FROM {grant_target_name}") + node.query(f"REVOKE {privilege} ON {on} FROM {grant_target_name}") with When("I attempt to dictGet without privilege"): node.query(f"SELECT dictGet ({dict_name},'y',toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -130,8 +137,8 @@ def dictGetOrDefault_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=dictGetOrDefault_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name", [ + Suite(run=dictGetOrDefault_check, + examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in dictGetOrDefault_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -151,60 +158,67 @@ def dictGetOrDefault_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=dictGetOrDefault_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name", [ + Suite(run=dictGetOrDefault_check, + examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in dictGetOrDefault_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) -@Examples("privilege",[ - ("dictGet",), - ("dictHas",), - ("dictGetHierarchy",), - ("dictIsIn",), +@Examples("privilege on",[ + ("ALL", "*.*"), + ("dictGet", "dict"), + ("dictHas", "dict"), + ("dictGetHierarchy", "dict"), + ("dictIsIn", "dict"), ]) @Requirements( RQ_SRS_006_RBAC_dictGet_OrDefault_RequiredPrivilege("1.0") ) -def dictGetOrDefault_check(self, privilege, grant_target_name, user_name, node=None): +def dictGetOrDefault_check(self, privilege, on, grant_target_name, user_name, node=None): """Check that user is able to execute `dictGetOrDefault` if and only if they have the necessary privileges. """ if node is None: node = self.context.node + dict_name = f"dict_{getuid()}" + table_name = f"table_{getuid()}" + + on = on.replace("dict", f"{dict_name}") + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user without privilege"): with dict_setup(node, table_name, dict_name): - with When("I attempt to dictGetOrDefault without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to dictGetOrDefault without privilege"): node.query(f"SELECT dictGetOrDefault ({dict_name},'y',toUInt64(1),toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user with privilege"): with dict_setup(node, table_name, dict_name): with When(f"I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with Then("I attempt to dictGetOrDefault with privilege"): node.query(f"SELECT dictGetOrDefault ({dict_name},'y',toUInt64(1),toUInt64(1))", settings = [("user", user_name)]) - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" + with Scenario("user with revoked privilege"): with dict_setup(node, table_name, dict_name): with When("I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with And("I revoke privilege"): - node.query(f"REVOKE {privilege} ON {dict_name} FROM {grant_target_name}") + node.query(f"REVOKE {privilege} ON {on} FROM {grant_target_name}") with When("I attempt to dictGetOrDefault without privilege"): node.query(f"SELECT dictGetOrDefault ({dict_name},'y',toUInt64(1),toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -221,8 +235,8 @@ def dictHas_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=dictHas_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name", [ + Suite(run=dictHas_check, + examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in dictHas_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -242,60 +256,67 @@ def dictHas_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=dictHas_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name", [ + Suite(run=dictHas_check, + examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in dictHas_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) -@Examples("privilege",[ - ("dictGet",), - ("dictHas",), - ("dictGetHierarchy",), - ("dictIsIn",), +@Examples("privilege on",[ + ("ALL", "*.*"), + ("dictGet", "dict"), + ("dictHas", "dict"), + ("dictGetHierarchy", "dict"), + ("dictIsIn", "dict"), ]) @Requirements( RQ_SRS_006_RBAC_dictHas_RequiredPrivilege("1.0") ) -def dictHas_check(self, privilege, grant_target_name, user_name, node=None): +def dictHas_check(self, privilege, on, grant_target_name, user_name, node=None): """Check that user is able to execute `dictHas` if and only if they have the necessary privileges. """ if node is None: node = self.context.node + dict_name = f"dict_{getuid()}" + table_name = f"table_{getuid()}" + + on = on.replace("dict", f"{dict_name}") + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user without privilege"): with dict_setup(node, table_name, dict_name): - with When("I attempt to dictHas without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to dictHas without privilege"): node.query(f"SELECT dictHas({dict_name},toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user with privilege"): with dict_setup(node, table_name, dict_name): with When("I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with Then("I attempt to dictHas with privilege"): node.query(f"SELECT dictHas({dict_name},toUInt64(1))", settings = [("user", user_name)]) - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" + with Scenario("user with revoked privilege"): with dict_setup(node, table_name, dict_name): with When("I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with And("I revoke privilege"): - node.query(f"REVOKE {privilege} ON {dict_name} FROM {grant_target_name}") + node.query(f"REVOKE {privilege} ON {on} FROM {grant_target_name}") with When("I attempt to dictHas without privilege"): node.query(f"SELECT dictHas({dict_name},toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -311,8 +332,8 @@ def dictGetHierarchy_granted_directly(self, node=None): node = self.context.node with user(node, f"{user_name}"): - Suite(run=dictGetHierarchy_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name", [ + Suite(run=dictGetHierarchy_check, + examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in dictGetHierarchy_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -332,60 +353,67 @@ def dictGetHierarchy_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=dictGetHierarchy_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name", [ + Suite(run=dictGetHierarchy_check, + examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in dictGetHierarchy_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) -@Examples("privilege",[ - ("dictGet",), - ("dictHas",), - ("dictGetHierarchy",), - ("dictIsIn",), +@Examples("privilege on",[ + ("ALL", "*.*"), + ("dictGet", "dict"), + ("dictHas", "dict"), + ("dictGetHierarchy", "dict"), + ("dictIsIn", "dict"), ]) @Requirements( RQ_SRS_006_RBAC_dictGetHierarchy_RequiredPrivilege("1.0") ) -def dictGetHierarchy_check(self, privilege, grant_target_name, user_name, node=None): +def dictGetHierarchy_check(self, privilege, on, grant_target_name, user_name, node=None): """Check that user is able to execute `dictGetHierarchy` if and only if they have the necessary privileges. """ if node is None: node = self.context.node + dict_name = f"dict_{getuid()}" + table_name = f"table_{getuid()}" + + on = on.replace("dict", f"{dict_name}") + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user without privilege"): with dict_setup(node, table_name, dict_name): - with When("I attempt to dictGetHierarchy without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to dictGetHierarchy without privilege"): node.query(f"SELECT dictGetHierarchy({dict_name},toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user with privilege"): with dict_setup(node, table_name, dict_name): with When("I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with Then("I attempt to dictGetHierarchy with privilege"): node.query(f"SELECT dictGetHierarchy({dict_name},toUInt64(1))", settings = [("user", user_name)]) - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" + with Scenario("user with revoked privilege"): with dict_setup(node, table_name, dict_name): with When("I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with And("I revoke privilege"): - node.query(f"REVOKE {privilege} ON {dict_name} FROM {grant_target_name}") + node.query(f"REVOKE {privilege} ON {on} FROM {grant_target_name}") with When("I attempt to dictGetHierarchy without privilege"): node.query(f"SELECT dictGetHierarchy({dict_name},toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -401,8 +429,8 @@ def dictIsIn_granted_directly(self, node=None): node = self.context.node with user(node, f"{user_name}"): - Suite(run=dictIsIn_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name", [ + Suite(run=dictIsIn_check, + examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in dictIsIn_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -422,60 +450,67 @@ def dictIsIn_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=dictIsIn_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name", [ + Suite(run=dictIsIn_check, + examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in dictIsIn_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) -@Examples("privilege",[ - ("dictGet",), - ("dictHas",), - ("dictGetHierarchy",), - ("dictIsIn",), +@Examples("privilege on",[ + ("ALL", "*.*"), + ("dictGet", "dict"), + ("dictHas", "dict"), + ("dictGetHierarchy", "dict"), + ("dictIsIn", "dict"), ]) @Requirements( RQ_SRS_006_RBAC_dictIsIn_RequiredPrivilege("1.0") ) -def dictIsIn_check(self, privilege, grant_target_name, user_name, node=None): +def dictIsIn_check(self, privilege, on, grant_target_name, user_name, node=None): """Check that user is able to execute `dictIsIn` if and only if they have the necessary privileges. """ if node is None: node = self.context.node + dict_name = f"dict_{getuid()}" + table_name = f"table_{getuid()}" + + on = on.replace("dict", f"{dict_name}") + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user without privilege"): with dict_setup(node, table_name, dict_name): - with When("I attempt to dictIsIn without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to dictIsIn without privilege"): node.query(f"SELECT dictIsIn({dict_name},toUInt64(1),toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user with privilege"): with dict_setup(node, table_name, dict_name): with When("I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with Then("I attempt to dictIsIn with privilege"): node.query(f"SELECT dictIsIn({dict_name},toUInt64(1),toUInt64(1))", settings = [("user", user_name)]) - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" + with Scenario("user with revoked privilege"): with dict_setup(node, table_name, dict_name): with When("I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with And("I revoke privilege"): - node.query(f"REVOKE {privilege} ON {dict_name} FROM {grant_target_name}") + node.query(f"REVOKE {privilege} ON {on} FROM {grant_target_name}") with When("I attempt to dictIsIn without privilege"): node.query(f"SELECT dictIsIn({dict_name},toUInt64(1),toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -507,8 +542,8 @@ def dictGetType_granted_directly(self, type, node=None): node = self.context.node with user(node, f"{user_name}"): - Suite(run=dictGetType_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name type", [ + Suite(run=dictGetType_check, + examples=Examples("privilege on grant_target_name user_name type", [ tuple(list(row)+[user_name,user_name,type]) for row in dictGetType_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -544,67 +579,76 @@ def dictGetType_granted_via_role(self, type, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=dictGetType_check, setup=instrument_clickhouse_server_log, - examples=Examples("privilege grant_target_name user_name type", [ + Suite(run=dictGetType_check, + examples=Examples("privilege on grant_target_name user_name type", [ tuple(list(row)+[role_name,user_name,type]) for row in dictGetType_check.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) -@Examples("privilege",[ - ("dictGet",), - ("dictHas",), - ("dictGetHierarchy",), - ("dictIsIn",), +@Examples("privilege on",[ + ("ALL", "*.*"), + ("dictGet", "dict"), + ("dictHas", "dict"), + ("dictGetHierarchy", "dict"), + ("dictIsIn", "dict"), ]) @Requirements( RQ_SRS_006_RBAC_dictGet_Type_RequiredPrivilege("1.0") ) -def dictGetType_check(self, privilege, grant_target_name, user_name, type, node=None): +def dictGetType_check(self, privilege, on, grant_target_name, user_name, type, node=None): """Check that user is able to execute `dictGet` if and only if they have the necessary privileges. """ if node is None: node = self.context.node + dict_name = f"dict_{getuid()}" + table_name = f"table_{getuid()}" + + on = on.replace("dict", f"{dict_name}") + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user without privilege"): with dict_setup(node, table_name, dict_name, type): - with When("I attempt to dictGet without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to dictGet without privilege"): node.query(f"SELECT dictGet{type}({dict_name},'z',toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" - table_name = f"table_{getuid()}" + with Scenario("user with privilege"): with dict_setup(node, table_name, dict_name, type): with When("I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with Then("I attempt to dictGet with privilege"): node.query(f"SELECT dictGet{type}({dict_name},'z',toUInt64(1))", settings = [("user", user_name)]) - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): - dict_name = f"dict_{getuid()}" + with Scenario("user with revoked privilege"): with dict_setup(node, table_name, dict_name, type): with When("I grant privilege"): - node.query(f"GRANT {privilege} ON {dict_name} TO {grant_target_name}") + node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") with And("I revoke privilege"): - node.query(f"REVOKE {privilege} ON {dict_name} FROM {grant_target_name}") + node.query(f"REVOKE {privilege} ON {on} FROM {grant_target_name}") with When("I attempt to dictGet without privilege"): node.query(f"SELECT dictGet{type}({dict_name},'z',toUInt64(1))", settings = [("user", user_name)], exitcode=exitcode, message=message) @TestFeature @Requirements( - RQ_SRS_006_RBAC_dictGet_Privilege("1.0") + RQ_SRS_006_RBAC_dictGet_Privilege("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("dictGet") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -622,23 +666,23 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): tasks = [] try: - run_scenario(pool, tasks, Suite(test=dictGet_granted_directly)) - run_scenario(pool, tasks, Suite(test=dictGet_granted_via_role)) - run_scenario(pool, tasks, Suite(test=dictGetOrDefault_granted_directly)) - run_scenario(pool, tasks, Suite(test=dictGetOrDefault_granted_via_role)) - run_scenario(pool, tasks, Suite(test=dictHas_granted_directly)) - run_scenario(pool, tasks, Suite(test=dictHas_granted_via_role)) - run_scenario(pool, tasks, Suite(test=dictGetHierarchy_granted_directly)) - run_scenario(pool, tasks, Suite(test=dictGetHierarchy_granted_via_role)) - run_scenario(pool, tasks, Suite(test=dictIsIn_granted_directly)) - run_scenario(pool, tasks, Suite(test=dictIsIn_granted_via_role)) + run_scenario(pool, tasks, Suite(test=dictGet_granted_directly, setup=instrument_clickhouse_server_log)) + run_scenario(pool, tasks, Suite(test=dictGet_granted_via_role, setup=instrument_clickhouse_server_log)) + run_scenario(pool, tasks, Suite(test=dictGetOrDefault_granted_directly, setup=instrument_clickhouse_server_log)) + run_scenario(pool, tasks, Suite(test=dictGetOrDefault_granted_via_role, setup=instrument_clickhouse_server_log)) + run_scenario(pool, tasks, Suite(test=dictHas_granted_directly, setup=instrument_clickhouse_server_log)) + run_scenario(pool, tasks, Suite(test=dictHas_granted_via_role, setup=instrument_clickhouse_server_log)) + run_scenario(pool, tasks, Suite(test=dictGetHierarchy_granted_directly, setup=instrument_clickhouse_server_log)) + run_scenario(pool, tasks, Suite(test=dictGetHierarchy_granted_via_role, setup=instrument_clickhouse_server_log)) + run_scenario(pool, tasks, Suite(test=dictIsIn_granted_directly, setup=instrument_clickhouse_server_log)) + run_scenario(pool, tasks, Suite(test=dictIsIn_granted_via_role, setup=instrument_clickhouse_server_log)) for example in dictGetType_granted_directly.examples: type, = example with Example(example): - run_scenario(pool, tasks, Suite(test=dictGetType_granted_directly),{"type" : type}) - run_scenario(pool, tasks, Suite(test=dictGetType_granted_via_role),{"type" : type}) + run_scenario(pool, tasks, Suite(test=dictGetType_granted_directly, setup=instrument_clickhouse_server_log),{"type" : type}) + run_scenario(pool, tasks, Suite(test=dictGetType_granted_via_role, setup=instrument_clickhouse_server_log),{"type" : type}) finally: join(tasks) diff --git a/tests/testflows/rbac/tests/privileges/distributed_table.py b/tests/testflows/rbac/tests/privileges/distributed_table.py index 5b62448a446..ba001ea7f2c 100755 --- a/tests/testflows/rbac/tests/privileges/distributed_table.py +++ b/tests/testflows/rbac/tests/privileges/distributed_table.py @@ -69,6 +69,7 @@ def create(self): create_scenarios=[ create_without_privilege, create_with_privilege_granted_directly_or_via_role, + create_with_all_privilege_granted_directly_or_via_role, ] for scenario in create_scenarios: @@ -79,18 +80,30 @@ def create_without_privilege(self, node=None): """Check that user is unable to create a distributed table without privileges. """ user_name = f"user_{getuid()}" + table0_name = f"table0_{getuid()}" table1_name = f"table1_{getuid()}" + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") + cluster = self.context.cluster_name + if node is None: node = self.context.node with Given("I have a user"): user(name=user_name) + with And("I have a table on a cluster"): table(name=table0_name, cluster=cluster) - with When("I attempt to create the distributed table without privilege"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {user_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {user_name}") + + with Then("I attempt to create the distributed table without privilege"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed(sharded_cluster, default, {table0_name}, rand())", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) @@ -101,20 +114,25 @@ def create_with_privilege_granted_directly_or_via_role(self, node=None): """ user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" + if node is None: node = self.context.node with Given("I have a user"): user(name=user_name) + Scenario(test=create_with_privilege, name="create with privilege granted directly")(grant_target_name=user_name, user_name=user_name) with Given("I have a user"): user(name=user_name) + with And("I have a role"): role(name=role_name) + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") + Scenario(test=create_with_privilege, name="create with privilege granted through a role")(grant_target_name=role_name, user_name=user_name) @@ -138,20 +156,24 @@ def create_with_privilege(self, user_name, grant_target_name, node=None): with When("I grant create table privilege"): node.query(f"GRANT CREATE ON {table1_name} TO {grant_target_name}") + with Then("I attempt to create the distributed table as the user"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I revoke the create table privilege"): node.query(f"REVOKE CREATE TABLE ON {table1_name} FROM {grant_target_name}") + with And("I grant remote privilege"): node.query(f"GRANT REMOTE ON *.* to {grant_target_name}") + with Then("I attempt to create the distributed table as the user"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant create table privilege"): node.query(f"GRANT CREATE ON {table1_name} TO {grant_target_name}") + with Then("I attempt to create the distributed table as the user"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())", settings = [("user", f"{user_name}")]) @@ -159,6 +181,62 @@ def create_with_privilege(self, user_name, grant_target_name, node=None): with Finally("I drop the distributed table"): node.query(f"DROP TABLE IF EXISTS {table1_name}") +@TestScenario +def create_with_all_privilege_granted_directly_or_via_role(self, node=None): + """Check that user is able to create a distributed table if and only if + they have ALL privilege granted either directly or through a role. + """ + user_name = f"user_{getuid()}" + role_name = f"role_{getuid()}" + + if node is None: + node = self.context.node + + with Given("I have a user"): + user(name=user_name) + + Scenario(test=create_with_privilege, + name="create with privilege granted directly")(grant_target_name=user_name, user_name=user_name) + + with Given("I have a user"): + user(name=user_name) + + with And("I have a role"): + role(name=role_name) + + with When("I grant the role to the user"): + node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") + + Scenario(test=create_with_privilege, + name="create with privilege granted through a role")(grant_target_name=role_name, user_name=user_name) + +@TestOutline +def create_with_privilege(self, user_name, grant_target_name, node=None): + """Grant ALL privilege and check the user is able is create the table. + """ + table0_name = f"table0_{getuid()}" + table1_name = f"table1_{getuid()}" + + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") + cluster = self.context.cluster_name + + if node is None: + node = self.context.node + + try: + with Given("I have a table on a cluster"): + table(name=table0_name, cluster=cluster) + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I create the distributed table as the user"): + node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())", settings = [("user", f"{user_name}")]) + + finally: + with Finally("I drop the distributed table"): + node.query(f"DROP TABLE IF EXISTS {table1_name}") + @TestSuite @Requirements( RQ_SRS_006_RBAC_DistributedTable_Select("1.0"), @@ -169,6 +247,7 @@ def select(self): select_scenarios = [ select_without_privilege, select_with_privilege_granted_directly_or_via_role, + select_with_all_privilege_granted_directly_or_via_role ] for scenario in select_scenarios: @@ -191,11 +270,19 @@ def select_without_privilege(self, node=None): try: with Given("I have a user"): user(name=user_name) + with And("I have a table on a cluster"): table(name=table0_name, cluster=cluster) + with And("I have a distributed table"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())") + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {user_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {user_name}") + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) @@ -222,8 +309,10 @@ def select_with_privilege_granted_directly_or_via_role(self, node=None): with Given("I have a user"): user(name=user_name) + with And("I have a role"): role(name=role_name) + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") @@ -247,25 +336,89 @@ def select_with_privilege(self, user_name, grant_target_name, node=None): try: with Given("I have a table on a cluster"): table(name=table0_name, cluster=cluster) + with And("I have a distributed table"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())") with When("I grant select privilege on the distributed table"): node.query(f"GRANT SELECT ON {table1_name} TO {grant_target_name}") + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I revoke select privilege on the distributed table"): node.query(f"REVOKE SELECT ON {table1_name} FROM {grant_target_name}") + with And("I grant select privilege on the table used by the distributed table"): node.query(f"GRANT SELECT ON {table0_name} to {grant_target_name}") + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant the user select privilege on the distributed table"): node.query(f"GRANT SELECT ON {table1_name} TO {grant_target_name}") + + with Then("I attempt to select from the distributed table as the user"): + node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")]) + + finally: + with Finally("I drop the distributed table"): + node.query(f"DROP TABLE IF EXISTS {table1_name}") + +@TestScenario +def select_with_all_privilege_granted_directly_or_via_role(self, node=None): + """Check that user is able to select from a distributed table if and only if + they have ALL privilege. + """ + user_name = f"user_{getuid()}" + role_name = f"role_{getuid()}" + + if node is None: + node = self.context.node + + with Given("I have a user"): + user(name=user_name) + + Scenario(test=select_with_privilege, + name="select with privilege granted directly")(grant_target_name=user_name, user_name=user_name) + + with Given("I have a user"): + user(name=user_name) + + with And("I have a role"): + role(name=role_name) + + with When("I grant the role to the user"): + node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") + + Scenario(test=select_with_privilege, + name="select with privilege granted through a role")(grant_target_name=role_name, user_name=user_name) + +@TestOutline +def select_with_privilege(self, user_name, grant_target_name, node=None): + """Grant ALL and check the user is able to select from the distributed table. + """ + table0_name = f"table0_{getuid()}" + table1_name = f"table1_{getuid()}" + + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") + cluster = self.context.cluster_name + + if node is None: + node = self.context.node + + try: + with Given("I have a table on a cluster"): + table(name=table0_name, cluster=cluster) + + with And("I have a distributed table"): + node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())") + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")]) @@ -293,10 +446,12 @@ def insert_without_privilege(self, node=None): """Check that user is unable to insert into a distributed table without privileges. """ user_name = f"user_{getuid()}" + table0_name = f"table0_{getuid()}" table1_name = f"table1_{getuid()}" exitcode, message = errors.not_enough_privileges(name=f"{user_name}") + cluster = self.context.cluster_name if node is None: @@ -305,11 +460,19 @@ def insert_without_privilege(self, node=None): try: with Given("I have a user"): user(name=user_name) + with And("I have a table on a cluster"): table(name=table0_name, cluster=cluster) + with And("I have a distributed table"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())") + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {user_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {user_name}") + with Then("I attempt to insert into the distributed table as the user"): node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) @@ -336,8 +499,10 @@ def insert_with_privilege_granted_directly_or_via_role(self, node=None): with Given("I have a user"): user(name=user_name) + with And("I have a role"): role(name=role_name) + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") @@ -361,25 +526,43 @@ def insert_with_privilege(self, user_name, grant_target_name, node=None): try: with Given("I have a table on a cluster"): table(name=table0_name, cluster=cluster) + with And("I have a distributed table"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())") with When("I grant insert privilege on the distributed table"): node.query(f"GRANT INSERT ON {table1_name} TO {grant_target_name}") + with Then("I attempt to insert into the distributed table as the user"): node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I revoke the insert privilege on the distributed table"): node.query(f"REVOKE INSERT ON {table1_name} FROM {grant_target_name}") + with And("I grant insert privilege on the table used by the distributed table"): node.query(f"GRANT INSERT ON {table0_name} to {grant_target_name}") + with Then("I attempt to insert into the distributed table as the user"): node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant insert privilege on the distributed table"): node.query(f"GRANT INSERT ON {table1_name} TO {grant_target_name}") + + with Then("I attempt to insert into the distributed table as the user"): + node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")]) + + with When("I revoke ALL privileges"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to insert into the distributed table as the user"): + node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")], + exitcode=exitcode, message=message) + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* To {grant_target_name}") + with Then("I attempt to insert into the distributed table as the user"): node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")]) @@ -426,8 +609,10 @@ def select_with_table_on_materialized_view_privilege_granted_directly_or_via_rol with Given("I have a user"): user(name=user_name) + with And("I have a role"): role(name=role_name) + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") @@ -452,33 +637,63 @@ def select_with_table_on_materialized_view(self, user_name, grant_target_name, n try: with Given("I have a table on a cluster"): table(name=table0_name, cluster=cluster) + with And("I have a materialized view on a cluster"): node.query(f"CREATE MATERIALIZED VIEW {view_name} ON CLUSTER {cluster} ENGINE = Memory() AS SELECT * FROM {table0_name}") + with And("I have a distributed table on the materialized view"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {view_name}, rand())") + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to select from the distributed table as the user"): + node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")], + exitcode=exitcode, message=message) + with When("I grant select privilege on the distributed table"): node.query(f"GRANT SELECT ON {table1_name} TO {grant_target_name}") + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I revoke the select privilege on the distributed table"): node.query(f"REVOKE SELECT ON {table1_name} FROM {grant_target_name}") + with And("I grant select privilege on the materialized view"): node.query(f"GRANT SELECT ON {view_name} to {grant_target_name}") + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant select privilege on the distributed table"): node.query(f"GRANT SELECT ON {table1_name} TO {grant_target_name}") + + with Then("I attempt to select from the distributed table as the user"): + node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")]) + + with When("I revoke ALL privileges"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to select from the distributed table as the user"): + node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")], + exitcode=exitcode, message=message) + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* To {grant_target_name}") + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")]) finally: with Finally("I drop the distributed table"): node.query(f"DROP TABLE IF EXISTS {table1_name}") + with And("I drop the view"): node.query(f"DROP VIEW IF EXISTS {view_name}") @@ -501,8 +716,10 @@ def select_with_table_on_source_table_of_materialized_view_privilege_granted_dir with Given("I have a user"): user(name=user_name) + with And("I have a role"): role(name=role_name) + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") @@ -527,33 +744,53 @@ def select_with_table_on_source_table_of_materialized_view(self, user_name, gran try: with Given("I have a table on a cluster"): table(name=table0_name, cluster=cluster) + with And("I have a materialized view on a cluster"): node.query(f"CREATE MATERIALIZED VIEW {view_name} ON CLUSTER {cluster} ENGINE = Memory() AS SELECT * FROM {table0_name}") + with And("I have a distributed table using the source table of the materialized view"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())") with When("I grant select privilege on the distributed table"): node.query(f"GRANT SELECT ON {table1_name} TO {grant_target_name}") + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I revoke select privilege on the distributed table"): node.query(f"REVOKE SELECT ON {table1_name} FROM {grant_target_name}") + with And("I grant select privilege on the source table"): node.query(f"GRANT SELECT ON {table0_name} to {grant_target_name}") + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant select privilege on the distributed table"): node.query(f"GRANT SELECT ON {table1_name} TO {grant_target_name}") + + with Then("I attempt to select from the distributed table as the user"): + node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")]) + + with When("I revoke ALL privileges"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to select from the distributed table as the user"): + node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")], + exitcode=exitcode, message=message) + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* To {grant_target_name}") + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")]) finally: with Finally("I drop the distributed table"): node.query(f"DROP TABLE IF EXISTS {table1_name}") + with And("I drop the view"): node.query(f"DROP VIEW IF EXISTS {view_name}") @@ -576,8 +813,10 @@ def select_with_table_on_distributed_table_privilege_granted_directly_or_via_rol with Given("I have a user"): user(name=user_name) + with And("I have a role"): role(name=role_name) + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") @@ -602,26 +841,47 @@ def select_with_table_on_distributed_table(self, user_name, grant_target_name, n try: with Given("I have a table on a cluster"): table(name=table0_name, cluster=cluster) + with And("I have a distributed table on a cluster"): node.query(f"CREATE TABLE {table1_name} ON CLUSTER {cluster} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())") + with And("I have a distributed table on that distributed table"): node.query(f"CREATE TABLE {table2_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table1_name}, rand())") for permutation in permutations(table_count=3): + with grant_select_on_table(node, permutation, grant_target_name, table0_name, table1_name, table2_name) as tables_granted: + with When(f"permutation={permutation}, tables granted = {tables_granted}"): + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table2_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant select on all tables"): + with grant_select_on_table(node, max(permutations(table_count=3))+1, grant_target_name, table0_name, table1_name, table2_name): + with Then("I attempt to select from the distributed table as the user"): node.query(f"SELECT * FROM {table2_name}", settings = [("user", f"{user_name}")]) + with When("I revoke ALL privileges"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to select from the distributed table as the user"): + node.query(f"SELECT * FROM {table2_name}", settings = [("user", f"{user_name}")], + exitcode=exitcode, message=message) + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* To {grant_target_name}") + + with Then("I attempt to select from the distributed table as the user"): + node.query(f"SELECT * FROM {table2_name}", settings = [("user", f"{user_name}")]) + finally: with Finally("I drop the first distributed table"): node.query(f"DROP TABLE IF EXISTS {table1_name}") + with And("I drop the other distributed table"): node.query(f"DROP TABLE IF EXISTS {table2_name}") @@ -644,8 +904,10 @@ def insert_with_table_on_materialized_view_privilege_granted_directly_or_via_rol with Given("I have a user"): user(name=user_name) + with And("I have a role"): role(name=role_name) + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") @@ -671,35 +933,56 @@ def insert_with_table_on_materialized_view(self, user_name, grant_target_name, n try: with Given(f"I have a table on cluster {cluster}"): table(name=table0_name, cluster=cluster) + with And("I have another table on the same cluster"): table(name=table1_name, cluster=cluster) + with And("I have a materialized view on a cluster"): node.query(f"CREATE MATERIALIZED VIEW {view_name} ON CLUSTER {cluster} TO {table0_name} AS SELECT * FROM {table1_name}") + with And("I have a distributed table on the materialized view"): node.query(f"CREATE TABLE {table2_name} (a UInt64) ENGINE = Distributed({cluster}, default, {view_name}, rand())") with When("I grant insert privilege on the distributed table"): node.query(f"GRANT INSERT ON {table2_name} TO {grant_target_name}") + with Then("I attempt to insert into the distributed table as the user"): node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I revoke the insert privilege on the distributed table"): node.query(f"REVOKE INSERT ON {table2_name} FROM {grant_target_name}") + with And("I grant insert privilege on the view"): node.query(f"GRANT INSERT ON {view_name} to {grant_target_name}") + with Then("I attempt insert into the distributed table as the user"): node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant insert privilege on the distributed table"): node.query(f"GRANT INSERT ON {table2_name} TO {grant_target_name}") + + with Then("I attempt to insert into the distributed table as the user"): + node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")]) + + with When("I revoke ALL privileges"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt insert into the distributed table as the user"): + node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")], + exitcode=exitcode, message=message) + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* To {grant_target_name}") + with Then("I attempt to insert into the distributed table as the user"): node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")]) finally: with Finally("I drop the distributed table"): node.query(f"DROP TABLE IF EXISTS {table2_name}") + with And("I drop the view"): node.query(f"DROP VIEW IF EXISTS {view_name}") @@ -722,8 +1005,10 @@ def insert_with_table_on_source_table_of_materialized_view_privilege_granted_dir with Given("I have a user"): user(name=user_name) + with And("I have a role"): role(name=role_name) + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") @@ -748,33 +1033,53 @@ def insert_with_table_on_source_table_of_materialized_view(self, user_name, gran try: with Given("I have a table on a cluster"): table(name=table0_name, cluster=cluster) + with And("I have a materialized view on a cluster"): node.query(f"CREATE MATERIALIZED VIEW {view_name} ON CLUSTER {cluster} ENGINE = Memory() AS SELECT * FROM {table0_name}") + with And("I have a distributed table on the materialized view"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())") with When("I grant insert privilege on the distributed table"): node.query(f"GRANT INSERT ON {table1_name} TO {grant_target_name}") + with Then("I attempt to insert into the distributed table as the user"): node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I revoke insert privilege on the distributed table"): node.query(f"REVOKE INSERT ON {table1_name} FROM {grant_target_name}") + with And("I grant insert privilege on the source table"): node.query(f"GRANT INSERT ON {table0_name} to {grant_target_name}") + with Then("I attempt insert into the distributed table as the user"): node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant insert privilege on the distributed table"): node.query(f"GRANT INSERT ON {table1_name} TO {grant_target_name}") + + with Then("I attempt to insert into the distributed table as the user"): + node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")]) + + with When("I revoke ALL privileges"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt insert into the distributed table as the user"): + node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")], + exitcode=exitcode, message=message) + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* To {grant_target_name}") + with Then("I attempt to insert into the distributed table as the user"): node.query(f"INSERT INTO {table1_name} VALUES (8888)", settings = [("user", f"{user_name}")]) finally: with Finally("I drop the distributed table"): node.query(f"DROP TABLE IF EXISTS {table1_name}") + with And("I drop the view"): node.query(f"DROP VIEW IF EXISTS {view_name}") @@ -797,8 +1102,10 @@ def insert_with_table_on_distributed_table_privilege_granted_directly_or_via_rol with Given("I have a user"): user(name=user_name) + with And("I have a role"): role(name=role_name) + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name} ON CLUSTER one_shard_cluster") @@ -823,47 +1130,70 @@ def insert_with_table_on_distributed_table(self, user_name, grant_target_name, n try: with Given("I have a table on a cluster"): table(name=table0_name, cluster=cluster) + with And("I have a distributed table on a cluster"): node.query(f"CREATE TABLE {table1_name} ON CLUSTER {cluster} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())") + with And("I have a distributed table on that distributed table"): node.query(f"CREATE TABLE {table2_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table1_name}, rand())") with When("I grant insert privilege on the outer distributed table"): node.query(f"GRANT INSERT ON {table2_name} TO {grant_target_name}") + with Then("I attempt to insert into the outer distributed table as the user"): node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I revoke the insert privilege on the outer distributed table"): node.query(f"REVOKE INSERT ON {table2_name} FROM {grant_target_name}") + with And("I grant insert privilege on the inner distributed table"): node.query(f"GRANT INSERT ON {table1_name} to {grant_target_name}") + with Then("I attempt insert into the outer distributed table as the user"): node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I revoke the insert privilege on the inner distributed table"): node.query(f"REVOKE INSERT ON {table1_name} FROM {grant_target_name}") + with And("I grant insert privilege on the innermost table"): node.query(f"GRANT INSERT ON {table0_name} to {grant_target_name}") + with Then("I attempt insert into the outer distributed table as the user"): node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant insert privilege on the inner distributed table"): node.query(f"GRANT INSERT ON {table1_name} to {grant_target_name}") + with Then("I attempt insert into the outer distributed table as the user"): node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant insert privilege on the outer distributed table"): node.query(f"GRANT INSERT ON {table2_name} to {grant_target_name}") + + with Then("I attempt insert into the outer distributed table as the user"): + node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")]) + + with When("I revoke ALL privileges"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt insert into the outer distributed table as the user"): + node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")], + exitcode=exitcode, message=message) + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* To {grant_target_name}") + with Then("I attempt insert into the outer distributed table as the user"): node.query(f"INSERT INTO {table2_name} VALUES (8888)", settings = [("user", f"{user_name}")]) finally: with Finally("I drop the outer distributed table"): node.query(f"DROP TABLE IF EXISTS {table1_name}") + with And("I drop the inner distributed table"): node.query(f"DROP TABLE IF EXISTS {table2_name}") @@ -882,6 +1212,7 @@ def local_user(self, cluster, node=None): is able to execute queries they have privileges to. """ user_name = f"user_{getuid()}" + table0_name = f"table0_{getuid()}" table1_name = f"table1_{getuid()}" @@ -891,22 +1222,35 @@ def local_user(self, cluster, node=None): try: with Given("I have a user on one node"): node.query(f"CREATE USER {user_name}") + with And("I have a table on a cluster"): table(name=table0_name, cluster=cluster) + with And("I have a distributed table"): node.query(f"CREATE TABLE {table1_name} (a UInt64) ENGINE = Distributed({cluster}, default, {table0_name}, rand())") with When("I grant select privilege on the distributed table"): node.query(f"GRANT SELECT ON {table1_name} TO {user_name}") + with And("I grant select privilege on the other table"): node.query(f"GRANT SELECT ON {table0_name} TO {user_name}") with Then("I select from the distributed table as the user"): node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")]) + with When("I revoke ALL privileges"): + node.query(f"REVOKE ALL ON *.* FROM {user_name}") + + with And("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* To {user_name}") + + with Then("I select from the distributed table as the user"): + node.query(f"SELECT * FROM {table1_name}", settings = [("user", f"{user_name}")]) + finally: with Finally("I drop the user"): node.query(f"DROP USER IF EXISTS {user_name}") + with And("I drop the distributed table"): node.query(f"DROP TABLE IF EXISTS {table1_name}") @@ -919,8 +1263,10 @@ def multiple_node_user(self, node=None): if and only if they have the required privileges on the node they are executing the query from. """ user_name = f"user_{getuid()}" + table0_name = f"table0_{getuid()}" table1_name = f"table1_{getuid()}" + exitcode, message = errors.not_enough_privileges(name=f"{user_name}") if node is None: @@ -931,13 +1277,16 @@ def multiple_node_user(self, node=None): try: with Given("I have a user on a cluster with two nodes"): node.query(f"CREATE USER {user_name} ON CLUSTER sharded_cluster12") + with And("I have a table on a cluster"): table(name=table0_name, cluster="sharded_cluster12") + with And("I have a distributed table"): node.query(f"CREATE TABLE {table1_name} ON CLUSTER sharded_cluster12 (a UInt64) ENGINE = Distributed(sharded_cluster12, default, {table0_name}, rand())") with When("I grant select privilege on the distributed table on one node"): node.query(f"GRANT SELECT ON {table1_name} TO {user_name}") + with And("I grant select privilege on the other table on one node"): node.query(f"GRANT SELECT ON {table0_name} TO {user_name}") @@ -951,6 +1300,7 @@ def multiple_node_user(self, node=None): finally: with Finally("I drop the user"): node.query(f"DROP USER IF EXISTS {user_name}") + with And("I drop the distributed table"): node.query(f"DROP TABLE IF EXISTS {table1_name}") @@ -973,13 +1323,19 @@ def cluster_tests(self, cluster, node=None): pool = Pool(3) try: - for suite in loads(current_module(), Suite): - run_scenario(pool, tasks, Suite(test=suite)) + try: + for suite in loads(current_module(), Suite): + run_scenario(pool, tasks, Suite(test=suite)) + finally: + join(tasks) finally: - join(tasks) - + pool.close() @TestFeature +@Requirements( + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") +) @Name("distributed table") def feature(self, node="clickhouse1"): """Check the RBAC functionality of queries executed using distributed tables. @@ -992,9 +1348,13 @@ def feature(self, node="clickhouse1"): pool = Pool(3) try: - run_scenario(pool, tasks, Feature(test=cluster_tests)) - run_scenario(pool, tasks, Scenario(test=local_user)) - run_scenario(pool, tasks, Scenario(test=multiple_node_user)) + try: + run_scenario(pool, tasks, Feature(test=cluster_tests)) + run_scenario(pool, tasks, Scenario(test=local_user)) + run_scenario(pool, tasks, Scenario(test=multiple_node_user)) + finally: + join(tasks) finally: - join(tasks) + pool.close() + diff --git a/tests/testflows/rbac/tests/privileges/drop/drop_database.py b/tests/testflows/rbac/tests/privileges/drop/drop_database.py index fd31b8d5411..274003e763f 100644 --- a/tests/testflows/rbac/tests/privileges/drop/drop_database.py +++ b/tests/testflows/rbac/tests/privileges/drop/drop_database.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute DROP DATABASE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,21 +32,27 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): db_name = f"db_{getuid()}" try: with Given("I have a database"): node.query(f"CREATE DATABASE {db_name}") - with When("I attempt to drop the database"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to drop the database"): node.query(f"DROP DATABASE {db_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) finally: with Finally("I drop the database"): node.query(f"DROP DATABASE IF EXISTS {db_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): db_name = f"db_{getuid()}" try: @@ -63,7 +69,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the database"): node.query(f"DROP DATABASE IF EXISTS {db_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): db_name = f"db_{getuid()}" try: @@ -84,9 +90,49 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the database"): node.query(f"DROP DATABASE IF EXISTS {db_name}") + with Scenario("user with revoked ALL privilege"): + db_name = f"db_{getuid()}" + + try: + with Given("I have a database"): + node.query(f"CREATE DATABASE {db_name}") + + with When("I grant the drop database privilege"): + node.query(f"GRANT DROP DATABASE ON {db_name}.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to drop a database"): + node.query(f"DROP DATABASE {db_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I drop the database"): + node.query(f"DROP DATABASE IF EXISTS {db_name}") + + with Scenario("user with ALL privilege"): + db_name = f"db_{getuid()}" + + try: + with Given("I have a database"): + node.query(f"CREATE DATABASE {db_name}") + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to drop a database"): + node.query(f"DROP DATABASE {db_name}", settings = [("user", user_name)]) + + finally: + with Finally("I drop the database"): + node.query(f"DROP DATABASE IF EXISTS {db_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_DropDatabase("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("drop database") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -99,5 +145,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/drop/drop_dictionary.py b/tests/testflows/rbac/tests/privileges/drop/drop_dictionary.py index 14e6da0ebe9..c3f07885bd5 100644 --- a/tests/testflows/rbac/tests/privileges/drop/drop_dictionary.py +++ b/tests/testflows/rbac/tests/privileges/drop/drop_dictionary.py @@ -12,12 +12,12 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute DROP DICTIONARY with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") @@ -29,21 +29,27 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): dict_name = f"dict_{getuid()}" try: with Given("I have a dictionary"): node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)") - with When("I attempt to drop a dictionary without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to drop a dictionary without privilege"): node.query(f"DROP DICTIONARY {dict_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) finally: with Finally("I drop the dictionary"): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): dict_name = f"dict_{getuid()}" try: @@ -60,7 +66,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the dictionary"): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): dict_name = f"dict_{getuid()}" try: @@ -80,9 +86,27 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the dictionary"): node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") + with Scenario("user with ALL privilege"): + dict_name = f"db_{getuid()}" + + try: + with Given("I have a dictionary"): + node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)") + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I drop the dictionary"): + node.query(f"DROP DICTIONARY {dict_name}", settings = [("user", user_name)]) + + finally: + with Finally("I drop the dictionary"): + node.query(f"DROP DICTIONARY IF EXISTS {dict_name}") @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_DropDictionary("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("drop dictionary") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -95,5 +119,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/drop/drop_quota.py b/tests/testflows/rbac/tests/privileges/drop/drop_quota.py index de25f0e15b1..b8727556a26 100644 --- a/tests/testflows/rbac/tests/privileges/drop/drop_quota.py +++ b/tests/testflows/rbac/tests/privileges/drop/drop_quota.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=drop_quota, flags=TE, + Suite(run=drop_quota, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in drop_quota.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=drop_quota, flags=TE, + Suite(run=drop_quota, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in drop_quota.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("DROP QUOTA",), ]) @@ -63,7 +64,13 @@ def drop_quota(self, privilege, grant_target_name, user_name, node=None): with Given("I have a quota"): node.query(f"CREATE QUOTA {drop_row_policy_name}") - with When("I check the user can't drop a quota"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't drop a quota"): node.query(f"DROP QUOTA {drop_row_policy_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -129,6 +136,8 @@ def drop_quota(self, privilege, grant_target_name, user_name, node=None): @Name("drop quota") @Requirements( RQ_SRS_006_RBAC_Privileges_DropQuota("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of DROP QUOTA. diff --git a/tests/testflows/rbac/tests/privileges/drop/drop_role.py b/tests/testflows/rbac/tests/privileges/drop/drop_role.py index 4b6b7c04741..ca9eb1b0947 100644 --- a/tests/testflows/rbac/tests/privileges/drop/drop_role.py +++ b/tests/testflows/rbac/tests/privileges/drop/drop_role.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=drop_role, flags=TE, + Suite(run=drop_role, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in drop_role.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=drop_role, flags=TE, + Suite(run=drop_role, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in drop_role.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("DROP ROLE",), ]) @@ -58,14 +59,22 @@ def drop_role(self, privilege, grant_target_name, user_name, node=None): with Scenario("DROP ROLE without privilege"): drop_role_name = f"drop_role_{getuid()}" + with role(node, drop_role_name): - with When("I check the user can't drop a role"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't drop a role"): node.query(f"DROP ROLE {drop_role_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) with Scenario("DROP ROLE with privilege"): drop_role_name = f"drop_role_{getuid()}" + with role(node, drop_role_name): with When(f"I grant {privilege}"): @@ -93,6 +102,7 @@ def drop_role(self, privilege, grant_target_name, user_name, node=None): with Scenario("DROP ROLE with revoked privilege"): drop_role_name = f"drop_role_{getuid()}" + with role(node, drop_role_name): with When(f"I grant {privilege}"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -108,6 +118,8 @@ def drop_role(self, privilege, grant_target_name, user_name, node=None): @Name("drop role") @Requirements( RQ_SRS_006_RBAC_Privileges_DropRole("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of DROP ROLE. diff --git a/tests/testflows/rbac/tests/privileges/drop/drop_row_policy.py b/tests/testflows/rbac/tests/privileges/drop/drop_row_policy.py index 6e8a2aaa3d5..ad7fed94df0 100644 --- a/tests/testflows/rbac/tests/privileges/drop/drop_row_policy.py +++ b/tests/testflows/rbac/tests/privileges/drop/drop_row_policy.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=drop_row_policy, flags=TE, + Suite(run=drop_row_policy, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in drop_row_policy.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=drop_row_policy, flags=TE, + Suite(run=drop_row_policy, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in drop_row_policy.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("DROP ROW POLICY",), ("DROP POLICY",), @@ -65,7 +66,13 @@ def drop_row_policy(self, privilege, grant_target_name, user_name, node=None): with Given("I have a row policy"): node.query(f"CREATE ROW POLICY {drop_row_policy_name} ON {table_name}") - with When("I check the user can't drop a row policy"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't drop a row policy"): node.query(f"DROP ROW POLICY {drop_row_policy_name} ON {table_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -130,15 +137,140 @@ def drop_row_policy(self, privilege, grant_target_name, user_name, node=None): with Finally("I drop the row policy"): node.query(f"DROP ROW POLICY IF EXISTS {drop_row_policy_name} ON {table_name}") +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Restriction("1.0") +) +def drop_all_pol_with_conditions(self, node=None): + """Check that when all policies with conditions are dropped, the table becomes unrestricted. + """ + + if node is None: + node = self.context.node + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The row policy has a condition"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING 1") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with And("I can't see any of the rows on the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '' == output, error() + + with When("I drop the row policy"): + node.query(f"DROP ROW POLICY {pol_name} ON {table_name}") + + with Then("I select all the rows from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output and '2' in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0"), +) +def drop_on(self, node=None): + """Check that when a row policy is dropped, users are able to access rows restricted by that policy. + """ + + if node is None: + node = self.context.node + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + with table(node, table_name): + + with Given("I have a row policy"): + row_policy(name=pol_name, table=table_name) + + with And("The row policy has a condition"): + node.query(f"ALTER ROW POLICY {pol_name} ON {table_name} FOR SELECT USING y=1 TO default") + + with And("The table has some values"): + node.query(f"INSERT INTO {table_name} (y) VALUES (1),(2)") + + with And("I can't see one of the rows on the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output and '2' not in output, error() + + with When("I drop the row policy"): + node.query(f"DROP ROW POLICY {pol_name} ON {table_name}") + + with Then("I select all the rows from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output and '2' in output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_RowPolicy_Drop_OnCluster("1.0"), +) +def drop_on_cluster(self, node=None): + """Check that when a row policy is dropped on a cluster, it works on all nodes. + """ + + if node is None: + node = self.context.node + node2 = self.context.node2 + + table_name = f"table_{getuid()}" + pol_name = f"pol_{getuid()}" + + try: + with Given("I have a table on a cluster"): + node.query(f"CREATE TABLE {table_name} ON CLUSTER sharded_cluster (x UInt64) ENGINE = Memory") + + with And("I have a row policy"): + node.query(f"CREATE ROW POLICY {pol_name} ON CLUSTER sharded_cluster ON {table_name} FOR SELECT USING 1") + + with And("There are some values on the table on the first node"): + node.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with And("There are some values on the table on the second node"): + node2.query(f"INSERT INTO {table_name} (x) VALUES (1)") + + with When("I drop the row policy on cluster"): + node.query(f"DROP ROW POLICY {pol_name} ON {table_name} ON CLUSTER sharded_cluster") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + with And("I select from another node on the cluster"): + output = node2.query(f"SELECT * FROM {table_name}").output + assert '1' in output, error() + + finally: + with Finally("I drop the row policy", flags=TE): + node.query(f"DROP ROW POLICY IF EXISTS {pol_name} ON CLUSTER sharded_cluster ON {table_name}") + + with And("I drop the table", flags=TE): + node.query(f"DROP TABLE {table_name} ON CLUSTER sharded_cluster") + @TestFeature @Name("drop row policy") @Requirements( RQ_SRS_006_RBAC_Privileges_DropRowPolicy("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of DROP ROW POLICY. """ self.context.node = self.context.cluster.node(node) + self.context.node2 = self.context.cluster.node("clickhouse2") Suite(run=privileges_granted_directly, setup=instrument_clickhouse_server_log) Suite(run=privileges_granted_via_role, setup=instrument_clickhouse_server_log) + + Scenario(run=drop_all_pol_with_conditions, setup=instrument_clickhouse_server_log) + Scenario(run=drop_on, setup=instrument_clickhouse_server_log) + Scenario(run=drop_on_cluster, setup=instrument_clickhouse_server_log) diff --git a/tests/testflows/rbac/tests/privileges/drop/drop_settings_profile.py b/tests/testflows/rbac/tests/privileges/drop/drop_settings_profile.py index 51139653283..3aa9ef2c369 100644 --- a/tests/testflows/rbac/tests/privileges/drop/drop_settings_profile.py +++ b/tests/testflows/rbac/tests/privileges/drop/drop_settings_profile.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=drop_settings_profile, flags=TE, + Suite(run=drop_settings_profile, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in drop_settings_profile.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=drop_settings_profile, flags=TE, + Suite(run=drop_settings_profile, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in drop_settings_profile.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("DROP SETTINGS PROFILE",), ("DROP PROFILE",), @@ -64,7 +65,13 @@ def drop_settings_profile(self, privilege, grant_target_name, user_name, node=No with Given("I have a settings_profile"): node.query(f"CREATE SETTINGS PROFILE {drop_row_policy_name}") - with When("I check the user can't drop a settings_profile"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't drop a settings_profile"): node.query(f"DROP SETTINGS PROFILE {drop_row_policy_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -130,6 +137,8 @@ def drop_settings_profile(self, privilege, grant_target_name, user_name, node=No @Name("drop settings profile") @Requirements( RQ_SRS_006_RBAC_Privileges_DropSettingsProfile("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of DROP SETTINGS PROFILE. diff --git a/tests/testflows/rbac/tests/privileges/drop/drop_table.py b/tests/testflows/rbac/tests/privileges/drop/drop_table.py index e5deac646eb..1fd394daf96 100644 --- a/tests/testflows/rbac/tests/privileges/drop/drop_table.py +++ b/tests/testflows/rbac/tests/privileges/drop/drop_table.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute DROP TABLE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,14 +32,20 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): table_name = f"table_{getuid()}" try: with Given("I have a table"): node.query(f"CREATE TABLE {table_name} (x Int8) ENGINE=Memory") - with When("I attempt to drop a table without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to drop a table without privilege"): node.query(f"DROP TABLE {table_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) @@ -47,7 +53,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the table"): node.query(f"DROP TABLE IF EXISTS {table_name}") - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): table_name = f"table_{getuid()}" try: @@ -64,7 +70,7 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the table"): node.query(f"DROP TABLE IF EXISTS {table_name}") - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): table_name = f"table_{getuid()}" try: with Given("I have a table"): @@ -84,9 +90,48 @@ def privilege_check(grant_target_name, user_name, node=None): with Finally("I drop the table"): node.query(f"DROP TABLE IF EXISTS {table_name}") + with Scenario("user with revoked ALL privilege"): + table_name = f"table_{getuid()}" + try: + with Given("I have a table"): + node.query(f"CREATE TABLE {table_name} (x Int8) ENGINE=Memory") + + with When("I grant the drop table privilege"): + node.query(f"GRANT DROP TABLE ON *.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to drop a table"): + node.query(f"DROP TABLE {table_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + finally: + with Finally("I drop the table"): + node.query(f"DROP TABLE IF EXISTS {table_name}") + + with Scenario("user with ALL privilege"): + table_name = f"table_{getuid()}" + + try: + with Given("I have a table"): + node.query(f"CREATE TABLE {table_name} (x Int8) ENGINE=Memory") + + with When("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I drop the table"): + node.query(f"DROP TABLE {table_name}", settings = [("user", user_name)]) + + finally: + with Finally("I drop the table"): + node.query(f"DROP TABLE IF EXISTS {table_name}") + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_DropTable("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("drop table") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -99,5 +144,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/drop/drop_user.py b/tests/testflows/rbac/tests/privileges/drop/drop_user.py index 9aec34cca81..c3f1df8ae15 100644 --- a/tests/testflows/rbac/tests/privileges/drop/drop_user.py +++ b/tests/testflows/rbac/tests/privileges/drop/drop_user.py @@ -17,7 +17,7 @@ def drop_user_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=drop_user, flags=TE, + Suite(run=drop_user, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in drop_user.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def drop_user_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=drop_user, flags=TE, + Suite(run=drop_user, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in drop_user.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("DROP USER",), ]) @@ -59,14 +60,22 @@ def drop_user(self, privilege, grant_target_name, user_name, node=None): with Scenario("DROP USER without privilege"): drop_user_name = f"drop_user_{getuid()}" + with user(node, drop_user_name): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + with When("I check the user can't drop a user"): node.query(f"DROP USER {drop_user_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) with Scenario("DROP USER with privilege"): drop_user_name = f"drop_user_{getuid()}" + with user(node, drop_user_name): with When(f"I grant {privilege}"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -76,6 +85,7 @@ def drop_user(self, privilege, grant_target_name, user_name, node=None): with Scenario("DROP USER on cluster"): drop_user_name = f"drop_user_{getuid()}" + try: with Given("I have a user on a cluster"): node.query(f"CREATE USER {drop_user_name} ON CLUSTER sharded_cluster") @@ -93,6 +103,7 @@ def drop_user(self, privilege, grant_target_name, user_name, node=None): with Scenario("DROP USER with revoked privilege"): drop_user_name = f"drop_user_{getuid()}" + with user(node, drop_user_name): with When(f"I grant {privilege}"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -108,6 +119,8 @@ def drop_user(self, privilege, grant_target_name, user_name, node=None): @Name("drop user") @Requirements( RQ_SRS_006_RBAC_Privileges_DropUser("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of DROP USER. diff --git a/tests/testflows/rbac/tests/privileges/feature.py b/tests/testflows/rbac/tests/privileges/feature.py index e7a0cf2d368..7302a971ec1 100755 --- a/tests/testflows/rbac/tests/privileges/feature.py +++ b/tests/testflows/rbac/tests/privileges/feature.py @@ -11,91 +11,92 @@ def feature(self): try: try: - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.insert", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.select", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.public_tables", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.distributed_table", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.grant_option", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.truncate", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.optimize", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.kill_query", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.kill_mutation", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.role_admin", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.dictGet", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.introspection", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.sources", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.admin_option", "feature"), flags=TE), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.insert", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.select", "feature"), ), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.public_tables", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.distributed_table", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.grant_option", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.truncate", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.optimize", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.kill_query", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.kill_mutation", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.role_admin", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.dictGet", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.introspection", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.sources", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.admin_option", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.all_role", "feature")), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_tables", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_dictionaries", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_databases", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_columns", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_users", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_roles", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_quotas", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_settings_profiles", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_row_policies", "feature"), flags=TE), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_tables", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_dictionaries", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_databases", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_columns", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_users", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_roles", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_quotas", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_settings_profiles", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.show.show_row_policies", "feature")), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_column", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_index", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_constraint", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_ttl", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_settings", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_update", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_delete", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_freeze", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_fetch", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_move", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_user", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_role", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_row_policy", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_quota", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_settings_profile", "feature"), flags=TE), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_column", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_index", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_constraint", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_ttl", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_settings", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_update", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_delete", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_freeze", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_fetch", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_move", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_user", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_role", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_row_policy", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_quota", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.alter.alter_settings_profile", "feature")), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_database", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_dictionary", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_temp_table", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_table", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_user", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_role", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_row_policy", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_quota", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_settings_profile", "feature"), flags=TE), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_database", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_dictionary", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_temp_table", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_table", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_user", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_role", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_row_policy", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_quota", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.create.create_settings_profile", "feature")), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.attach.attach_database", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.attach.attach_dictionary", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.attach.attach_temp_table", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.attach.attach_table", "feature"), flags=TE), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.attach.attach_database", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.attach.attach_dictionary", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.attach.attach_temp_table", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.attach.attach_table", "feature")), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_database", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_dictionary", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_table", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_user", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_role", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_row_policy", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_quota", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_settings_profile", "feature"), flags=TE), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_database", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_dictionary", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_table", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_user", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_role", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_row_policy", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_quota", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.drop.drop_settings_profile", "feature")), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.detach.detach_database", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.detach.detach_dictionary", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.detach.detach_table", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.detach.detach_view", "feature"), flags=TE), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.detach.detach_database", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.detach.detach_dictionary", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.detach.detach_table", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.detach.detach_view", "feature")), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.drop_cache", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.reload", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.flush", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.merges", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.moves", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.replication_queues", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.ttl_merges", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.restart_replica", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.sends", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.sync_replica", "feature"), flags=TE), {}) - run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.fetches", "feature"), flags=TE), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.drop_cache", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.reload", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.flush", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.merges", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.moves", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.replication_queues", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.ttl_merges", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.restart_replica", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.sends", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.sync_replica", "feature")), {}) + run_scenario(pool, tasks, Feature(test=load("rbac.tests.privileges.system.fetches", "feature")), {}) finally: join(tasks) finally: pool.close() - Feature(test=load("rbac.tests.privileges.system.shutdown", "feature"), flags=TE) + Feature(test=load("rbac.tests.privileges.system.shutdown", "feature")) diff --git a/tests/testflows/rbac/tests/privileges/insert.py b/tests/testflows/rbac/tests/privileges/insert.py index 78478967d37..305ce62f5e4 100755 --- a/tests/testflows/rbac/tests/privileges/insert.py +++ b/tests/testflows/rbac/tests/privileges/insert.py @@ -16,6 +16,9 @@ def input_output_equality_check(node, input_columns, input_data, table_name): return input_dict == output_dict @TestScenario +@Requirements( + RQ_SRS_006_RBAC_Privileges_None("1.0") +) def without_privilege(self, table_type, node=None): """Check that user without insert privilege on a table is not able to insert on that table. """ @@ -28,7 +31,13 @@ def without_privilege(self, table_type, node=None): with table(node, table_name, table_type): with user(node, user_name): - with When("I run INSERT without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {user_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {user_name}") + + with Then("I run INSERT without privilege"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", settings = [("user", user_name)], @@ -60,6 +69,34 @@ def user_with_privilege(self, table_type, node=None): output = node.query(f"SELECT d FROM {table_name} FORMAT JSONEachRow").output assert output == '{"d":"2020-01-01"}', error() +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Grant_Privilege_Insert("1.0"), +) +def all_privilege(self, table_type, node=None): + """Check that user can insert into a table on which they have insert privilege. + """ + user_name = f"user_{getuid()}" + table_name = f"table_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name, table_type): + + with user(node, user_name): + + with When("I grant insert privilege"): + node.query(f"GRANT ALL ON *.* TO {user_name}") + + with And("I use INSERT"): + node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", settings=[("user",user_name)]) + + with Then("I check the insert functioned"): + output = node.query(f"SELECT d FROM {table_name} FORMAT JSONEachRow").output + assert output == '{"d":"2020-01-01"}', error() + @TestScenario @Requirements( RQ_SRS_006_RBAC_Revoke_Privilege_Insert("1.0"), @@ -82,7 +119,31 @@ def user_with_revoked_privilege(self, table_type, node=None): with And("I revoke insert privilege"): node.query(f"REVOKE INSERT ON {table_name} FROM {user_name}") - with And("I use INSERT"): + with Then("I use INSERT"): + exitcode, message = errors.not_enough_privileges(name=user_name) + node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", + settings=[("user",user_name)], exitcode=exitcode, message=message) + +@TestScenario +def user_with_all_revoked_privilege(self, table_type, node=None): + """Check that user is unable to insert into a table after ALL privilege has been revoked from user. + """ + user_name = f"user_{getuid()}" + table_name = f"table_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name, table_type): + with user(node, user_name): + + with When("I grant insert privilege"): + node.query(f"GRANT INSERT ON {table_name} TO {user_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {user_name}") + + with Then("I use INSERT"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -111,26 +172,36 @@ def user_column_privileges(self, grant_columns, insert_columns_pass, data_fail, """ user_name = f"user_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with user(node, user_name): + with When("I grant insert privilege"): node.query(f"GRANT INSERT({grant_columns}) ON {table_name} TO {user_name}") + if insert_columns_fail is not None: with And("I insert into a column without insert privilege"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"INSERT INTO {table_name} ({insert_columns_fail}) VALUES ({data_fail})", settings=[("user",user_name)], exitcode=exitcode, message=message) + with And("I insert into granted column"): node.query(f"INSERT INTO {table_name} ({insert_columns_pass}) VALUES ({data_pass})", settings=[("user",user_name)]) + with Then("I check the insert functioned"): input_equals_output = input_output_equality_check(node, insert_columns_pass, data_pass, table_name) assert input_equals_output, error() + if revoke_columns is not None: + with When("I revoke insert privilege from columns"): node.query(f"REVOKE INSERT({revoke_columns}) ON {table_name} FROM {user_name}") + with And("I insert into revoked columns"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"INSERT INTO {table_name} ({insert_columns_pass}) VALUES ({data_pass})", @@ -147,16 +218,23 @@ def role_with_privilege(self, table_type, node=None): user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with user(node, user_name), role(node, role_name): + with When("I grant insert privilege to a role"): node.query(f"GRANT INSERT ON {table_name} TO {role_name}") + with And("I grant the role to a user"): node.query(f"GRANT {role_name} TO {user_name}") + with And("I insert into the table"): node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", settings=[("user",user_name)]) + with Then("I check the data matches the input"): output = node.query(f"SELECT d FROM {table_name} FORMAT JSONEachRow").output assert output == '{"d":"2020-01-01"}', error() @@ -173,16 +251,23 @@ def role_with_revoked_privilege(self, table_type, node=None): user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with user(node, user_name), role(node, role_name): + with When("I grant privilege to a role"): node.query(f"GRANT INSERT ON {table_name} TO {role_name}") + with And("I grant the role to a user"): node.query(f"GRANT {role_name} TO {user_name}") + with And("I revoke privilege from the role"): node.query(f"REVOKE INSERT ON {table_name} FROM {role_name}") + with And("I insert into the table"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", @@ -196,16 +281,23 @@ def user_with_revoked_role(self, table_type, node=None): user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with user(node, user_name), role(node, role_name): + with When("I grant privilege to a role"): node.query(f"GRANT INSERT ON {table_name} TO {role_name}") + with And("I grant the role to a user"): node.query(f"GRANT {role_name} TO {user_name}") + with And("I revoke the role from the user"): node.query(f"REVOKE {role_name} FROM {user_name}") + with And("I insert into the table"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", @@ -235,32 +327,43 @@ def role_column_privileges(self, grant_columns, insert_columns_pass, data_fail, user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): with user(node, user_name), role(node, role_name): - with When("I grant insert privilege"): - node.query(f"GRANT INSERT({grant_columns}) ON {table_name} TO {role_name}") - with And("I grant the role to a user"): - node.query(f"GRANT {role_name} TO {user_name}") - if insert_columns_fail is not None: - with And("I insert into columns without insert privilege"): - exitcode, message = errors.not_enough_privileges(name=user_name) - node.query(f"INSERT INTO {table_name} ({insert_columns_fail}) VALUES ({data_fail})", - settings=[("user",user_name)], exitcode=exitcode, message=message) - with And("I insert into granted column"): + + with When("I grant insert privilege"): + node.query(f"GRANT INSERT({grant_columns}) ON {table_name} TO {role_name}") + + with And("I grant the role to a user"): + node.query(f"GRANT {role_name} TO {user_name}") + + if insert_columns_fail is not None: + with And("I insert into columns without insert privilege"): + exitcode, message = errors.not_enough_privileges(name=user_name) + + node.query(f"INSERT INTO {table_name} ({insert_columns_fail}) VALUES ({data_fail})", + settings=[("user",user_name)], exitcode=exitcode, message=message) + + with And("I insert into granted column"): + node.query(f"INSERT INTO {table_name} ({insert_columns_pass}) VALUES ({data_pass})", + settings=[("user",user_name)]) + + with Then("I check the insert functioned"): + input_equals_output = input_output_equality_check(node, insert_columns_pass, data_pass, table_name) + assert input_equals_output, error() + + if revoke_columns is not None: + with When("I revoke insert privilege from columns"): + node.query(f"REVOKE INSERT({revoke_columns}) ON {table_name} FROM {role_name}") + + with And("I insert into revoked columns"): + exitcode, message = errors.not_enough_privileges(name=user_name) + node.query(f"INSERT INTO {table_name} ({insert_columns_pass}) VALUES ({data_pass})", - settings=[("user",user_name)]) - with Then("I check the insert functioned"): - input_equals_output = input_output_equality_check(node, insert_columns_pass, data_pass, table_name) - assert input_equals_output, error() - if revoke_columns is not None: - with When("I revoke insert privilege from columns"): - node.query(f"REVOKE INSERT({revoke_columns}) ON {table_name} FROM {role_name}") - with And("I insert into revoked columns"): - exitcode, message = errors.not_enough_privileges(name=user_name) - node.query(f"INSERT INTO {table_name} ({insert_columns_pass}) VALUES ({data_pass})", - settings=[("user",user_name)], exitcode=exitcode, message=message) + settings=[("user",user_name)], exitcode=exitcode, message=message) @TestScenario @Requirements( @@ -272,29 +375,40 @@ def user_with_privilege_on_cluster(self, table_type, node=None): """ user_name = f"user_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + try: with Given("I have a user on a cluster"): node.query(f"CREATE USER OR REPLACE {user_name} ON CLUSTER sharded_cluster") + with When("I grant insert privilege on a cluster without the node with the table"): node.query(f"GRANT ON CLUSTER sharded_cluster23 INSERT ON {table_name} TO {user_name}") + with And("I insert into the table expecting a fail"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", settings=[("user",user_name)], exitcode=exitcode, message=message) + with And("I grant insert privilege on cluster including all nodes"): node.query(f"GRANT ON CLUSTER sharded_cluster INSERT ON {table_name} TO {user_name}") + with And("I revoke insert privilege on cluster without the node with the table"): node.query(f"REVOKE ON CLUSTER sharded_cluster23 INSERT ON {table_name} FROM {user_name}") + with And("I insert into the table"): node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", settings=[("user",user_name)]) + with And("I check that I can read inserted data"): output = node.query(f"SELECT d FROM {table_name} FORMAT JSONEachRow").output assert output == '{"d":"2020-01-01"}', error() + with And("I revoke insert privilege on cluster with all nodes"): node.query(f"REVOKE ON CLUSTER sharded_cluster INSERT ON {table_name} FROM {user_name}") + with Then("I insert into table expecting fail"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", settings=[("user",user_name)], @@ -314,33 +428,46 @@ def role_with_privilege_on_cluster(self, table_type, node=None): user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + try: with Given("I have a user on a cluster"): node.query(f"CREATE USER OR REPLACE {user_name} ON CLUSTER sharded_cluster") + with And("I have a role on a cluster"): node.query(f"CREATE ROLE OR REPLACE {role_name} ON CLUSTER sharded_cluster") + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") + with And("I grant insert privilege on a cluster without the node with the table"): node.query(f"GRANT ON CLUSTER sharded_cluster23 INSERT ON {table_name} TO {role_name}") + with And("I insert into the table expecting a fail"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", settings=[("user",user_name)], exitcode=exitcode, message=message) + with And("I grant insert privilege on cluster including all nodes"): node.query(f"GRANT ON CLUSTER sharded_cluster INSERT ON {table_name} TO {role_name}") + with And("I revoke insert privilege on cluster without the table node"): node.query(f"REVOKE ON CLUSTER sharded_cluster23 INSERT ON {table_name} FROM {role_name}") + with And("I insert into the table"): node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", settings=[("user",user_name)]) + with And("I check that I can read inserted data"): output = node.query(f"SELECT d FROM {table_name} FORMAT JSONEachRow").output assert output == '{"d":"2020-01-01"}', error() + with And("I revoke insert privilege on cluster with all nodes"): node.query(f"REVOKE ON CLUSTER sharded_cluster INSERT ON {table_name} FROM {role_name}") + with Then("I insert into table expecting fail"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')", settings=[("user",user_name)], @@ -357,7 +484,6 @@ def role_with_privilege_on_cluster(self, table_type, node=None): @Examples("table_type", [ (key,) for key in table_types.keys() ]) -@Flags(TE) @Name("insert") def feature(self, table_type, parallel=None, stress=None, node="clickhouse1"): """Check the RBAC functionality of INSERT. @@ -377,7 +503,10 @@ def feature(self, table_type, parallel=None, stress=None, node="clickhouse1"): pool = Pool(10) try: - for scenario in loads(current_module(), Scenario): - run_scenario(pool, tasks, Scenario(test=scenario, setup=instrument_clickhouse_server_log), {"table_type" : table_type}) + try: + for scenario in loads(current_module(), Scenario): + run_scenario(pool, tasks, Scenario(test=scenario, setup=instrument_clickhouse_server_log), {"table_type" : table_type}) + finally: + join(tasks) finally: - join(tasks) + pool.close() diff --git a/tests/testflows/rbac/tests/privileges/introspection.py b/tests/testflows/rbac/tests/privileges/introspection.py index f8d774902ab..a8d62cf8618 100644 --- a/tests/testflows/rbac/tests/privileges/introspection.py +++ b/tests/testflows/rbac/tests/privileges/introspection.py @@ -35,7 +35,7 @@ def addressToLine_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=addressToLine, flags=TE, + Suite(run=addressToLine, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in addressToLine.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -56,13 +56,14 @@ def addressToLine_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=addressToLine, flags=TE, + Suite(run=addressToLine, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in addressToLine.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("INTROSPECTION",), ("INTROSPECTION FUNCTIONS",), ("addressToLine",), @@ -80,7 +81,13 @@ def addressToLine(self, privilege, grant_target_name, user_name, node=None): with Scenario("addressToLine without privilege"): - with When("I check the user can't use addressToLine"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use addressToLine"): node.query(f"WITH addressToLine(toUInt64(dummy)) AS addr SELECT 1 WHERE addr = ''", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -116,7 +123,7 @@ def addressToSymbol_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=addressToSymbol, flags=TE, + Suite(run=addressToSymbol, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in addressToSymbol.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -137,13 +144,14 @@ def addressToSymbol_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=addressToSymbol, flags=TE, + Suite(run=addressToSymbol, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in addressToSymbol.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("INTROSPECTION",), ("INTROSPECTION FUNCTIONS",), ("addressToSymbol",), @@ -161,7 +169,13 @@ def addressToSymbol(self, privilege, grant_target_name, user_name, node=None): with Scenario("addressToSymbol without privilege"): - with When("I check the user can't use addressToSymbol"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use addressToSymbol"): node.query(f"WITH addressToSymbol(toUInt64(dummy)) AS addr SELECT 1 WHERE addr = ''", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -197,7 +211,7 @@ def demangle_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=demangle, flags=TE, + Suite(run=demangle, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in demangle.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -218,13 +232,14 @@ def demangle_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=demangle, flags=TE, + Suite(run=demangle, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in demangle.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("INTROSPECTION",), ("INTROSPECTION FUNCTIONS",), ("demangle",), @@ -242,7 +257,13 @@ def demangle(self, privilege, grant_target_name, user_name, node=None): with Scenario("demangle without privilege"): - with When("I check the user can't use demangle"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use demangle"): node.query(f"WITH demangle(toString(dummy)) AS addr SELECT 1 WHERE addr = ''", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -270,6 +291,8 @@ def demangle(self, privilege, grant_target_name, user_name, node=None): @Name("introspection") @Requirements( RQ_SRS_006_RBAC_Privileges_Introspection("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of INTROSPECTION. diff --git a/tests/testflows/rbac/tests/privileges/kill_mutation.py b/tests/testflows/rbac/tests/privileges/kill_mutation.py index 41d4a837480..9a27836cad4 100644 --- a/tests/testflows/rbac/tests/privileges/kill_mutation.py +++ b/tests/testflows/rbac/tests/privileges/kill_mutation.py @@ -14,8 +14,16 @@ def no_privilege(self, node=None): table_name = f"merge_tree_{getuid()}" with table(node, table_name): + with user(node, user_name): - with When("I attempt to kill mutation on table"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {user_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {user_name}") + + with Then("I attempt to kill mutation on table"): node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)]) with Scenario("kill mutation on cluster"): @@ -23,8 +31,16 @@ def no_privilege(self, node=None): table_name = f"merge_tree_{getuid()}" with table(node, table_name): + with user(node, user_name): - with When("I attempt to kill mutation on cluster"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {user_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {user_name}") + + with Then("I attempt to kill mutation on cluster"): node.query(f"KILL MUTATION ON CLUSTER sharded_cluster WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)]) @TestSuite @@ -40,9 +56,9 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(test=update, setup=instrument_clickhouse_server_log)(user_name=user_name, grant_target_name=user_name) - Suite(test=delete, setup=instrument_clickhouse_server_log)(user_name=user_name, grant_target_name=user_name) - Suite(test=drop_column, setup=instrument_clickhouse_server_log)(user_name=user_name, grant_target_name=user_name) + Suite(test=update)(user_name=user_name, grant_target_name=user_name) + Suite(test=delete)(user_name=user_name, grant_target_name=user_name) + Suite(test=drop_column)(user_name=user_name, grant_target_name=user_name) @TestSuite def privileges_granted_via_role(self, node=None): @@ -61,9 +77,9 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(test=update, setup=instrument_clickhouse_server_log)(user_name=user_name, grant_target_name=role_name) - Suite(test=delete, setup=instrument_clickhouse_server_log)(user_name=user_name, grant_target_name=role_name) - Suite(test=drop_column, setup=instrument_clickhouse_server_log)(user_name=user_name, grant_target_name=role_name) + Suite(test=update)(user_name=user_name, grant_target_name=role_name) + Suite(test=delete)(user_name=user_name, grant_target_name=role_name) + Suite(test=drop_column)(user_name=user_name, grant_target_name=role_name) @TestSuite @Requirements( @@ -78,6 +94,9 @@ def update(self, user_name, grant_target_name, node=None): if node is None: node = self.context.node + with Given("The user has no privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + with Scenario("KILL ALTER UPDATE without privilege"): table_name = f"merge_tree_{getuid()}" @@ -86,7 +105,13 @@ def update(self, user_name, grant_target_name, node=None): with Given("I have an ALTER UPDATE mutation"): node.query(f"ALTER TABLE {table_name} UPDATE a = x WHERE 1") - with When("I try to KILL MUTATION"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I try to KILL MUTATION"): node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)], exitcode=exitcode, message="Exception: Not allowed to kill mutation.") @@ -101,7 +126,7 @@ def update(self, user_name, grant_target_name, node=None): with When("I grant the ALTER UPDATE privilege"): node.query(f"GRANT ALTER UPDATE ON {table_name} TO {grant_target_name}") - with When("I try to KILL MUTATION"): + with Then("I try to KILL MUTATION"): node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)]) with Scenario("KILL ALTER UPDATE with revoked privilege"): @@ -118,10 +143,42 @@ def update(self, user_name, grant_target_name, node=None): with And("I revoke the ALTER UPDATE privilege"): node.query(f"REVOKE ALTER UPDATE ON {table_name} FROM {grant_target_name}") - with When("I try to KILL MUTATION"): + with Then("I try to KILL MUTATION"): node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)], exitcode=exitcode, message="Exception: Not allowed to kill mutation.") + with Scenario("KILL ALTER UPDATE with revoked ALL privilege"): + table_name = f"merge_tree_{getuid()}" + + with table(node, table_name): + + with Given("I have an ALTER UPDATE mutation"): + node.query(f"ALTER TABLE {table_name} UPDATE a = x WHERE 1") + + with When("I grant the ALTER UPDATE privilege"): + node.query(f"GRANT ALTER UPDATE ON {table_name} TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I try to KILL MUTATION"): + node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)], + exitcode=exitcode, message="Exception: Not allowed to kill mutation.") + + with Scenario("KILL ALTER UPDATE with ALL privilege"): + table_name = f"merge_tree_{getuid()}" + + with table(node, table_name): + + with Given("I have an ALTER UPDATE mutation"): + node.query(f"ALTER TABLE {table_name} UPDATE a = x WHERE 1") + + with When("I grant the ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I try to KILL MUTATION"): + node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)]) + @TestSuite @Requirements( RQ_SRS_006_RBAC_Privileges_KillMutation_AlterDelete("1.0") @@ -135,6 +192,9 @@ def delete(self, user_name, grant_target_name, node=None): if node is None: node = self.context.node + with Given("The user has no privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + with Scenario("KILL ALTER DELETE without privilege"): table_name = f"merge_tree_{getuid()}" @@ -143,7 +203,13 @@ def delete(self, user_name, grant_target_name, node=None): with Given("I have an ALTER DELETE mutation"): node.query(f"ALTER TABLE {table_name} DELETE WHERE 1") - with When("I try to KILL MUTATION"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I try to KILL MUTATION"): node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)], exitcode=exitcode, message="Exception: Not allowed to kill mutation.") @@ -158,7 +224,7 @@ def delete(self, user_name, grant_target_name, node=None): with When("I grant the ALTER DELETE privilege"): node.query(f"GRANT ALTER DELETE ON {table_name} TO {grant_target_name}") - with When("I try to KILL MUTATION"): + with Then("I try to KILL MUTATION"): node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)]) with Scenario("KILL ALTER DELETE with revoked privilege"): @@ -175,10 +241,42 @@ def delete(self, user_name, grant_target_name, node=None): with And("I revoke the ALTER DELETE privilege"): node.query(f"REVOKE ALTER DELETE ON {table_name} FROM {grant_target_name}") - with When("I try to KILL MUTATION"): + with Then("I try to KILL MUTATION"): node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)], exitcode=exitcode, message="Exception: Not allowed to kill mutation.") + with Scenario("KILL ALTER DELETE with revoked ALL privilege"): + table_name = f"merge_tree_{getuid()}" + + with table(node, table_name): + + with Given("I have an ALTER DELETE mutation"): + node.query(f"ALTER TABLE {table_name} DELETE WHERE 1") + + with When("I grant the ALTER DELETE privilege"): + node.query(f"GRANT ALTER DELETE ON {table_name} TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I try to KILL MUTATION"): + node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)], + exitcode=exitcode, message="Exception: Not allowed to kill mutation.") + + with Scenario("KILL ALTER DELETE with ALL privilege"): + table_name = f"merge_tree_{getuid()}" + + with table(node, table_name): + + with Given("I have an ALTER DELETE mutation"): + node.query(f"ALTER TABLE {table_name} DELETE WHERE 1") + + with When("I grant the ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I try to KILL MUTATION"): + node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)]) + @TestSuite @Requirements( RQ_SRS_006_RBAC_Privileges_KillMutation_AlterDropColumn("1.0") @@ -192,6 +290,9 @@ def drop_column(self, user_name, grant_target_name, node=None): if node is None: node = self.context.node + with Given("The user has no privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + with Scenario("KILL ALTER DROP COLUMN without privilege"): table_name = f"merge_tree_{getuid()}" @@ -200,7 +301,13 @@ def drop_column(self, user_name, grant_target_name, node=None): with Given("I have an ALTER DROP COLUMN mutation"): node.query(f"ALTER TABLE {table_name} DROP COLUMN x") - with When("I try to KILL MUTATION"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I try to KILL MUTATION"): node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)], exitcode=exitcode, message="Exception: Not allowed to kill mutation.") @@ -215,7 +322,7 @@ def drop_column(self, user_name, grant_target_name, node=None): with When("I grant the ALTER DROP COLUMN privilege"): node.query(f"GRANT ALTER DROP COLUMN ON {table_name} TO {grant_target_name}") - with When("I try to KILL MUTATION"): + with Then("I try to KILL MUTATION"): node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)]) with Scenario("KILL ALTER DROP COLUMN with revoked privilege"): @@ -232,13 +339,47 @@ def drop_column(self, user_name, grant_target_name, node=None): with And("I revoke the ALTER DROP COLUMN privilege"): node.query(f"REVOKE ALTER DROP COLUMN ON {table_name} FROM {grant_target_name}") - with When("I try to KILL MUTATION"): + with Then("I try to KILL MUTATION"): node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)], exitcode=exitcode, message="Exception: Not allowed to kill mutation.") + with Scenario("KILL ALTER DROP COLUMN with revoked privilege"): + table_name = f"merge_tree_{getuid()}" + + with table(node, table_name): + + with Given("I have an ALTER DROP COLUMN mutation"): + node.query(f"ALTER TABLE {table_name} DROP COLUMN x") + + with When("I grant the ALTER DROP COLUMN privilege"): + node.query(f"GRANT ALTER DROP COLUMN ON {table_name} TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I try to KILL MUTATION"): + node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)], + exitcode=exitcode, message="Exception: Not allowed to kill mutation.") + + with Scenario("KILL ALTER DROP COLUMN with ALL privilege"): + table_name = f"merge_tree_{getuid()}" + + with table(node, table_name): + + with Given("I have an ALTER DROP COLUMN mutation"): + node.query(f"ALTER TABLE {table_name} DROP COLUMN x") + + with When("I grant the ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I try to KILL MUTATION"): + node.query(f"KILL MUTATION WHERE database = 'default' AND table = '{table_name}'", settings = [("user", user_name)]) + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_KillMutation("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("kill mutation") def feature(self, node="clickhouse1", stress=None, parallel=None): diff --git a/tests/testflows/rbac/tests/privileges/kill_query.py b/tests/testflows/rbac/tests/privileges/kill_query.py index 161ee7b35e0..d1f96e23fd8 100644 --- a/tests/testflows/rbac/tests/privileges/kill_query.py +++ b/tests/testflows/rbac/tests/privileges/kill_query.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute KILL QUERY with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,20 +32,27 @@ def privilege_check(grant_target_name, user_name, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): - with When("I attempt to kill a query without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to kill a query without privilege"): node.query(f"KILL QUERY WHERE user ='default'", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): + with When("I grant kill query privilege"): node.query(f"GRANT KILL QUERY TO {grant_target_name}") with Then("I attempt to kill a query"): node.query(f"KILL QUERY WHERE 1", settings = [("user", user_name)]) - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): with When("I grant the kill query privilege"): node.query(f"GRANT KILL QUERY TO {grant_target_name}") @@ -57,7 +64,19 @@ def privilege_check(grant_target_name, user_name, node=None): node.query(f"KILL QUERY WHERE 1", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("execute on cluster", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked ALL privilege"): + + with When("I grant the kill query privilege"): + node.query(f"GRANT KILL QUERY TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to kill a query"): + node.query(f"KILL QUERY WHERE 1", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + with Scenario("execute on cluster"): with When("I grant the truncate privilege"): node.query(f"GRANT KILL QUERY TO {grant_target_name}") @@ -65,9 +84,22 @@ def privilege_check(grant_target_name, user_name, node=None): with Then("I attempt to kill a query"): node.query(f"KILL QUERY ON CLUSTER WHERE 1'", settings = [("user", user_name)]) + with Scenario("user with ALL privilege"): + + with When("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with And("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* ON {grant_target_name}") + + with Then("I attempt to kill a query"): + node.query(f"KILL QUERY WHERE 1", settings = [("user", user_name)]) + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_KillQuery("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Name("kill query") def feature(self, node="clickhouse1", stress=None, parallel=None): @@ -80,5 +112,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): if stress is not None: self.context.stress = stress - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role() diff --git a/tests/testflows/rbac/tests/privileges/optimize.py b/tests/testflows/rbac/tests/privileges/optimize.py index b0e8b69e372..7d3f41a43b4 100644 --- a/tests/testflows/rbac/tests/privileges/optimize.py +++ b/tests/testflows/rbac/tests/privileges/optimize.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, table_type, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute OPTIMIZE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, table_type=table_type, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,16 +32,22 @@ def privilege_check(grant_target_name, user_name, table_type, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): table_name = f"merge_tree_{getuid()}" with table(node, table_name, table_type): - with When("I attempt to optimize a table without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to optimize a table without privilege"): node.query(f"OPTIMIZE TABLE {table_name} FINAL", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): table_name = f"merge_tree_{getuid()}" with table(node, table_name, table_type): @@ -52,7 +58,7 @@ def privilege_check(grant_target_name, user_name, table_type, node=None): with Then("I attempt to optimize a table"): node.query(f"OPTIMIZE TABLE {table_name}", settings = [("user", user_name)]) - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): table_name = f"merge_tree_{getuid()}" with table(node, table_name, table_type): @@ -67,7 +73,22 @@ def privilege_check(grant_target_name, user_name, table_type, node=None): node.query(f"OPTIMIZE TABLE {table_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("execute on cluster", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked ALL privilege"): + table_name = f"merge_tree_{getuid()}" + + with table(node, table_name, table_type): + + with When("I grant the optimize privilege"): + node.query(f"GRANT OPTIMIZE ON {table_name} TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to optimize a table"): + node.query(f"OPTIMIZE TABLE {table_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + with Scenario("execute on cluster"): table_name = f"merge_tree_{getuid()}" try: @@ -84,9 +105,24 @@ def privilege_check(grant_target_name, user_name, table_type, node=None): with Finally("I drop the table from the cluster"): node.query(f"DROP TABLE IF EXISTS {table_name} ON CLUSTER sharded_cluster") + with Scenario("user with ALL privilege"): + table_name = f"merge_tree_{getuid()}" + + with table(node, table_name, table_type): + + with When("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with And("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to optimize a table"): + node.query(f"OPTIMIZE TABLE {table_name}", settings = [("user", user_name)]) @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_Optimize("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() @@ -109,5 +145,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): continue with Example(str(example)): - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role(table_type=table_type) diff --git a/tests/testflows/rbac/tests/privileges/public_tables.py b/tests/testflows/rbac/tests/privileges/public_tables.py index 98077438946..ed17c1a77ea 100755 --- a/tests/testflows/rbac/tests/privileges/public_tables.py +++ b/tests/testflows/rbac/tests/privileges/public_tables.py @@ -95,5 +95,5 @@ def sensitive_tables(self, node=None): def feature(self, node="clickhouse1"): self.context.node = self.context.cluster.node(node) - Scenario(run=public_tables, setup=instrument_clickhouse_server_log, flags=TE) - Scenario(run=sensitive_tables, setup=instrument_clickhouse_server_log, flags=TE) \ No newline at end of file + Scenario(run=public_tables, setup=instrument_clickhouse_server_log) + Scenario(run=sensitive_tables, setup=instrument_clickhouse_server_log) diff --git a/tests/testflows/rbac/tests/privileges/role_admin.py b/tests/testflows/rbac/tests/privileges/role_admin.py index 955b0fcd258..8deea7874cd 100644 --- a/tests/testflows/rbac/tests/privileges/role_admin.py +++ b/tests/testflows/rbac/tests/privileges/role_admin.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(test=role_admin, flags=TE)(grant_target_name=user_name, user_name=user_name) + Suite(test=role_admin)(grant_target_name=user_name, user_name=user_name) @TestSuite def privileges_granted_via_role(self, node=None): @@ -35,7 +35,7 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(test=role_admin, flags=TE)(grant_target_name=role_name, user_name=user_name) + Suite(test=role_admin)(grant_target_name=role_name, user_name=user_name) @TestSuite def role_admin(self, grant_target_name, user_name, node=None): @@ -52,7 +52,13 @@ def role_admin(self, grant_target_name, user_name, node=None): with user(node, target_user_name), role(node, role_admin_name): - with When("I check the user can't grant a role"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't grant a role"): node.query(f"GRANT {role_admin_name} TO {target_user_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -105,10 +111,40 @@ def role_admin(self, grant_target_name, user_name, node=None): node.query(f"GRANT {role_admin_name} TO {target_user_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) + with Scenario("Grant role with revoked ALL privilege"): + role_admin_name = f"role_admin_{getuid()}" + target_user_name = f"target_user_{getuid()}" + + with user(node, target_user_name), role(node, role_admin_name): + + with When(f"I grant ROLE ADMIN"): + node.query(f"GRANT ROLE ADMIN ON *.* TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I check the user cannot grant a role"): + node.query(f"GRANT {role_admin_name} TO {target_user_name}", settings=[("user",user_name)], + exitcode=exitcode, message=message) + + with Scenario("Grant role with ALL privilege"): + role_admin_name = f"role_admin_{getuid()}" + target_user_name = f"target_user_{getuid()}" + + with user(node, target_user_name), role(node, role_admin_name): + + with When(f"I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I check the user can grant a role"): + node.query(f"GRANT {role_admin_name} TO {target_user_name}", settings = [("user", f"{user_name}")]) + @TestFeature @Name("role admin") @Requirements( RQ_SRS_006_RBAC_Privileges_RoleAdmin("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of ROLE ADMIN. diff --git a/tests/testflows/rbac/tests/privileges/select.py b/tests/testflows/rbac/tests/privileges/select.py index e58dd8184d2..036ea944ae1 100755 --- a/tests/testflows/rbac/tests/privileges/select.py +++ b/tests/testflows/rbac/tests/privileges/select.py @@ -9,17 +9,31 @@ from rbac.helper.common import * import rbac.helper.errors as errors @TestScenario +@Requirements( + RQ_SRS_006_RBAC_Privileges_None("1.0") +) def without_privilege(self, table_type, node=None): """Check that user without select privilege on a table is not able to select on that table. """ user_name = f"user_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with user(node, user_name): - with When("I run SELECT without privilege"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {user_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {user_name}") + + with Then("I run SELECT without privilege"): exitcode, message = errors.not_enough_privileges(name=user_name) + node.query(f"SELECT * FROM {table_name}", settings = [("user",user_name)], exitcode=exitcode, message=message) @@ -32,16 +46,52 @@ def user_with_privilege(self, table_type, node=None): """ user_name = f"user_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with Given("I have some data inserted into table"): node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')") + with user(node, user_name): + with When("I grant privilege"): node.query(f"GRANT SELECT ON {table_name} TO {user_name}") + with Then("I verify SELECT command"): user_select = node.query(f"SELECT d FROM {table_name}", settings = [("user",user_name)]) + + default = node.query(f"SELECT d FROM {table_name}") + assert user_select.output == default.output, error() + +@TestScenario +@Requirements( + RQ_SRS_006_RBAC_Privileges_All("1.0") +) +def user_with_all_privilege(self, table_type, node=None): + """Check that user can select from a table if have ALL privilege. + """ + user_name = f"user_{getuid()}" + table_name = f"table_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name, table_type): + + with Given("I have some data inserted into table"): + node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')") + + with user(node, user_name): + + with When("I grant privilege"): + node.query(f"GRANT ALL ON *.* TO {user_name}") + + with Then("I verify SELECT command"): + user_select = node.query(f"SELECT d FROM {table_name}", settings = [("user",user_name)]) + default = node.query(f"SELECT d FROM {table_name}") assert user_select.output == default.output, error() @@ -55,15 +105,47 @@ def user_with_revoked_privilege(self, table_type, node=None): """ user_name = f"user_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with user(node, user_name): + with When("I grant privilege"): node.query(f"GRANT SELECT ON {table_name} TO {user_name}") + with And("I revoke privilege"): node.query(f"REVOKE SELECT ON {table_name} FROM {user_name}") - with And("I use SELECT, throws exception"): + + with Then("I use SELECT, throws exception"): + exitcode, message = errors.not_enough_privileges(name=user_name) + node.query(f"SELECT * FROM {table_name}", settings = [("user",user_name)], + exitcode=exitcode, message=message) + +@TestScenario +def user_with_revoked_all_privilege(self, table_type, node=None): + """Check that user is unable to select from a table after ALL privilege + on that table has been revoked from the user. + """ + user_name = f"user_{getuid()}" + table_name = f"table_{getuid()}" + + if node is None: + node = self.context.node + + with table(node, table_name, table_type): + + with user(node, user_name): + + with When("I grant privilege"): + node.query(f"GRANT SELECT ON {table_name} TO {user_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {user_name}") + + with Then("I use SELECT, throws exception"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"SELECT * FROM {table_name}", settings = [("user",user_name)], exitcode=exitcode, message=message) @@ -90,25 +172,35 @@ def user_column_privileges(self, grant_columns, select_columns_pass, data_pass, """ user_name = f"user_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type), user(node, user_name): + with Given("The table has some data on some columns"): node.query(f"INSERT INTO {table_name} ({select_columns_pass}) VALUES ({data_pass})") + with When("I grant select privilege"): node.query(f"GRANT SELECT({grant_columns}) ON {table_name} TO {user_name}") + if select_columns_fail is not None: + with And("I select from not granted column"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"SELECT ({select_columns_fail}) FROM {table_name}", settings = [("user",user_name)], exitcode=exitcode, message=message) + with Then("I select from granted column, verify correct result"): user_select = node.query(f"SELECT ({select_columns_pass}) FROM {table_name}", settings = [("user",user_name)]) default = node.query(f"SELECT ({select_columns_pass}) FROM {table_name}") assert user_select.output == default.output + if revoke_columns is not None: + with When("I revoke select privilege for columns from user"): node.query(f"REVOKE SELECT({revoke_columns}) ON {table_name} FROM {user_name}") + with And("I select from revoked columns"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"SELECT ({select_columns_pass}) FROM {table_name}", settings = [("user",user_name)], exitcode=exitcode, message=message) @@ -124,17 +216,25 @@ def role_with_privilege(self, table_type, node=None): user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with Given("I have some data inserted into table"): node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')") + with user(node, user_name): + with role(node, role_name): + with When("I grant select privilege to a role"): node.query(f"GRANT SELECT ON {table_name} TO {role_name}") + with And("I grant role to the user"): node.query(f"GRANT {role_name} TO {user_name}") + with Then("I verify SELECT command"): user_select = node.query(f"SELECT d FROM {table_name}", settings = [("user",user_name)]) default = node.query(f"SELECT d FROM {table_name}") @@ -151,16 +251,23 @@ def role_with_revoked_privilege(self, table_type, node=None): user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with user(node, user_name), role(node, role_name): + with When("I grant privilege to a role"): node.query(f"GRANT SELECT ON {table_name} TO {role_name}") + with And("I grant the role to a user"): node.query(f"GRANT {role_name} TO {user_name}") + with And("I revoke privilege from the role"): node.query(f"REVOKE SELECT ON {table_name} FROM {role_name}") + with And("I select from the table"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"SELECT * FROM {table_name}", settings = [("user",user_name)], @@ -174,16 +281,23 @@ def user_with_revoked_role(self, table_type, node=None): user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with user(node, user_name), role(node, role_name): + with When("I grant privilege to a role"): node.query(f"GRANT SELECT ON {table_name} TO {role_name}") + with And("I grant the role to a user"): node.query(f"GRANT {role_name} TO {user_name}") + with And("I revoke the role from the user"): node.query(f"REVOKE {role_name} FROM {user_name}") + with And("I select from the table"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"SELECT * FROM {table_name}", settings = [("user",user_name)], @@ -212,28 +326,39 @@ def role_column_privileges(self, grant_columns, select_columns_pass, data_pass, user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): + with Given("The table has some data on some columns"): node.query(f"INSERT INTO {table_name} ({select_columns_pass}) VALUES ({data_pass})") + with user(node, user_name), role(node, role_name): + with When("I grant select privilege"): node.query(f"GRANT SELECT({grant_columns}) ON {table_name} TO {role_name}") + with And("I grant the role to a user"): node.query(f"GRANT {role_name} TO {user_name}") + if select_columns_fail is not None: with And("I select from not granted column"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"SELECT ({select_columns_fail}) FROM {table_name}", settings = [("user",user_name)], exitcode=exitcode, message=message) + with Then("I verify SELECT command"): user_select = node.query(f"SELECT d FROM {table_name}", settings = [("user",user_name)]) default = node.query(f"SELECT d FROM {table_name}") assert user_select.output == default.output, error() + if revoke_columns is not None: + with When("I revoke select privilege for columns from role"): node.query(f"REVOKE SELECT({revoke_columns}) ON {table_name} FROM {role_name}") + with And("I select from revoked columns"): exitcode, message = errors.not_enough_privileges(name=user_name) node.query(f"SELECT ({select_columns_pass}) FROM {table_name}", @@ -250,20 +375,26 @@ def user_with_privilege_on_cluster(self, table_type, node=None): user_name = f"user_{getuid()}" role_name = f"role_{getuid()}" table_name = f"table_{getuid()}" + if node is None: node = self.context.node + with table(node, table_name, table_type): try: with Given("I have some data inserted into table"): node.query(f"INSERT INTO {table_name} (d) VALUES ('2020-01-01')") + with Given("I have a user on a cluster"): node.query(f"CREATE USER OR REPLACE {user_name} ON CLUSTER sharded_cluster") + with When("I grant select privilege on a cluster"): node.query(f"GRANT ON CLUSTER sharded_cluster SELECT ON {table_name} TO {user_name}") + with Then("I verify SELECT command"): user_select = node.query(f"SELECT d FROM {table_name}", settings = [("user",user_name)]) default = node.query(f"SELECT d FROM {table_name}") assert user_select.output == default.output, error() + finally: with Finally("I drop the user"): node.query(f"DROP USER {user_name} ON CLUSTER sharded_cluster") @@ -291,7 +422,10 @@ def feature(self, table_type, parallel=None, stress=None, node="clickhouse1"): pool = Pool(10) try: - for scenario in loads(current_module(), Scenario): - run_scenario(pool, tasks, Scenario(test=scenario, setup=instrument_clickhouse_server_log), {"table_type" : table_type}) + try: + for scenario in loads(current_module(), Scenario): + run_scenario(pool, tasks, Scenario(test=scenario, setup=instrument_clickhouse_server_log), {"table_type" : table_type}) + finally: + join(tasks) finally: - join(tasks) + pool.close() diff --git a/tests/testflows/rbac/tests/privileges/show/show_columns.py b/tests/testflows/rbac/tests/privileges/show/show_columns.py index 996663cdcbc..108200e7a57 100644 --- a/tests/testflows/rbac/tests/privileges/show/show_columns.py +++ b/tests/testflows/rbac/tests/privileges/show/show_columns.py @@ -18,7 +18,7 @@ def describe_with_privilege_granted_directly(self, node=None): with user(node, f"{user_name}"): table_name = f"table_name_{getuid()}" - Suite(test=describe, setup=instrument_clickhouse_server_log)(grant_target_name=user_name, user_name=user_name, table_name=table_name) + Suite(test=describe)(grant_target_name=user_name, user_name=user_name, table_name=table_name) @TestSuite def describe_with_privilege_granted_via_role(self, node=None): @@ -37,7 +37,7 @@ def describe_with_privilege_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(test=describe, setup=instrument_clickhouse_server_log)(grant_target_name=role_name, user_name=user_name, table_name=table_name) + Suite(test=describe)(grant_target_name=role_name, user_name=user_name, table_name=table_name) @TestSuite @Requirements( @@ -54,11 +54,19 @@ def describe(self, grant_target_name, user_name, table_name, node=None): with table(node, table_name): with Scenario("DESCRIBE table without privilege"): - with When(f"I attempt to DESCRIBE {table_name}"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then(f"I attempt to DESCRIBE {table_name}"): node.query(f"DESCRIBE {table_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) with Scenario("DESCRIBE with privilege"): + with When(f"I grant SHOW COLUMNS on the table"): node.query(f"GRANT SHOW COLUMNS ON {table_name} TO {grant_target_name}") @@ -66,6 +74,7 @@ def describe(self, grant_target_name, user_name, table_name, node=None): node.query(f"DESCRIBE TABLE {table_name}", settings=[("user",user_name)]) with Scenario("DESCRIBE with revoked privilege"): + with When(f"I grant SHOW COLUMNS on the table"): node.query(f"GRANT SHOW COLUMNS ON {table_name} TO {grant_target_name}") @@ -76,6 +85,26 @@ def describe(self, grant_target_name, user_name, table_name, node=None): node.query(f"DESCRIBE {table_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) + with Scenario("DESCRIBE with revoked ALL privilege"): + + with When(f"I grant SHOW COLUMNS on the table"): + node.query(f"GRANT SHOW COLUMNS ON {table_name} TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then(f"I attempt to DESCRIBE {table_name}"): + node.query(f"DESCRIBE {table_name}", settings=[("user",user_name)], + exitcode=exitcode, message=message) + + with Scenario("DESCRIBE with ALL privilege"): + + with When(f"I grant SHOW COLUMNS on the table"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then(f"I attempt to DESCRIBE {table_name}"): + node.query(f"DESCRIBE TABLE {table_name}", settings=[("user",user_name)]) + @TestSuite def show_create_with_privilege_granted_directly(self, node=None): """Check that user is able to execute SHOW CREATE on a table if and only if @@ -89,7 +118,7 @@ def show_create_with_privilege_granted_directly(self, node=None): with user(node, f"{user_name}"): table_name = f"table_name_{getuid()}" - Suite(test=show_create, setup=instrument_clickhouse_server_log)(grant_target_name=user_name, user_name=user_name, table_name=table_name) + Suite(test=show_create)(grant_target_name=user_name, user_name=user_name, table_name=table_name) @TestSuite def show_create_with_privilege_granted_via_role(self, node=None): @@ -108,7 +137,7 @@ def show_create_with_privilege_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(test=show_create, setup=instrument_clickhouse_server_log)(grant_target_name=role_name, user_name=user_name, table_name=table_name) + Suite(test=show_create)(grant_target_name=role_name, user_name=user_name, table_name=table_name) @TestSuite @Requirements( @@ -125,11 +154,19 @@ def show_create(self, grant_target_name, user_name, table_name, node=None): with table(node, table_name): with Scenario("SHOW CREATE without privilege"): - with When(f"I attempt to SHOW CREATE {table_name}"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then(f"I attempt to SHOW CREATE {table_name}"): node.query(f"SHOW CREATE TABLE {table_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) with Scenario("SHOW CREATE with privilege"): + with When(f"I grant SHOW COLUMNS on the table"): node.query(f"GRANT SHOW COLUMNS ON {table_name} TO {grant_target_name}") @@ -137,6 +174,7 @@ def show_create(self, grant_target_name, user_name, table_name, node=None): node.query(f"SHOW CREATE TABLE {table_name}", settings=[("user",user_name)]) with Scenario("SHOW CREATE with revoked privilege"): + with When(f"I grant SHOW COLUMNS on the table"): node.query(f"GRANT SHOW COLUMNS ON {table_name} TO {grant_target_name}") @@ -147,10 +185,20 @@ def show_create(self, grant_target_name, user_name, table_name, node=None): node.query(f"SHOW CREATE TABLE {table_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) + with Scenario("SHOW CREATE with ALL privilege"): + + with When(f"I grant SHOW COLUMNS on the table"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then(f"I attempt to SHOW CREATE {table_name}"): + node.query(f"SHOW CREATE TABLE {table_name}", settings=[("user",user_name)]) + @TestFeature @Name("show columns") @Requirements( - RQ_SRS_006_RBAC_ShowColumns_Privilege("1.0") + RQ_SRS_006_RBAC_ShowColumns_Privilege("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SHOW COLUMNS. diff --git a/tests/testflows/rbac/tests/privileges/show/show_databases.py b/tests/testflows/rbac/tests/privileges/show/show_databases.py index 27d10ef2b73..39a46947afe 100644 --- a/tests/testflows/rbac/tests/privileges/show/show_databases.py +++ b/tests/testflows/rbac/tests/privileges/show/show_databases.py @@ -20,7 +20,7 @@ def dict_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): db_name = f"db_name_{getuid()}" - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name db_name", [ tuple(list(row)+[user_name,user_name,db_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -44,13 +44,14 @@ def dict_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name db_name", [ tuple(list(row)+[role_name,user_name,db_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SHOW","*.*"), ("SHOW DATABASES","db"), ("CREATE DATABASE","db"), @@ -65,9 +66,9 @@ def check_privilege(self, privilege, on, grant_target_name, user_name, db_name, on = on.replace("db", f"{db_name}") - Suite(test=show_db, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, db_name=db_name) - Suite(test=use, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, db_name=db_name) - Suite(test=show_create, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, db_name=db_name) + Suite(test=show_db)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, db_name=db_name) + Suite(test=use)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, db_name=db_name) + Suite(test=show_create)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, db_name=db_name) @TestSuite @Requirements( @@ -83,14 +84,23 @@ def show_db(self, privilege, on, grant_target_name, user_name, db_name, node=Non try: with Given("I have a database"): + node.query(f"CREATE DATABASE {db_name}") with Scenario("SHOW DATABASES without privilege"): - with When("I check the user doesn't see the database"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user doesn't see the database"): output = node.query("SHOW DATABASES", settings = [("user", f"{user_name}")]).output assert output == '', error() with Scenario("SHOW DATABASES with privilege"): + with When(f"I grant {privilege} on the database"): node.query(f"GRANT {privilege} ON {db_name}.* TO {grant_target_name}") @@ -98,6 +108,7 @@ def show_db(self, privilege, on, grant_target_name, user_name, db_name, node=Non output = node.query("SHOW DATABASES", settings = [("user", f"{user_name}")], message = f'{db_name}') with Scenario("SHOW DATABASES with revoked privilege"): + with When(f"I grant {privilege} on the database"): node.query(f"GRANT {privilege} ON {db_name}.* TO {grant_target_name}") @@ -130,11 +141,19 @@ def use(self, privilege, on, grant_target_name, user_name, db_name, node=None): node.query(f"CREATE DATABASE {db_name}") with Scenario("USE without privilege"): - with When(f"I attempt to USE {db_name}"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then(f"I attempt to USE {db_name}"): node.query(f"USE {db_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) with Scenario("USE with privilege"): + with When(f"I grant {privilege} on the database"): node.query(f"GRANT {privilege} ON {db_name}.* TO {grant_target_name}") @@ -142,6 +161,7 @@ def use(self, privilege, on, grant_target_name, user_name, db_name, node=None): node.query(f"USE {db_name}", settings=[("user",user_name)]) with Scenario("USE with revoked privilege"): + with When(f"I grant {privilege} on the database"): node.query(f"GRANT {privilege} ON {db_name}.* TO {grant_target_name}") @@ -174,11 +194,19 @@ def show_create(self, privilege, on, grant_target_name, user_name, db_name, node node.query(f"CREATE DATABASE {db_name}") with Scenario("SHOW CREATE without privilege"): - with When(f"I attempt to SHOW CREATE {db_name}"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then(f"I attempt to SHOW CREATE {db_name}"): node.query(f"SHOW CREATE DATABASE {db_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) with Scenario("SHOW CREATE with privilege"): + with When(f"I grant {privilege} on the database"): node.query(f"GRANT {privilege} ON {db_name}.* TO {grant_target_name}") @@ -186,6 +214,7 @@ def show_create(self, privilege, on, grant_target_name, user_name, db_name, node node.query(f"SHOW CREATE DATABASE {db_name}", settings=[("user",user_name)]) with Scenario("SHOW CREATE with revoked privilege"): + with When(f"I grant {privilege} on the database"): node.query(f"GRANT {privilege} ON {db_name}.* TO {grant_target_name}") @@ -203,7 +232,9 @@ def show_create(self, privilege, on, grant_target_name, user_name, db_name, node @TestFeature @Name("show databases") @Requirements( - RQ_SRS_006_RBAC_ShowDatabases_Privilege("1.0") + RQ_SRS_006_RBAC_ShowDatabases_Privilege("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SHOW DATABASES. diff --git a/tests/testflows/rbac/tests/privileges/show/show_dictionaries.py b/tests/testflows/rbac/tests/privileges/show/show_dictionaries.py index ec5617af904..5b717b5f47c 100644 --- a/tests/testflows/rbac/tests/privileges/show/show_dictionaries.py +++ b/tests/testflows/rbac/tests/privileges/show/show_dictionaries.py @@ -20,7 +20,7 @@ def dict_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): dict_name = f"dict_name_{getuid()}" - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name dict_name", [ tuple(list(row)+[user_name,user_name,dict_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -44,13 +44,14 @@ def dict_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name dict_name", [ tuple(list(row)+[role_name,user_name,dict_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SHOW","*.*"), ("SHOW DICTIONARIES","dict"), ("CREATE DICTIONARY","dict"), @@ -65,9 +66,9 @@ def check_privilege(self, privilege, on, grant_target_name, user_name, dict_name on = on.replace("dict", f"{dict_name}") - Suite(test=show_dict, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, dict_name=dict_name) - Suite(test=exists, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, dict_name=dict_name) - Suite(test=show_create, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, dict_name=dict_name) + Suite(test=show_dict)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, dict_name=dict_name) + Suite(test=exists)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, dict_name=dict_name) + Suite(test=show_create)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, dict_name=dict_name) @TestSuite @Requirements( @@ -87,7 +88,14 @@ def show_dict(self, privilege, on, grant_target_name, user_name, dict_name, node node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)") with Scenario("SHOW DICTIONARIES without privilege"): - with When("I check the user doesn't see the dictionary"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user doesn't see the dictionary"): output = node.query("SHOW DICTIONARIES", settings = [("user", f"{user_name}")]).output assert output == '', error() @@ -131,7 +139,14 @@ def exists(self, privilege, on, grant_target_name, user_name, dict_name, node=No node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)") with Scenario("EXISTS without privilege"): - with When(f"I check if {dict_name} EXISTS"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then(f"I check if {dict_name} EXISTS"): node.query(f"EXISTS {dict_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -175,7 +190,14 @@ def show_create(self, privilege, on, grant_target_name, user_name, dict_name, no node.query(f"CREATE DICTIONARY {dict_name}(x Int32, y Int32) PRIMARY KEY x LAYOUT(FLAT()) SOURCE(CLICKHOUSE()) LIFETIME(0)") with Scenario("SHOW CREATE without privilege"): - with When(f"I attempt to SHOW CREATE {dict_name}"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then(f"I attempt to SHOW CREATE {dict_name}"): node.query(f"SHOW CREATE DICTIONARY {dict_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -205,6 +227,8 @@ def show_create(self, privilege, on, grant_target_name, user_name, dict_name, no @Name("show dictionaries") @Requirements( RQ_SRS_006_RBAC_ShowDictionaries_Privilege("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SHOW DICTIONARIES. diff --git a/tests/testflows/rbac/tests/privileges/show/show_quotas.py b/tests/testflows/rbac/tests/privileges/show/show_quotas.py index d84b5192677..20476ae759b 100644 --- a/tests/testflows/rbac/tests/privileges/show/show_quotas.py +++ b/tests/testflows/rbac/tests/privileges/show/show_quotas.py @@ -29,7 +29,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -50,13 +50,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("SHOW ACCESS",), ("SHOW QUOTAS",), @@ -69,8 +70,8 @@ def check_privilege(self, privilege, grant_target_name, user_name, node=None): if node is None: node = self.context.node - Suite(test=show_quotas, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) - Suite(test=show_create, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=show_quotas)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=show_create)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) @TestSuite @Requirements( @@ -86,7 +87,13 @@ def show_quotas(self, privilege, grant_target_name, user_name, node=None): with Scenario("SHOW QUOTAS without privilege"): - with When("I check the user can't use SHOW QUOTAS"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SHOW QUOTAS"): node.query(f"SHOW QUOTAS", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -127,7 +134,13 @@ def show_create(self, privilege, grant_target_name, user_name, node=None): with quota(node, target_quota_name): - with When("I check the user can't use SHOW CREATE QUOTA"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SHOW CREATE QUOTA"): node.query(f"SHOW CREATE QUOTA {target_quota_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -161,6 +174,8 @@ def show_create(self, privilege, grant_target_name, user_name, node=None): @Name("show quotas") @Requirements( RQ_SRS_006_RBAC_ShowQuotas_Privilege("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SHOW QUOTAS. diff --git a/tests/testflows/rbac/tests/privileges/show/show_roles.py b/tests/testflows/rbac/tests/privileges/show/show_roles.py index 3106e1c5df3..14d038102dd 100644 --- a/tests/testflows/rbac/tests/privileges/show/show_roles.py +++ b/tests/testflows/rbac/tests/privileges/show/show_roles.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("SHOW ACCESS",), ("SHOW ROLES",), @@ -57,8 +58,8 @@ def check_privilege(self, privilege, grant_target_name, user_name, node=None): if node is None: node = self.context.node - Suite(test=show_roles, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) - Suite(test=show_create, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=show_roles)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=show_create)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) @TestSuite @Requirements( @@ -74,7 +75,13 @@ def show_roles(self, privilege, grant_target_name, user_name, node=None): with Scenario("SHOW ROLES without privilege"): - with When("I check the user can't use SHOW ROLES"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SHOW ROLES"): node.query(f"SHOW ROLES", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -115,7 +122,13 @@ def show_create(self, privilege, grant_target_name, user_name, node=None): with role(node, target_role_name): - with When("I check the user can't use SHOW CREATE ROLE"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SHOW CREATE ROLE"): node.query(f"SHOW CREATE ROLE {target_role_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -149,6 +162,8 @@ def show_create(self, privilege, grant_target_name, user_name, node=None): @Name("show roles") @Requirements( RQ_SRS_006_RBAC_ShowRoles_Privilege("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SHOW ROLES. diff --git a/tests/testflows/rbac/tests/privileges/show/show_row_policies.py b/tests/testflows/rbac/tests/privileges/show/show_row_policies.py index cfa25284cee..789c4c95223 100644 --- a/tests/testflows/rbac/tests/privileges/show/show_row_policies.py +++ b/tests/testflows/rbac/tests/privileges/show/show_row_policies.py @@ -29,7 +29,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -50,13 +50,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("SHOW ACCESS",), ("SHOW ROW POLICIES",), @@ -71,8 +72,8 @@ def check_privilege(self, privilege, grant_target_name, user_name, node=None): if node is None: node = self.context.node - Suite(test=show_row_policies, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) - Suite(test=show_create, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=show_row_policies)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=show_create)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) @TestSuite @Requirements( @@ -88,7 +89,13 @@ def show_row_policies(self, privilege, grant_target_name, user_name, node=None): with Scenario("SHOW ROW POLICIES without privilege"): - with When("I check the user can't use SHOW ROW POLICIES"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SHOW ROW POLICIES"): node.query(f"SHOW ROW POLICIES", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -130,7 +137,13 @@ def show_create(self, privilege, grant_target_name, user_name, node=None): with row_policy(node, target_row_policy_name, table_name): - with When("I check the user can't use SHOW CREATE ROW POLICY"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SHOW CREATE ROW POLICY"): node.query(f"SHOW CREATE ROW POLICY {target_row_policy_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -166,6 +179,8 @@ def show_create(self, privilege, grant_target_name, user_name, node=None): @Name("show row policies") @Requirements( RQ_SRS_006_RBAC_ShowRowPolicies_Privilege("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SHOW ROW POLICYS. diff --git a/tests/testflows/rbac/tests/privileges/show/show_settings_profiles.py b/tests/testflows/rbac/tests/privileges/show/show_settings_profiles.py index 8c29a7f462e..18ca0ee7f6e 100644 --- a/tests/testflows/rbac/tests/privileges/show/show_settings_profiles.py +++ b/tests/testflows/rbac/tests/privileges/show/show_settings_profiles.py @@ -29,7 +29,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -50,13 +50,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("SHOW ACCESS",), ("SHOW SETTINGS PROFILES",), @@ -71,8 +72,8 @@ def check_privilege(self, privilege, grant_target_name, user_name, node=None): if node is None: node = self.context.node - Suite(test=show_settings_profiles, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) - Suite(test=show_create, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=show_settings_profiles)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=show_create)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) @TestSuite @Requirements( @@ -88,7 +89,13 @@ def show_settings_profiles(self, privilege, grant_target_name, user_name, node=N with Scenario("SHOW SETTINGS PROFILES without privilege"): - with When("I check the user can't use SHOW SETTINGS PROFILES"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SHOW SETTINGS PROFILES"): node.query(f"SHOW SETTINGS PROFILES", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -129,7 +136,13 @@ def show_create(self, privilege, grant_target_name, user_name, node=None): with settings_profile(node, target_settings_profile_name): - with When("I check the user can't use SHOW CREATE SETTINGS PROFILE"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SHOW CREATE SETTINGS PROFILE"): node.query(f"SHOW CREATE SETTINGS PROFILE {target_settings_profile_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -163,6 +176,8 @@ def show_create(self, privilege, grant_target_name, user_name, node=None): @Name("show settings profiles") @Requirements( RQ_SRS_006_RBAC_ShowSettingsProfiles_Privilege("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SHOW SETTINGS PROFILES. diff --git a/tests/testflows/rbac/tests/privileges/show/show_tables.py b/tests/testflows/rbac/tests/privileges/show/show_tables.py index 913b64cef69..d445550c032 100755 --- a/tests/testflows/rbac/tests/privileges/show/show_tables.py +++ b/tests/testflows/rbac/tests/privileges/show/show_tables.py @@ -20,7 +20,7 @@ def table_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): table_name = f"table_name_{getuid()}" - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[user_name,user_name,table_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -44,13 +44,14 @@ def table_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[role_name,user_name,table_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SHOW", "*.*"), ("SHOW TABLES", "table"), ("SELECT", "table"), @@ -67,9 +68,9 @@ def check_privilege(self, privilege, on, grant_target_name, user_name, table_nam if node is None: node = self.context.node - Suite(test=show_tables, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) - Suite(test=exists, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) - Suite(test=check, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=show_tables)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=exists)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=check)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) @TestSuite @Requirements( @@ -88,11 +89,19 @@ def show_tables(self, privilege, on, grant_target_name, user_name, table_name, n with table(node, table_name): with Scenario("SHOW TABLES without privilege"): - with When("I check the user doesn't see the table"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user doesn't see the table"): output = node.query("SHOW TABLES", settings = [("user", f"{user_name}")]).output assert output == '', error() with Scenario("SHOW TABLES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -100,6 +109,7 @@ def show_tables(self, privilege, on, grant_target_name, user_name, table_name, n node.query("SHOW TABLES", settings = [("user", f"{user_name}")], message=f"{table_name}") with Scenario("SHOW TABLES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -127,12 +137,21 @@ def exists(self, privilege, on, grant_target_name, user_name, table_name, node=N on = f"{table_name}" with table(node, table_name): + with Scenario("EXISTS without privilege"): - with When(f"I check if {table_name} EXISTS"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then(f"I check if {table_name} EXISTS"): node.query(f"EXISTS {table_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) with Scenario("EXISTS with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -140,6 +159,7 @@ def exists(self, privilege, on, grant_target_name, user_name, table_name, node=N node.query(f"EXISTS {table_name}", settings=[("user",user_name)]) with Scenario("EXISTS with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -167,12 +187,21 @@ def check(self, privilege, on, grant_target_name, user_name, table_name, node=No on = f"{table_name}" with table(node, table_name): + with Scenario("CHECK without privilege"): - with When(f"I CHECK {table_name}"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then(f"I CHECK {table_name}"): node.query(f"CHECK TABLE {table_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) with Scenario("CHECK with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -180,6 +209,7 @@ def check(self, privilege, on, grant_target_name, user_name, table_name, node=No node.query(f"CHECK TABLE {table_name}", settings=[("user",user_name)]) with Scenario("CHECK with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -194,6 +224,8 @@ def check(self, privilege, on, grant_target_name, user_name, table_name, node=No @Name("show tables") @Requirements( RQ_SRS_006_RBAC_ShowTables_Privilege("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SHOW TABLES. diff --git a/tests/testflows/rbac/tests/privileges/show/show_users.py b/tests/testflows/rbac/tests/privileges/show/show_users.py index 48e6ba51f48..aa5c97297b5 100644 --- a/tests/testflows/rbac/tests/privileges/show/show_users.py +++ b/tests/testflows/rbac/tests/privileges/show/show_users.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("ACCESS MANAGEMENT",), ("SHOW ACCESS",), ("SHOW USERS",), @@ -57,8 +58,8 @@ def check_privilege(self, privilege, grant_target_name, user_name, node=None): if node is None: node = self.context.node - Suite(test=show_users, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) - Suite(test=show_create, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=show_users)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=show_create)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) @TestSuite @Requirements( @@ -74,7 +75,13 @@ def show_users(self, privilege, grant_target_name, user_name, node=None): with Scenario("SHOW USERS without privilege"): - with When("I check the user can't use SHOW USERS"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SHOW USERS"): node.query(f"SHOW USERS", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -115,7 +122,13 @@ def show_create(self, privilege, grant_target_name, user_name, node=None): with user(node, target_user_name): - with When("I check the user can't use SHOW CREATE USER"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SHOW CREATE USER"): node.query(f"SHOW CREATE USER {target_user_name}", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -149,6 +162,8 @@ def show_create(self, privilege, grant_target_name, user_name, node=None): @Name("show users") @Requirements( RQ_SRS_006_RBAC_ShowUsers_Privilege("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SHOW USERS. diff --git a/tests/testflows/rbac/tests/privileges/sources.py b/tests/testflows/rbac/tests/privileges/sources.py index 8c1b61ee401..19d32cf500a 100644 --- a/tests/testflows/rbac/tests/privileges/sources.py +++ b/tests/testflows/rbac/tests/privileges/sources.py @@ -17,7 +17,7 @@ def file_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=file, flags=TE, + Suite(run=file, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in file.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def file_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=file, flags=TE, + Suite(run=file, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in file.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("SOURCES",), ("FILE",), ]) @@ -65,7 +66,13 @@ def file(self, privilege, grant_target_name, user_name, node=None): with Given("The user has table privilege"): node.query(f"GRANT CREATE TABLE ON {table_name} TO {grant_target_name}") - with When("I check the user can't use the File source"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use the File source"): node.query(f"CREATE TABLE {table_name} (x String) ENGINE=File()", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -102,7 +109,7 @@ def url_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=url, flags=TE, + Suite(run=url, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in url.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -123,13 +130,14 @@ def url_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=url, flags=TE, + Suite(run=url, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in url.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("SOURCES",), ("URL",), ]) @@ -150,7 +158,13 @@ def url(self, privilege, grant_target_name, user_name, node=None): with Given("The user has table privilege"): node.query(f"GRANT CREATE TABLE ON {table_name} TO {grant_target_name}") - with When("I check the user can't use the URL source"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use the URL source"): node.query(f"CREATE TABLE {table_name} (x String) ENGINE=URL()", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -187,7 +201,7 @@ def remote_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=remote, flags=TE, + Suite(run=remote, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in remote.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -208,13 +222,14 @@ def remote_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=remote, flags=TE, + Suite(run=remote, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in remote.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("SOURCES",), ("REMOTE",), ]) @@ -235,7 +250,13 @@ def remote(self, privilege, grant_target_name, user_name, node=None): with Given("The user has table privilege"): node.query(f"GRANT CREATE TABLE ON {table_name} TO {grant_target_name}") - with When("I check the user can't use the Remote source"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use the Remote source"): node.query(f"CREATE TABLE {table_name} (x String) ENGINE = Distributed()", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -272,7 +293,7 @@ def MySQL_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=MySQL, flags=TE, + Suite(run=MySQL, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in MySQL.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -293,13 +314,14 @@ def MySQL_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=MySQL, flags=TE, + Suite(run=MySQL, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in MySQL.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("SOURCES",), ("MYSQL",), ]) @@ -320,7 +342,13 @@ def MySQL(self, privilege, grant_target_name, user_name, node=None): with Given("The user has table privilege"): node.query(f"GRANT CREATE TABLE ON {table_name} TO {grant_target_name}") - with When("I check the user can't use the MySQL source"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use the MySQL source"): node.query(f"CREATE TABLE {table_name} (x String) ENGINE=MySQL()", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -357,7 +385,7 @@ def ODBC_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=ODBC, flags=TE, + Suite(run=ODBC, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in ODBC.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -378,13 +406,14 @@ def ODBC_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=ODBC, flags=TE, + Suite(run=ODBC, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in ODBC.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("SOURCES",), ("ODBC",), ]) @@ -405,7 +434,13 @@ def ODBC(self, privilege, grant_target_name, user_name, node=None): with Given("The user has table privilege"): node.query(f"GRANT CREATE TABLE ON {table_name} TO {grant_target_name}") - with When("I check the user can't use the ODBC source"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use the ODBC source"): node.query(f"CREATE TABLE {table_name} (x String) ENGINE=ODBC()", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -442,7 +477,7 @@ def JDBC_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=JDBC, flags=TE, + Suite(run=JDBC, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in JDBC.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -463,13 +498,14 @@ def JDBC_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=JDBC, flags=TE, + Suite(run=JDBC, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in JDBC.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("SOURCES",), ("JDBC",), ]) @@ -490,7 +526,13 @@ def JDBC(self, privilege, grant_target_name, user_name, node=None): with Given("The user has table privilege"): node.query(f"GRANT CREATE TABLE ON {table_name} TO {grant_target_name}") - with When("I check the user can't use the JDBC source"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use the JDBC source"): node.query(f"CREATE TABLE {table_name} (x String) ENGINE=JDBC()", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -527,7 +569,7 @@ def HDFS_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=HDFS, flags=TE, + Suite(run=HDFS, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in HDFS.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -548,13 +590,14 @@ def HDFS_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=HDFS, flags=TE, + Suite(run=HDFS, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in HDFS.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("SOURCES",), ("HDFS",), ]) @@ -575,7 +618,13 @@ def HDFS(self, privilege, grant_target_name, user_name, node=None): with Given("The user has table privilege"): node.query(f"GRANT CREATE TABLE ON {table_name} TO {grant_target_name}") - with When("I check the user can't use the HDFS source"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use the HDFS source"): node.query(f"CREATE TABLE {table_name} (x String) ENGINE=HDFS()", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -612,7 +661,7 @@ def S3_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=S3, flags=TE, + Suite(run=S3, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in S3.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -633,13 +682,14 @@ def S3_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=S3, flags=TE, + Suite(run=S3, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in S3.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("SOURCES",), ("S3",), ]) @@ -660,7 +710,13 @@ def S3(self, privilege, grant_target_name, user_name, node=None): with Given("The user has table privilege"): node.query(f"GRANT CREATE TABLE ON {table_name} TO {grant_target_name}") - with When("I check the user can't use the S3 source"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use the S3 source"): node.query(f"CREATE TABLE {table_name} (x String) ENGINE=S3()", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -689,6 +745,8 @@ def S3(self, privilege, grant_target_name, user_name, node=None): @Name("sources") @Requirements( RQ_SRS_006_RBAC_Privileges_Sources("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SOURCES. diff --git a/tests/testflows/rbac/tests/privileges/system/drop_cache.py b/tests/testflows/rbac/tests/privileges/system/drop_cache.py index 6439beb248d..8f1a6caeaac 100644 --- a/tests/testflows/rbac/tests/privileges/system/drop_cache.py +++ b/tests/testflows/rbac/tests/privileges/system/drop_cache.py @@ -17,7 +17,7 @@ def dns_cache_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=dns_cache, flags=TE, + Suite(run=dns_cache, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in dns_cache.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -38,7 +38,7 @@ def dns_cache_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=dns_cache, flags=TE, + Suite(run=dns_cache, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in dns_cache.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -48,6 +48,7 @@ def dns_cache_privileges_granted_via_role(self, node=None): RQ_SRS_006_RBAC_Privileges_System_DropCache_DNS("1.0"), ) @Examples("privilege",[ + ("ALL",), ("SYSTEM",), ("SYSTEM DROP CACHE",), ("SYSTEM DROP DNS CACHE",), @@ -65,11 +66,19 @@ def dns_cache(self, privilege, grant_target_name, user_name, node=None): node = self.context.node with Scenario("SYSTEM DROP DNS CACHE without privilege"): - with When("I check the user is unable to execute SYSTEM DROP DNS CACHE"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user is unable to execute SYSTEM DROP DNS CACHE"): node.query("SYSTEM DROP DNS CACHE", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM DROP DNS CACHE with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -77,6 +86,7 @@ def dns_cache(self, privilege, grant_target_name, user_name, node=None): node.query("SYSTEM DROP DNS CACHE", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM DROP DNS CACHE with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -99,7 +109,7 @@ def mark_cache_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=mark_cache, flags=TE, + Suite(run=mark_cache, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in mark_cache.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -120,7 +130,7 @@ def mark_cache_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=mark_cache, flags=TE, + Suite(run=mark_cache, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in mark_cache.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -130,6 +140,7 @@ def mark_cache_privileges_granted_via_role(self, node=None): RQ_SRS_006_RBAC_Privileges_System_DropCache_Mark("1.0"), ) @Examples("privilege",[ + ("ALL",), ("SYSTEM",), ("SYSTEM DROP CACHE",), ("SYSTEM DROP MARK CACHE",), @@ -147,11 +158,19 @@ def mark_cache(self, privilege, grant_target_name, user_name, node=None): node = self.context.node with Scenario("SYSTEM DROP MARK CACHE without privilege"): - with When("I check the user is unable to execute SYSTEM DROP MARK CACHE"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user is unable to execute SYSTEM DROP MARK CACHE"): node.query("SYSTEM DROP MARK CACHE", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM DROP MARK CACHE with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -159,6 +178,7 @@ def mark_cache(self, privilege, grant_target_name, user_name, node=None): node.query("SYSTEM DROP MARK CACHE", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM DROP MARK CACHE with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -181,7 +201,7 @@ def uncompressed_cache_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=uncompressed_cache, flags=TE, + Suite(run=uncompressed_cache, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in uncompressed_cache.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -202,7 +222,7 @@ def uncompressed_cache_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=uncompressed_cache, flags=TE, + Suite(run=uncompressed_cache, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in uncompressed_cache.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -212,6 +232,7 @@ def uncompressed_cache_privileges_granted_via_role(self, node=None): RQ_SRS_006_RBAC_Privileges_System_DropCache_Uncompressed("1.0"), ) @Examples("privilege",[ + ("ALL",), ("SYSTEM",), ("SYSTEM DROP CACHE",), ("SYSTEM DROP UNCOMPRESSED CACHE",), @@ -229,11 +250,19 @@ def uncompressed_cache(self, privilege, grant_target_name, user_name, node=None) node = self.context.node with Scenario("SYSTEM DROP UNCOMPRESSED CACHE without privilege"): - with When("I check the user is unable to execute SYSTEM DROP UNCOMPRESSED CACHE"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user is unable to execute SYSTEM DROP UNCOMPRESSED CACHE"): node.query("SYSTEM DROP UNCOMPRESSED CACHE", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM DROP UNCOMPRESSED CACHE with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -241,6 +270,7 @@ def uncompressed_cache(self, privilege, grant_target_name, user_name, node=None) node.query("SYSTEM DROP UNCOMPRESSED CACHE", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM DROP UNCOMPRESSED CACHE with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -255,6 +285,8 @@ def uncompressed_cache(self, privilege, grant_target_name, user_name, node=None) @Name("system drop cache") @Requirements( RQ_SRS_006_RBAC_Privileges_System_DropCache("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM DROP CACHE. diff --git a/tests/testflows/rbac/tests/privileges/system/fetches.py b/tests/testflows/rbac/tests/privileges/system/fetches.py index 14c046f4fbe..3aba1b71566 100644 --- a/tests/testflows/rbac/tests/privileges/system/fetches.py +++ b/tests/testflows/rbac/tests/privileges/system/fetches.py @@ -17,7 +17,7 @@ def replicated_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=check_replicated_privilege, flags=TE, + Suite(run=check_replicated_privilege, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in check_replicated_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def replicated_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_replicated_privilege, flags=TE, + Suite(run=check_replicated_privilege, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in check_replicated_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM FETCHES", "table"), ("SYSTEM STOP FETCHES", "table"), @@ -59,8 +60,8 @@ def check_replicated_privilege(self, privilege, on, grant_target_name, user_name if node is None: node = self.context.node - Suite(test=start_replication_queues, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) - Suite(test=stop_replication_queues, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=start_replication_queues)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=stop_replication_queues)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) @TestSuite def start_replication_queues(self, privilege, on, grant_target_name, user_name, node=None): @@ -77,11 +78,19 @@ def start_replication_queues(self, privilege, on, grant_target_name, user_name, with table(node, table_name, "ReplicatedMergeTree-sharded_cluster"): with Scenario("SYSTEM START FETCHES without privilege"): - with When("I check the user can't start fetches"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't start fetches"): node.query(f"SYSTEM START FETCHES {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM START FETCHES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -89,6 +98,7 @@ def start_replication_queues(self, privilege, on, grant_target_name, user_name, node.query(f"SYSTEM START FETCHES {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM START FETCHES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -114,11 +124,19 @@ def stop_replication_queues(self, privilege, on, grant_target_name, user_name, n with table(node, table_name, "ReplicatedMergeTree-sharded_cluster"): with Scenario("SYSTEM STOP FETCHES without privilege"): - with When("I check the user can't stop fetches"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't stop fetches"): node.query(f"SYSTEM STOP FETCHES {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM STOP FETCHES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -126,6 +144,7 @@ def stop_replication_queues(self, privilege, on, grant_target_name, user_name, n node.query(f"SYSTEM STOP FETCHES {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM STOP FETCHES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -140,6 +159,8 @@ def stop_replication_queues(self, privilege, on, grant_target_name, user_name, n @Name("system fetches") @Requirements( RQ_SRS_006_RBAC_Privileges_System_Fetches("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM FETCHES. diff --git a/tests/testflows/rbac/tests/privileges/system/flush.py b/tests/testflows/rbac/tests/privileges/system/flush.py index 8835b51db9e..8c540fa1286 100644 --- a/tests/testflows/rbac/tests/privileges/system/flush.py +++ b/tests/testflows/rbac/tests/privileges/system/flush.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=flush_logs, flags=TE, + Suite(run=flush_logs, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in flush_logs.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=flush_logs, flags=TE, + Suite(run=flush_logs, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in flush_logs.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM FLUSH", "*.*"), ("SYSTEM FLUSH LOGS", "*.*"), @@ -62,11 +63,19 @@ def flush_logs(self, privilege, on, grant_target_name, user_name, node=None): node = self.context.node with Scenario("SYSTEM FLUSH LOGS without privilege"): - with When("I check the user can't flush logs"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't flush logs"): node.query(f"SYSTEM FLUSH LOGS", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM FLUSH LOGS with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -74,6 +83,7 @@ def flush_logs(self, privilege, on, grant_target_name, user_name, node=None): node.query(f"SYSTEM FLUSH LOGS", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM FLUSH LOGS with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -97,7 +107,7 @@ def distributed_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): table_name = f"table_name_{getuid()}" - Suite(run=flush_distributed, flags=TE, + Suite(run=flush_distributed, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[user_name,user_name,table_name]) for row in flush_distributed.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -119,13 +129,14 @@ def distributed_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=flush_distributed, flags=TE, + Suite(run=flush_distributed, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[role_name,user_name,table_name]) for row in flush_distributed.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM FLUSH", "*.*"), ("SYSTEM FLUSH DISTRIBUTED", "table"), @@ -151,11 +162,19 @@ def flush_distributed(self, privilege, on, grant_target_name, user_name, table_n node.query(f"CREATE TABLE {table_name} (a UInt64) ENGINE = Distributed(sharded_cluster, default, {table0_name}, rand())") with Scenario("SYSTEM FLUSH DISTRIBUTED without privilege"): - with When("I check the user can't flush distributed"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't flush distributed"): node.query(f"SYSTEM FLUSH DISTRIBUTED {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM FLUSH DISTRIBUTED with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -163,6 +182,7 @@ def flush_distributed(self, privilege, on, grant_target_name, user_name, table_n node.query(f"SYSTEM FLUSH DISTRIBUTED {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM FLUSH DISTRIBUTED with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -182,6 +202,8 @@ def flush_distributed(self, privilege, on, grant_target_name, user_name, table_n @Name("system flush") @Requirements( RQ_SRS_006_RBAC_Privileges_System_Flush("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM FLUSH. diff --git a/tests/testflows/rbac/tests/privileges/system/merges.py b/tests/testflows/rbac/tests/privileges/system/merges.py index 0f347299c44..324b9c0b4ec 100644 --- a/tests/testflows/rbac/tests/privileges/system/merges.py +++ b/tests/testflows/rbac/tests/privileges/system/merges.py @@ -18,7 +18,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): table_name = f"table_name_{getuid()}" - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[user_name,user_name,table_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -40,13 +40,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[role_name,user_name,table_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM MERGES", "table"), ("SYSTEM STOP MERGES", "table"), @@ -61,8 +62,8 @@ def check_privilege(self, privilege, on, grant_target_name, user_name, table_nam if node is None: node = self.context.node - Suite(test=start_merges, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) - Suite(test=stop_merges, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=start_merges)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=stop_merges)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) @TestSuite def start_merges(self, privilege, on, grant_target_name, user_name, table_name, node=None): @@ -78,11 +79,19 @@ def start_merges(self, privilege, on, grant_target_name, user_name, table_name, with table(node, table_name): with Scenario("SYSTEM START MERGES without privilege"): - with When("I check the user can't start merges"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't start merges"): node.query(f"SYSTEM START MERGES {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM START MERGES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -90,6 +99,7 @@ def start_merges(self, privilege, on, grant_target_name, user_name, table_name, node.query(f"SYSTEM START MERGES {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM START MERGES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -114,11 +124,19 @@ def stop_merges(self, privilege, on, grant_target_name, user_name, table_name, n with table(node, table_name): with Scenario("SYSTEM STOP MERGES without privilege"): - with When("I check the user can't stop merges"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't stop merges"): node.query(f"SYSTEM STOP MERGES {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM STOP MERGES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -126,6 +144,7 @@ def stop_merges(self, privilege, on, grant_target_name, user_name, table_name, n node.query(f"SYSTEM STOP MERGES {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM STOP MERGES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -140,6 +159,8 @@ def stop_merges(self, privilege, on, grant_target_name, user_name, table_name, n @Name("system merges") @Requirements( RQ_SRS_006_RBAC_Privileges_System_Merges("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM MERGES. diff --git a/tests/testflows/rbac/tests/privileges/system/moves.py b/tests/testflows/rbac/tests/privileges/system/moves.py index 2081e6dfe22..2a75ff39aaf 100644 --- a/tests/testflows/rbac/tests/privileges/system/moves.py +++ b/tests/testflows/rbac/tests/privileges/system/moves.py @@ -18,7 +18,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): table_name = f"table_name_{getuid()}" - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[user_name,user_name,table_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -40,13 +40,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[role_name,user_name,table_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM MOVES", "table"), ("SYSTEM STOP MOVES", "table"), @@ -61,8 +62,8 @@ def check_privilege(self, privilege, on, grant_target_name, user_name, table_nam if node is None: node = self.context.node - Suite(test=start_moves, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) - Suite(test=stop_moves, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=start_moves)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=stop_moves)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) @TestSuite def start_moves(self, privilege, on, grant_target_name, user_name, table_name, node=None): @@ -78,11 +79,19 @@ def start_moves(self, privilege, on, grant_target_name, user_name, table_name, n with table(node, table_name): with Scenario("SYSTEM START MOVES without privilege"): - with When("I check the user can't start moves"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't start moves"): node.query(f"SYSTEM START MOVES {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM START MOVES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -90,6 +99,7 @@ def start_moves(self, privilege, on, grant_target_name, user_name, table_name, n node.query(f"SYSTEM START MOVES {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM START MOVES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -114,11 +124,19 @@ def stop_moves(self, privilege, on, grant_target_name, user_name, table_name, no with table(node, table_name): with Scenario("SYSTEM STOP MOVES without privilege"): - with When("I check the user can't stop moves"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't stop moves"): node.query(f"SYSTEM STOP MOVES {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM STOP MOVES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -126,6 +144,7 @@ def stop_moves(self, privilege, on, grant_target_name, user_name, table_name, no node.query(f"SYSTEM STOP MOVES {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM STOP MOVES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -140,6 +159,8 @@ def stop_moves(self, privilege, on, grant_target_name, user_name, table_name, no @Name("system moves") @Requirements( RQ_SRS_006_RBAC_Privileges_System_Moves("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM MOVES. diff --git a/tests/testflows/rbac/tests/privileges/system/reload.py b/tests/testflows/rbac/tests/privileges/system/reload.py index cfc752fb253..bb8f91a0dd4 100644 --- a/tests/testflows/rbac/tests/privileges/system/reload.py +++ b/tests/testflows/rbac/tests/privileges/system/reload.py @@ -38,7 +38,7 @@ def config_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=config, flags=TE, + Suite(run=config, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in config.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -59,7 +59,7 @@ def config_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=config, flags=TE, + Suite(run=config, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in config.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -69,6 +69,7 @@ def config_privileges_granted_via_role(self, node=None): RQ_SRS_006_RBAC_Privileges_System_Reload_Config("1.0"), ) @Examples("privilege",[ + ("ALL",), ("SYSTEM",), ("SYSTEM RELOAD",), ("SYSTEM RELOAD CONFIG",), @@ -83,11 +84,19 @@ def config(self, privilege, grant_target_name, user_name, node=None): node = self.context.node with Scenario("SYSTEM RELOAD CONFIG without privilege"): - with When("I check the user is unable to execute SYSTEM RELOAD CONFIG"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user is unable to execute SYSTEM RELOAD CONFIG"): node.query("SYSTEM RELOAD CONFIG", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM RELOAD CONFIG with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -95,6 +104,7 @@ def config(self, privilege, grant_target_name, user_name, node=None): node.query("SYSTEM RELOAD CONFIG", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM RELOAD CONFIG with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -117,7 +127,7 @@ def dictionary_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=dictionary, flags=TE, + Suite(run=dictionary, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in dictionary.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -138,7 +148,7 @@ def dictionary_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=dictionary, flags=TE, + Suite(run=dictionary, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in dictionary.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -148,6 +158,7 @@ def dictionary_privileges_granted_via_role(self, node=None): RQ_SRS_006_RBAC_Privileges_System_Reload_Dictionary("1.0"), ) @Examples("privilege",[ + ("ALL",), ("SYSTEM",), ("SYSTEM RELOAD",), ("SYSTEM RELOAD DICTIONARIES",), @@ -163,16 +174,24 @@ def dictionary(self, privilege, grant_target_name, user_name, node=None): node = self.context.node with Scenario("SYSTEM RELOAD DICTIONARY without privilege"): + dict_name = f"dict_{getuid()}" table_name = f"table_{getuid()}" with dict_setup(node, table_name, dict_name): - with When("I check the user is unable to execute SYSTEM RELOAD DICTIONARY"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user is unable to execute SYSTEM RELOAD DICTIONARY"): node.query(f"SYSTEM RELOAD DICTIONARY default.{dict_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM RELOAD DICTIONARY with privilege"): + dict_name = f"dict_{getuid()}" table_name = f"table_{getuid()}" @@ -185,6 +204,7 @@ def dictionary(self, privilege, grant_target_name, user_name, node=None): node.query(f"SYSTEM RELOAD DICTIONARY default.{dict_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM RELOAD DICTIONARY with revoked privilege"): + dict_name = f"dict_{getuid()}" table_name = f"table_{getuid()}" @@ -212,7 +232,7 @@ def dictionaries_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=dictionaries, flags=TE, + Suite(run=dictionaries, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in dictionaries.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -233,7 +253,7 @@ def dictionaries_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=dictionaries, flags=TE, + Suite(run=dictionaries, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in dictionaries.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -243,6 +263,7 @@ def dictionaries_privileges_granted_via_role(self, node=None): RQ_SRS_006_RBAC_Privileges_System_Reload_Dictionaries("1.0"), ) @Examples("privilege",[ + ("ALL",), ("SYSTEM",), ("SYSTEM RELOAD",), ("SYSTEM RELOAD DICTIONARIES",), @@ -258,11 +279,19 @@ def dictionaries(self, privilege, grant_target_name, user_name, node=None): node = self.context.node with Scenario("SYSTEM RELOAD DICTIONARIES without privilege"): - with When("I check the user is unable to execute SYSTEM RELOAD DICTIONARIES"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user is unable to execute SYSTEM RELOAD DICTIONARIES"): node.query("SYSTEM RELOAD DICTIONARIES", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM RELOAD DICTIONARIES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -270,6 +299,7 @@ def dictionaries(self, privilege, grant_target_name, user_name, node=None): node.query("SYSTEM RELOAD DICTIONARIES", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM RELOAD DICTIONARIES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -292,7 +322,7 @@ def embedded_dictionaries_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=embedded_dictionaries, flags=TE, + Suite(run=embedded_dictionaries, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in embedded_dictionaries.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -313,7 +343,7 @@ def embedded_dictionaries_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=embedded_dictionaries, flags=TE, + Suite(run=embedded_dictionaries, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in embedded_dictionaries.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -323,6 +353,7 @@ def embedded_dictionaries_privileges_granted_via_role(self, node=None): RQ_SRS_006_RBAC_Privileges_System_Reload_EmbeddedDictionaries("1.0"), ) @Examples("privilege",[ + ("ALL",), ("SYSTEM",), ("SYSTEM RELOAD",), ("SYSTEM RELOAD EMBEDDED DICTIONARIES",), @@ -337,11 +368,19 @@ def embedded_dictionaries(self, privilege, grant_target_name, user_name, node=No node = self.context.node with Scenario("SYSTEM RELOAD EMBEDDED DICTIONARIES without privilege"): - with When("I check the user is unable to execute SYSTEM RELOAD EMBEDDED DICTIONARIES"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user is unable to execute SYSTEM RELOAD EMBEDDED DICTIONARIES"): node.query("SYSTEM RELOAD EMBEDDED DICTIONARIES", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM RELOAD EMBEDDED DICTIONARIES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -349,6 +388,7 @@ def embedded_dictionaries(self, privilege, grant_target_name, user_name, node=No node.query("SYSTEM RELOAD EMBEDDED DICTIONARIES", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM RELOAD EMBEDDED DICTIONARIES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON *.* TO {grant_target_name}") @@ -363,6 +403,8 @@ def embedded_dictionaries(self, privilege, grant_target_name, user_name, node=No @Name("system reload") @Requirements( RQ_SRS_006_RBAC_Privileges_System_Reload("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM RELOAD. diff --git a/tests/testflows/rbac/tests/privileges/system/replication_queues.py b/tests/testflows/rbac/tests/privileges/system/replication_queues.py index 3ac2e09418a..47f12b7c866 100644 --- a/tests/testflows/rbac/tests/privileges/system/replication_queues.py +++ b/tests/testflows/rbac/tests/privileges/system/replication_queues.py @@ -17,7 +17,7 @@ def replicated_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=check_replicated_privilege, flags=TE, + Suite(run=check_replicated_privilege, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in check_replicated_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def replicated_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_replicated_privilege, flags=TE, + Suite(run=check_replicated_privilege, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in check_replicated_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM REPLICATION QUEUES", "table"), ("SYSTEM STOP REPLICATION QUEUES", "table"), @@ -59,8 +60,8 @@ def check_replicated_privilege(self, privilege, on, grant_target_name, user_name if node is None: node = self.context.node - Suite(test=start_replication_queues, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) - Suite(test=stop_replication_queues, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=start_replication_queues)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=stop_replication_queues)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) @TestSuite def start_replication_queues(self, privilege, on, grant_target_name, user_name, node=None): @@ -77,11 +78,19 @@ def start_replication_queues(self, privilege, on, grant_target_name, user_name, with table(node, table_name, "ReplicatedMergeTree-sharded_cluster"): with Scenario("SYSTEM START REPLICATION QUEUES without privilege"): - with When("I check the user can't start sends"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't start sends"): node.query(f"SYSTEM START REPLICATION QUEUES {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM START REPLICATION QUEUES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -89,6 +98,7 @@ def start_replication_queues(self, privilege, on, grant_target_name, user_name, node.query(f"SYSTEM START REPLICATION QUEUES {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM START REPLICATION QUEUES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -114,11 +124,19 @@ def stop_replication_queues(self, privilege, on, grant_target_name, user_name, n with table(node, table_name, "ReplicatedMergeTree-sharded_cluster"): with Scenario("SYSTEM STOP REPLICATION QUEUES without privilege"): - with When("I check the user can't stop sends"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't stop sends"): node.query(f"SYSTEM STOP REPLICATION QUEUES {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM STOP REPLICATION QUEUES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -126,6 +144,7 @@ def stop_replication_queues(self, privilege, on, grant_target_name, user_name, n node.query(f"SYSTEM STOP REPLICATION QUEUES {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM STOP REPLICATION QUEUES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -140,6 +159,8 @@ def stop_replication_queues(self, privilege, on, grant_target_name, user_name, n @Name("system replication queues") @Requirements( RQ_SRS_006_RBAC_Privileges_System_ReplicationQueues("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM REPLICATION QUEUES. diff --git a/tests/testflows/rbac/tests/privileges/system/restart_replica.py b/tests/testflows/rbac/tests/privileges/system/restart_replica.py index 0e3e61d04bb..4e3d5f7b060 100644 --- a/tests/testflows/rbac/tests/privileges/system/restart_replica.py +++ b/tests/testflows/rbac/tests/privileges/system/restart_replica.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=restart_replica, flags=TE, + Suite(run=restart_replica, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in restart_replica.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=restart_replica, flags=TE, + Suite(run=restart_replica, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in restart_replica.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM RESTART REPLICA", "table"), ("RESTART REPLICA", "table"), @@ -63,11 +64,19 @@ def restart_replica(self, privilege, on, grant_target_name, user_name, node=None with table(node, table_name, "ReplicatedMergeTree-sharded_cluster"): with Scenario("SYSTEM RESTART REPLICA without privilege"): - with When("I check the user can't restart replica"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't restart replica"): node.query(f"SYSTEM RESTART REPLICA {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM RESTART REPLICA with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -75,6 +84,7 @@ def restart_replica(self, privilege, on, grant_target_name, user_name, node=None node.query(f"SYSTEM RESTART REPLICA {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM RESTART REPLICA with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -89,6 +99,8 @@ def restart_replica(self, privilege, on, grant_target_name, user_name, node=None @Name("system restart replica") @Requirements( RQ_SRS_006_RBAC_Privileges_System_RestartReplica("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM RESTART REPLICA. diff --git a/tests/testflows/rbac/tests/privileges/system/sends.py b/tests/testflows/rbac/tests/privileges/system/sends.py index 24865088703..4acd173d922 100644 --- a/tests/testflows/rbac/tests/privileges/system/sends.py +++ b/tests/testflows/rbac/tests/privileges/system/sends.py @@ -17,7 +17,7 @@ def replicated_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=check_replicated_privilege, flags=TE, + Suite(run=check_replicated_privilege, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in check_replicated_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def replicated_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_replicated_privilege, flags=TE, + Suite(run=check_replicated_privilege, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in check_replicated_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM SENDS", "*.*"), ("SYSTEM START SENDS", "*.*"), @@ -67,8 +68,8 @@ def check_replicated_privilege(self, privilege, on, grant_target_name, user_name if node is None: node = self.context.node - Suite(test=start_replicated_sends, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) - Suite(test=stop_replicated_sends, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=start_replicated_sends)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=stop_replicated_sends)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name) @TestSuite def start_replicated_sends(self, privilege, on, grant_target_name, user_name, node=None): @@ -85,11 +86,19 @@ def start_replicated_sends(self, privilege, on, grant_target_name, user_name, no with table(node, table_name, "ReplicatedMergeTree-sharded_cluster"): with Scenario("SYSTEM START REPLICATED SENDS without privilege"): - with When("I check the user can't start sends"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't start sends"): node.query(f"SYSTEM START REPLICATED SENDS {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM START REPLICATED SENDS with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -97,6 +106,7 @@ def start_replicated_sends(self, privilege, on, grant_target_name, user_name, no node.query(f"SYSTEM START REPLICATED SENDS {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM START REPLICATED SENDS with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -122,11 +132,19 @@ def stop_replicated_sends(self, privilege, on, grant_target_name, user_name, nod with table(node, table_name, "ReplicatedMergeTree-sharded_cluster"): with Scenario("SYSTEM STOP REPLICATED SENDS without privilege"): - with When("I check the user can't stop sends"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't stop sends"): node.query(f"SYSTEM STOP REPLICATED SENDS {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM STOP REPLICATED SENDS with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -134,6 +152,7 @@ def stop_replicated_sends(self, privilege, on, grant_target_name, user_name, nod node.query(f"SYSTEM STOP REPLICATED SENDS {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM STOP REPLICATED SENDS with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -157,7 +176,7 @@ def distributed_privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): table_name = f"table_name_{getuid()}" - Suite(run=check_distributed_privilege, flags=TE, + Suite(run=check_distributed_privilege, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[user_name,user_name,table_name]) for row in check_distributed_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -179,13 +198,14 @@ def distributed_privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_distributed_privilege, flags=TE, + Suite(run=check_distributed_privilege, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[role_name,user_name,table_name]) for row in check_distributed_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM SENDS", "*.*"), ("SYSTEM START SENDS", "*.*"), @@ -208,8 +228,8 @@ def check_distributed_privilege(self, privilege, on, grant_target_name, user_nam if node is None: node = self.context.node - Suite(test=start_distributed_moves, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) - Suite(test=stop_distributed_moves, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=start_distributed_moves)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=stop_distributed_moves)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) @TestSuite def start_distributed_moves(self, privilege, on, grant_target_name, user_name, table_name, node=None): @@ -229,11 +249,19 @@ def start_distributed_moves(self, privilege, on, grant_target_name, user_name, t node.query(f"CREATE TABLE {table_name} (a UInt64) ENGINE = Distributed(sharded_cluster, default, {table0_name}, rand())") with Scenario("SYSTEM START DISTRIBUTED SENDS without privilege"): - with When("I check the user can't start merges"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't start merges"): node.query(f"SYSTEM START DISTRIBUTED SENDS {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM START DISTRIBUTED SENDS with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -241,6 +269,7 @@ def start_distributed_moves(self, privilege, on, grant_target_name, user_name, t node.query(f"SYSTEM START DISTRIBUTED SENDS {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM START DISTRIBUTED SENDS with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -273,11 +302,19 @@ def stop_distributed_moves(self, privilege, on, grant_target_name, user_name, ta node.query(f"CREATE TABLE {table_name} (a UInt64) ENGINE = Distributed(sharded_cluster, default, {table0_name}, rand())") with Scenario("SYSTEM STOP DISTRIBUTED SENDS without privilege"): - with When("I check the user can't stop merges"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't stop merges"): node.query(f"SYSTEM STOP DISTRIBUTED SENDS {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM STOP DISTRIBUTED SENDS with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -285,6 +322,7 @@ def stop_distributed_moves(self, privilege, on, grant_target_name, user_name, ta node.query(f"SYSTEM STOP DISTRIBUTED SENDS {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM STOP DISTRIBUTED SENDS with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -302,6 +340,8 @@ def stop_distributed_moves(self, privilege, on, grant_target_name, user_name, ta @Name("system sends") @Requirements( RQ_SRS_006_RBAC_Privileges_System_Sends("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM SENDS. diff --git a/tests/testflows/rbac/tests/privileges/system/shutdown.py b/tests/testflows/rbac/tests/privileges/system/shutdown.py index 290f6d8e5d1..26752ef4d01 100644 --- a/tests/testflows/rbac/tests/privileges/system/shutdown.py +++ b/tests/testflows/rbac/tests/privileges/system/shutdown.py @@ -19,7 +19,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @@ -40,13 +40,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in check_privilege.examples ], args=Args(name="privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege",[ + ("ALL",), ("SYSTEM",), ("SYSTEM SHUTDOWN",), ("SHUTDOWN",), @@ -59,8 +60,8 @@ def check_privilege(self, privilege, grant_target_name, user_name, node=None): if node is None: node = self.context.node - Suite(test=shutdown, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) - Suite(test=kill, setup=instrument_clickhouse_server_log)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=shutdown)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) + Suite(test=kill)(privilege=privilege, grant_target_name=grant_target_name, user_name=user_name) @TestSuite def shutdown(self, privilege, grant_target_name, user_name, node=None): @@ -75,7 +76,13 @@ def shutdown(self, privilege, grant_target_name, user_name, node=None): with Scenario("SYSTEM SHUTDOWN without privilege"): - with When("I check the user can't use SYSTEM SHUTDOWN"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SYSTEM SHUTDOWN"): node.query(f"SYSTEM SHUTDOWN", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -136,7 +143,13 @@ def kill(self, privilege, grant_target_name, user_name, node=None): with Scenario("SYSTEM KILL without privilege"): - with When("I check the user can't use SYSTEM KILL"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't use SYSTEM KILL"): node.query(f"SYSTEM KILL", settings=[("user",user_name)], exitcode=exitcode, message=message) @@ -190,6 +203,8 @@ def kill(self, privilege, grant_target_name, user_name, node=None): @Name("system shutdown") @Requirements( RQ_SRS_006_RBAC_Privileges_System_Shutdown("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM SHUTDOWN. diff --git a/tests/testflows/rbac/tests/privileges/system/sync_replica.py b/tests/testflows/rbac/tests/privileges/system/sync_replica.py index 7df697fd6e5..14681ad31ae 100644 --- a/tests/testflows/rbac/tests/privileges/system/sync_replica.py +++ b/tests/testflows/rbac/tests/privileges/system/sync_replica.py @@ -17,7 +17,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): - Suite(run=sync_replica, flags=TE, + Suite(run=sync_replica, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[user_name,user_name]) for row in sync_replica.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -38,13 +38,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=sync_replica, flags=TE, + Suite(run=sync_replica, examples=Examples("privilege on grant_target_name user_name", [ tuple(list(row)+[role_name,user_name]) for row in sync_replica.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM SYNC REPLICA", "table"), ("SYNC REPLICA", "table"), @@ -63,11 +64,19 @@ def sync_replica(self, privilege, on, grant_target_name, user_name, node=None): with table(node, table_name, "ReplicatedMergeTree-sharded_cluster"): with Scenario("SYSTEM SYNC REPLICA without privilege"): - with When("I check the user can't sync replica"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't sync replica"): node.query(f"SYSTEM SYNC REPLICA {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM SYNC REPLICA with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -75,6 +84,7 @@ def sync_replica(self, privilege, on, grant_target_name, user_name, node=None): node.query(f"SYSTEM SYNC REPLICA {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM SYNC REPLICA with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -89,6 +99,8 @@ def sync_replica(self, privilege, on, grant_target_name, user_name, node=None): @Name("system sync replica") @Requirements( RQ_SRS_006_RBAC_Privileges_System_SyncReplica("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM SYNC REPLICA. diff --git a/tests/testflows/rbac/tests/privileges/system/ttl_merges.py b/tests/testflows/rbac/tests/privileges/system/ttl_merges.py index 74f99026fe4..a59cc530a6d 100644 --- a/tests/testflows/rbac/tests/privileges/system/ttl_merges.py +++ b/tests/testflows/rbac/tests/privileges/system/ttl_merges.py @@ -18,7 +18,7 @@ def privileges_granted_directly(self, node=None): with user(node, f"{user_name}"): table_name = f"table_name_{getuid()}" - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[user_name,user_name,table_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @@ -40,13 +40,14 @@ def privileges_granted_via_role(self, node=None): with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") - Suite(run=check_privilege, flags=TE, + Suite(run=check_privilege, examples=Examples("privilege on grant_target_name user_name table_name", [ tuple(list(row)+[role_name,user_name,table_name]) for row in check_privilege.examples ], args=Args(name="check privilege={privilege}", format_name=True))) @TestOutline(Suite) @Examples("privilege on",[ + ("ALL", "*.*"), ("SYSTEM", "*.*"), ("SYSTEM TTL MERGES", "table"), ("SYSTEM STOP TTL MERGES", "table"), @@ -61,8 +62,8 @@ def check_privilege(self, privilege, on, grant_target_name, user_name, table_nam if node is None: node = self.context.node - Suite(test=start_ttl_merges, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) - Suite(test=stop_ttl_merges, setup=instrument_clickhouse_server_log)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=start_ttl_merges)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) + Suite(test=stop_ttl_merges)(privilege=privilege, on=on, grant_target_name=grant_target_name, user_name=user_name, table_name=table_name) @TestSuite def start_ttl_merges(self, privilege, on, grant_target_name, user_name, table_name, node=None): @@ -78,11 +79,19 @@ def start_ttl_merges(self, privilege, on, grant_target_name, user_name, table_na with table(node, table_name): with Scenario("SYSTEM START TTL MERGES without privilege"): - with When("I check the user can't start merges"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't start merges"): node.query(f"SYSTEM START TTL MERGES {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM START TTL MERGES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -90,6 +99,7 @@ def start_ttl_merges(self, privilege, on, grant_target_name, user_name, table_na node.query(f"SYSTEM START TTL MERGES {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM START TTL MERGES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -114,11 +124,19 @@ def stop_ttl_merges(self, privilege, on, grant_target_name, user_name, table_nam with table(node, table_name): with Scenario("SYSTEM STOP TTL MERGES without privilege"): - with When("I check the user can't stop merges"): + + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I check the user can't stop merges"): node.query(f"SYSTEM STOP TTL MERGES {table_name}", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with Scenario("SYSTEM STOP TTL MERGES with privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -126,6 +144,7 @@ def stop_ttl_merges(self, privilege, on, grant_target_name, user_name, table_nam node.query(f"SYSTEM STOP TTL MERGES {table_name}", settings = [("user", f"{user_name}")]) with Scenario("SYSTEM STOP TTL MERGES with revoked privilege"): + with When(f"I grant {privilege} on the table"): node.query(f"GRANT {privilege} ON {on} TO {grant_target_name}") @@ -140,6 +159,8 @@ def stop_ttl_merges(self, privilege, on, grant_target_name, user_name, table_nam @Name("system ttl merges") @Requirements( RQ_SRS_006_RBAC_Privileges_System_TTLMerges("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) def feature(self, node="clickhouse1"): """Check the RBAC functionality of SYSTEM TTL MERGES. diff --git a/tests/testflows/rbac/tests/privileges/truncate.py b/tests/testflows/rbac/tests/privileges/truncate.py index b7dfcbfd718..df81913f0a8 100644 --- a/tests/testflows/rbac/tests/privileges/truncate.py +++ b/tests/testflows/rbac/tests/privileges/truncate.py @@ -12,13 +12,13 @@ def privilege_granted_directly_or_via_role(self, table_type, node=None): if node is None: node = self.context.node - with Suite("user with direct privilege", setup=instrument_clickhouse_server_log): + with Suite("user with direct privilege"): with user(node, user_name): with When(f"I run checks that {user_name} is only able to execute TRUNCATE with required privileges"): privilege_check(grant_target_name=user_name, user_name=user_name, table_type=table_type, node=node) - with Suite("user with privilege via role", setup=instrument_clickhouse_server_log): + with Suite("user with privilege via role"): with user(node, user_name), role(node, role_name): with When("I grant the role to the user"): @@ -32,16 +32,22 @@ def privilege_check(grant_target_name, user_name, table_type, node=None): """ exitcode, message = errors.not_enough_privileges(name=f"{user_name}") - with Scenario("user without privilege", setup=instrument_clickhouse_server_log): + with Scenario("user without privilege"): table_name = f"merge_tree_{getuid()}" with table(node, table_name, table_type): - with When("I attempt to truncate a table without privilege"): + with When("I grant the user NONE privilege"): + node.query(f"GRANT NONE TO {grant_target_name}") + + with And("I grant the user USAGE privilege"): + node.query(f"GRANT USAGE ON *.* TO {grant_target_name}") + + with Then("I attempt to truncate a table without privilege"): node.query(f"TRUNCATE TABLE {table_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("user with privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with privilege"): table_name = f"merge_tree_{getuid()}" with table(node, table_name, table_type): @@ -52,7 +58,7 @@ def privilege_check(grant_target_name, user_name, table_type, node=None): with Then("I attempt to truncate a table"): node.query(f"TRUNCATE TABLE {table_name}", settings = [("user", user_name)]) - with Scenario("user with revoked privilege", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked privilege"): table_name = f"merge_tree_{getuid()}" with table(node, table_name, table_type): @@ -67,7 +73,22 @@ def privilege_check(grant_target_name, user_name, table_type, node=None): node.query(f"TRUNCATE TABLE {table_name}", settings = [("user", user_name)], exitcode=exitcode, message=message) - with Scenario("execute on cluster", setup=instrument_clickhouse_server_log): + with Scenario("user with revoked ALL privilege"): + table_name = f"merge_tree_{getuid()}" + + with table(node, table_name, table_type): + + with When("I grant the truncate privilege"): + node.query(f"GRANT TRUNCATE ON {table_name} TO {grant_target_name}") + + with And("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with Then("I attempt to truncate a table"): + node.query(f"TRUNCATE TABLE {table_name}", settings = [("user", user_name)], + exitcode=exitcode, message=message) + + with Scenario("execute on cluster"): table_name = f"merge_tree_{getuid()}" with table(node, table_name, table_type): @@ -78,9 +99,25 @@ def privilege_check(grant_target_name, user_name, table_type, node=None): with Then("I attempt to truncate a table"): node.query(f"TRUNCATE TABLE IF EXISTS {table_name} ON CLUSTER sharded_cluster", settings = [("user", user_name)]) + with Scenario("user with ALL privilege"): + table_name = f"merge_tree_{getuid()}" + + with table(node, table_name, table_type): + + with When("I revoke ALL privilege"): + node.query(f"REVOKE ALL ON *.* FROM {grant_target_name}") + + with And("I grant ALL privilege"): + node.query(f"GRANT ALL ON *.* TO {grant_target_name}") + + with Then("I attempt to truncate a table"): + node.query(f"TRUNCATE TABLE {table_name}", settings = [("user", user_name)]) + @TestFeature @Requirements( RQ_SRS_006_RBAC_Privileges_Truncate("1.0"), + RQ_SRS_006_RBAC_Privileges_All("1.0"), + RQ_SRS_006_RBAC_Privileges_None("1.0") ) @Examples("table_type", [ (key,) for key in table_types.keys() @@ -103,5 +140,5 @@ def feature(self, node="clickhouse1", stress=None, parallel=None): continue with Example(str(example)): - with Suite(test=privilege_granted_directly_or_via_role): + with Suite(test=privilege_granted_directly_or_via_role, setup=instrument_clickhouse_server_log): privilege_granted_directly_or_via_role(table_type=table_type) diff --git a/tests/testflows/rbac/tests/syntax/alter_quota.py b/tests/testflows/rbac/tests/syntax/alter_quota.py index 74a9c05bd27..6ccafc4dbcd 100755 --- a/tests/testflows/rbac/tests/syntax/alter_quota.py +++ b/tests/testflows/rbac/tests/syntax/alter_quota.py @@ -33,12 +33,12 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER user0") node.query(f"CREATE ROLE role0") - with Scenario("I alter quota with no options", flags=TE, requirements=[ + with Scenario("I alter quota with no options", requirements=[ RQ_SRS_006_RBAC_Quota_Alter("1.0")]): with When("I alter quota"): node.query("ALTER QUOTA quota0") - with Scenario("I alter quota that does not exist, throws an exception", flags=TE, requirements=[ + with Scenario("I alter quota that does not exist, throws an exception", requirements=[ RQ_SRS_006_RBAC_Quota_Alter("1.0")]): quota = "quota1" cleanup_quota(quota) @@ -47,11 +47,11 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER QUOTA {quota}", exitcode=exitcode, message=message) del quota - with Scenario("I alter quota with if exists, quota does exist", flags=TE, requirements=[ + with Scenario("I alter quota with if exists, quota does exist", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_IfExists("1.0")]): node.query("ALTER QUOTA IF EXISTS quota0") - with Scenario("I alter quota with if exists, quota does not exist", flags=TE, requirements=[ + with Scenario("I alter quota with if exists, quota does not exist", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_IfExists("1.0")]): quota = "quota1" cleanup_quota(quota) @@ -59,11 +59,11 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER QUOTA IF EXISTS {quota}") del quota - with Scenario("I alter quota using rename, target available", flags=TE, requirements=[ + with Scenario("I alter quota using rename, target available", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Rename("1.0")]): node.query("ALTER QUOTA quota0 RENAME TO quota0") - with Scenario("I alter quota using rename, target unavailable", flags=TE, requirements=[ + with Scenario("I alter quota using rename, target unavailable", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Rename("1.0")]): new_quota = "quota1" @@ -82,20 +82,20 @@ def feature(self, node="clickhouse1"): keys = ['none', 'user name', 'ip address', 'client key', 'client key or user name', 'client key or ip address'] for key in keys: - with Scenario(f"I alter quota keyed by {key}", flags=TE, requirements=[ + with Scenario(f"I alter quota keyed by {key}", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_KeyedBy("1.0"), RQ_SRS_006_RBAC_Quota_Alter_KeyedByOptions("1.0")]): with When("I alter quota with a key"): node.query(f"ALTER QUOTA quota0 KEYED BY '{key}'") - with Scenario("I alter quota for randomized interval", flags=TE, requirements=[ + with Scenario("I alter quota for randomized interval", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Interval_Randomized("1.0")]): with When("I alter quota on a randomized interval"): node.query("ALTER QUOTA quota0 FOR RANDOMIZED INTERVAL 1 DAY NO LIMITS") intervals = ['SECOND', 'MINUTE', 'HOUR', 'DAY', 'MONTH'] for i, interval in enumerate(intervals): - with Scenario(f"I alter quota for interval {interval}", flags=TE, requirements=[ + with Scenario(f"I alter quota for interval {interval}", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Interval("1.0")]): with When(f"I alter quota for {interval}"): node.query(f"ALTER QUOTA quota0 FOR INTERVAL 1 {interval} NO LIMITS") @@ -104,7 +104,7 @@ def feature(self, node="clickhouse1"): 'MAX RESULT BYTES', 'MAX READ ROWS', 'MAX READ BYTES', 'MAX EXECUTION TIME', 'NO LIMITS', 'TRACKING ONLY'] for i, constraint in enumerate(constraints): - with Scenario(f"I alter quota for {constraint.lower()}", flags=TE, requirements=[ + with Scenario(f"I alter quota for {constraint.lower()}", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Queries("1.0"), RQ_SRS_006_RBAC_Quota_Alter_Errors("1.0"), RQ_SRS_006_RBAC_Quota_Alter_ResultRows("1.0"), @@ -117,7 +117,7 @@ def feature(self, node="clickhouse1"): with When("I alter quota for a constraint"): node.query(f"ALTER QUOTA quota0 FOR INTERVAL 1 DAY {constraint}{' 1024' if constraint.startswith('MAX') else ''}") - with Scenario("I create quota for multiple constraints", flags=TE, requirements=[ + with Scenario("I create quota for multiple constraints", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Interval("1.0"), RQ_SRS_006_RBAC_Quota_Alter_Queries("1.0")]): node.query("ALTER QUOTA quota0 \ @@ -125,12 +125,12 @@ def feature(self, node="clickhouse1"): FOR INTERVAL 2 DAY MAX QUERIES 124, \ FOR INTERVAL 1 MONTH TRACKING ONLY") - with Scenario("I alter quota to assign to one role", flags=TE, requirements=[ + with Scenario("I alter quota to assign to one role", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Assignment("1.0")]): with When("I alter quota to a role"): node.query("ALTER QUOTA quota0 TO role0") - with Scenario("I alter quota to assign to role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter quota to assign to role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Assignment("1.0")]): role = "role1" with Given(f"I drop {role} if it exists"): @@ -140,7 +140,7 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER QUOTA quota0 TO {role}", exitcode=exitcode, message=message) del role - with Scenario("I alter quota to assign to all except role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter quota to assign to all except role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Assignment("1.0")]): role = "role1" with Given(f"I drop {role} if it exists"): @@ -150,32 +150,32 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER QUOTA quota0 TO ALL EXCEPT {role}", exitcode=exitcode, message=message) del role - with Scenario("I alter quota to assign to one role and one user", flags=TE, requirements=[ + with Scenario("I alter quota to assign to one role and one user", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Assignment("1.0")]): with When("I alter quota to a role and a user"): node.query("ALTER QUOTA quota0 TO role0, user0") - with Scenario("I alter quota assigned to none", flags=TE, requirements=[ + with Scenario("I alter quota assigned to none", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Assignment_None("1.0")]): with When("I alter quota to none"): node.query("ALTER QUOTA quota0 TO NONE") - with Scenario("I alter quota to assign to all", flags=TE, requirements=[ + with Scenario("I alter quota to assign to all", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Assignment_All("1.0")]): with When("I alter quota to all"): node.query("ALTER QUOTA quota0 TO ALL") - with Scenario("I alter quota to assign to all except one role", flags=TE, requirements=[ + with Scenario("I alter quota to assign to all except one role", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Assignment_Except("1.0")]): with When("I alter quota to all except one role"): node.query("ALTER QUOTA quota0 TO ALL EXCEPT role0") - with Scenario("I alter quota to assign to all except multiple roles", flags=TE, requirements=[ + with Scenario("I alter quota to assign to all except multiple roles", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Assignment_Except("1.0")]): with When("I alter quota to all except one multiple roles"): node.query("ALTER QUOTA quota0 TO ALL EXCEPT role0, user0") - with Scenario("I alter quota on cluster", flags=TE, requirements=[ + with Scenario("I alter quota on cluster", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Cluster("1.0")]): try: with Given("I have a quota on a cluster"): @@ -193,7 +193,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the quota"): node.query("DROP QUOTA IF EXISTS quota1 ON CLUSTER sharded_cluster") - with Scenario("I alter quota on nonexistent cluster, throws exception", flags=TE, requirements=[ + with Scenario("I alter quota on nonexistent cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_Quota_Alter_Cluster("1.0")]): with When("I run alter quota on a cluster"): exitcode, message = errors.cluster_not_found("fake_cluster") diff --git a/tests/testflows/rbac/tests/syntax/alter_role.py b/tests/testflows/rbac/tests/syntax/alter_role.py index b1e66fb5893..5068302fc84 100755 --- a/tests/testflows/rbac/tests/syntax/alter_role.py +++ b/tests/testflows/rbac/tests/syntax/alter_role.py @@ -38,13 +38,13 @@ def feature(self, node="clickhouse1"): with Given(f"I ensure that role {role} does not exist"): node.query(f"DROP ROLE IF EXISTS {role}") - with Scenario("I alter role with no options", flags=TE, requirements=[ + with Scenario("I alter role with no options", requirements=[ RQ_SRS_006_RBAC_Role_Alter("1.0")]): with setup("role0"): with When("I alter role"): node.query("ALTER ROLE role0") - with Scenario("I alter role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_Role_Alter("1.0")]): role = "role0" cleanup_role(role) @@ -53,13 +53,13 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER ROLE {role}", exitcode=exitcode, message=message) del role - with Scenario("I alter role if exists, role does exist", flags=TE, requirements=[ + with Scenario("I alter role if exists, role does exist", requirements=[ RQ_SRS_006_RBAC_Role_Alter_IfExists("1.0")]): with setup("role1"): with When("I alter role with if exists"): node.query("ALTER ROLE IF EXISTS role1") - with Scenario("I alter role if exists, role does not exist", flags=TE, requirements=[ + with Scenario("I alter role if exists, role does not exist", requirements=[ RQ_SRS_006_RBAC_Role_Alter_IfExists("1.0")]): role = "role0" cleanup_role(role) @@ -67,7 +67,7 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER ROLE IF EXISTS {role}") del role - with Scenario("I alter role on cluster", flags=TE, requirements=[ + with Scenario("I alter role on cluster", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Cluster("1.0")]): try: with Given("I have a role on a cluster"): @@ -82,13 +82,13 @@ def feature(self, node="clickhouse1"): with Finally("I drop the role"): node.query("DROP ROLE IF EXISTS role1,role2 ON CLUSTER sharded_cluster") - with Scenario("I alter role on nonexistent cluster, throws exception", flags=TE, requirements=[ + with Scenario("I alter role on nonexistent cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Cluster("1.0")]): with When("I run alter role on a cluster"): exitcode, message = errors.cluster_not_found("fake_cluster") node.query("ALTER ROLE role1 ON CLUSTER fake_cluster", exitcode=exitcode, message=message) - with Scenario("I alter role to rename, new name is available", flags=TE, requirements=[ + with Scenario("I alter role to rename, new name is available", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Rename("1.0")]): with setup("role2"): new_role = "role3" @@ -102,7 +102,7 @@ def feature(self, node="clickhouse1"): node.query(f"DROP ROLE IF EXISTS {new_role}") del new_role - with Scenario("I alter role to rename, new name is not available, throws exception", flags=TE, requirements=[ + with Scenario("I alter role to rename, new name is not available, throws exception", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Rename("1.0")]): with setup("role2a"): new_role = "role3a" @@ -117,13 +117,13 @@ def feature(self, node="clickhouse1"): node.query(f"DROP ROLE IF EXISTS {new_role}") del new_role - with Scenario("I alter role settings profile", flags=TE, requirements=[ + with Scenario("I alter role settings profile", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role4"): with When("I alter role with settings profile"): node.query("ALTER ROLE role4 SETTINGS PROFILE default, max_memory_usage=10000000 READONLY") - with Scenario("I alter role settings profile, profile does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter role settings profile, profile does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role4a"): with Given("I ensure profile profile0 does not exist"): @@ -132,20 +132,20 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.settings_profile_not_found_in_disk("profile0") node.query("ALTER ROLE role4a SETTINGS PROFILE profile0", exitcode=exitcode, message=message) - with Scenario("I alter role settings profile multiple", flags=TE, requirements=[ + with Scenario("I alter role settings profile multiple", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role4b", profile="profile0"): with When("I alter role with multiple profiles"): node.query("ALTER ROLE role4b SETTINGS PROFILE default, PROFILE profile0, \ max_memory_usage=10000000 READONLY") - with Scenario("I alter role settings without profile", flags=TE, requirements=[ + with Scenario("I alter role settings without profile", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role5"): with When("I alter role with settings and no profile"): node.query("ALTER ROLE role5 SETTINGS max_memory_usage=10000000 READONLY") - with Scenario("I alter role settings, variable does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter role settings, variable does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role5a"): with When("I alter role using settings and nonexistent value"): @@ -153,33 +153,33 @@ def feature(self, node="clickhouse1"): node.query("ALTER ROLE role5a SETTINGS fake_setting = 100000001", exitcode=exitcode, message=message) - with Scenario("I alter role settings without profile multiple", flags=TE, requirements=[ + with Scenario("I alter role settings without profile multiple", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role6"): with When("I alter role with multiple settings and no profile"): node.query("ALTER ROLE role6 SETTINGS max_memory_usage=10000000 READONLY, \ max_rows_to_read MIN 20 MAX 25") - with Scenario("I alter role settings with multiple profiles multiple variables", flags=TE, requirements=[ + with Scenario("I alter role settings with multiple profiles multiple variables", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role7", profile="profile1"): with When("I alter role with multiple settings and profiles"): node.query("ALTER ROLE role7 SETTINGS PROFILE default, PROFILE profile1, \ max_memory_usage=10000000 READONLY, max_rows_to_read MIN 20 MAX 25") - with Scenario("I alter role settings readonly", flags=TE, requirements=[ + with Scenario("I alter role settings readonly", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role8"): with When("I alter role with readonly"): node.query("ALTER ROLE role8 SETTINGS max_memory_usage READONLY") - with Scenario("I alter role settings writable", flags=TE, requirements=[ + with Scenario("I alter role settings writable", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role9"): with When("I alter role with writable"): node.query("ALTER ROLE role9 SETTINGS max_memory_usage WRITABLE") - with Scenario("I alter role settings min, with and without = sign", flags=TE, requirements=[ + with Scenario("I alter role settings min, with and without = sign", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role10"): with When("I set min, no equals"): @@ -187,7 +187,7 @@ def feature(self, node="clickhouse1"): with When("I set min, yes equals"): node.query("ALTER ROLE role10 SETTINGS max_memory_usage MIN = 200") - with Scenario("I alter role settings max, with and without = sign", flags=TE, requirements=[ + with Scenario("I alter role settings max, with and without = sign", requirements=[ RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]): with setup("role11"): with When("I set max, no equals"): diff --git a/tests/testflows/rbac/tests/syntax/alter_row_policy.py b/tests/testflows/rbac/tests/syntax/alter_row_policy.py index 7fbed4a63c4..6422a81fec2 100755 --- a/tests/testflows/rbac/tests/syntax/alter_row_policy.py +++ b/tests/testflows/rbac/tests/syntax/alter_row_policy.py @@ -42,21 +42,21 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROLE role0") node.query(f"CREATE ROLE role1") - with Scenario("I alter row policy with no options", flags=TE, requirements=[ + with Scenario("I alter row policy with no options", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy0"): with When("I alter row policy"): node.query("ALTER ROW POLICY policy0 ON default.foo") - with Scenario("I alter row policy using short syntax with no options", flags=TE, requirements=[ + with Scenario("I alter row policy using short syntax with no options", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy1"): with When("I alter row policy short form"): node.query("ALTER POLICY policy1 ON default.foo") - with Scenario("I alter row policy, does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter row policy, does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): policy = "policy2" @@ -66,14 +66,14 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER ROW POLICY {policy} ON default.foo", exitcode=exitcode, message=message) del policy - with Scenario("I alter row policy if exists", flags=TE, requirements=[ + with Scenario("I alter row policy if exists", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_IfExists("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy2"): with When("I alter row policy using if exists"): node.query("ALTER ROW POLICY IF EXISTS policy2 ON default.foo") - with Scenario("I alter row policy if exists, policy does not exist", flags=TE, requirements=[ + with Scenario("I alter row policy if exists, policy does not exist", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_IfExists("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): policy = "policy2" @@ -82,14 +82,14 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER ROW POLICY IF EXISTS {policy} ON default.foo") del policy - with Scenario("I alter row policy to rename, target available", flags=TE, requirements=[ + with Scenario("I alter row policy to rename, target available", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Rename("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy3"): with When("I alter row policy with rename"): node.query("ALTER ROW POLICY policy3 ON default.foo RENAME TO policy3") - with Scenario("I alter row policy to rename, target unavailable", flags=TE, requirements=[ + with Scenario("I alter row policy to rename, target unavailable", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Rename("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy3"): @@ -106,49 +106,49 @@ def feature(self, node="clickhouse1"): node.query(f"DROP ROW POLICY IF EXISTS {new_policy} ON default.foo") del new_policy - with Scenario("I alter row policy to permissive", flags=TE, requirements=[ + with Scenario("I alter row policy to permissive", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Permissive("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy4"): with When("I alter row policy as permissive"): node.query("ALTER ROW POLICY policy4 ON default.foo AS PERMISSIVE") - with Scenario("I alter row policy to restrictive", flags=TE, requirements=[ + with Scenario("I alter row policy to restrictive", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Restrictive("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy5"): with When("I alter row policy as restrictive"): node.query("ALTER ROW POLICY policy5 ON default.foo AS RESTRICTIVE") - with Scenario("I alter row policy for select", flags=TE, requirements=[ + with Scenario("I alter row policy for select", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_ForSelect("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy6"): with When("I alter row policy using for select"): node.query("ALTER ROW POLICY policy6 ON default.foo FOR SELECT USING x > 10") - with Scenario("I alter row policy using condition", flags=TE, requirements=[ + with Scenario("I alter row policy using condition", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Condition("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy6"): with When("I alter row policy wtih condition"): node.query("ALTER ROW POLICY policy6 ON default.foo USING x > 10") - with Scenario("I alter row policy using condition none", flags=TE, requirements=[ + with Scenario("I alter row policy using condition none", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Condition_None("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy7"): with When("I alter row policy using no condition"): node.query("ALTER ROW POLICY policy7 ON default.foo USING NONE") - with Scenario("I alter row policy to one role", flags=TE, requirements=[ + with Scenario("I alter row policy to one role", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy8"): with When("I alter row policy to a role"): node.query("ALTER ROW POLICY policy8 ON default.foo TO role0") - with Scenario("I alter row policy to assign to role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter row policy to assign to role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment("1.0")]): role = "role2" with cleanup("policy8a"): @@ -159,7 +159,7 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER ROW POLICY policy8a ON default.foo TO {role}", exitcode=exitcode, message=message) del role - with Scenario("I alter row policy to assign to all excpet role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter row policy to assign to all excpet role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment("1.0")]): role = "role2" with cleanup("policy8a"): @@ -170,35 +170,35 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER ROW POLICY policy8a ON default.foo TO ALL EXCEPT {role}", exitcode=exitcode, message=message) del role - with Scenario("I alter row policy assigned to multiple roles", flags=TE, requirements=[ + with Scenario("I alter row policy assigned to multiple roles", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy9"): with When("I alter row policy to multiple roles"): node.query("ALTER ROW POLICY policy9 ON default.foo TO role0, role1") - with Scenario("I alter row policy assigned to all", flags=TE, requirements=[ + with Scenario("I alter row policy assigned to all", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_All("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy10"): with When("I alter row policy to all"): node.query("ALTER ROW POLICY policy10 ON default.foo TO ALL") - with Scenario("I alter row policy assigned to all except one role", flags=TE, requirements=[ + with Scenario("I alter row policy assigned to all except one role", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_AllExcept("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy11"): with When("I alter row policy to all except"): node.query("ALTER ROW POLICY policy11 ON default.foo TO ALL EXCEPT role0") - with Scenario("I alter row policy assigned to all except multiple roles", flags=TE, requirements=[ + with Scenario("I alter row policy assigned to all except multiple roles", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_AllExcept("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy12"): with When("I alter row policy to all except multiple roles"): node.query("ALTER ROW POLICY policy12 ON default.foo TO ALL EXCEPT role0, role1") - with Scenario("I alter row policy assigned to none", flags=TE, requirements=[ + with Scenario("I alter row policy assigned to none", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_None("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with cleanup("policy12"): @@ -208,7 +208,7 @@ def feature(self, node="clickhouse1"): # Official syntax: ON CLUSTER cluster_name ON database.table # Working syntax: both orderings of ON CLUSTER and TABLE clauses work - with Scenario("I alter row policy on cluster", flags=TE, requirements=[ + with Scenario("I alter row policy on cluster", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_OnCluster("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): try: @@ -220,14 +220,14 @@ def feature(self, node="clickhouse1"): with Finally("I drop the row policy"): node.query("DROP ROW POLICY IF EXISTS policy13 ON CLUSTER sharded_cluster ON default.foo") - with Scenario("I alter row policy on fake cluster, throws exception", flags=TE, requirements=[ + with Scenario("I alter row policy on fake cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_OnCluster("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): with When("I run alter row policy command"): exitcode, message = errors.cluster_not_found("fake_cluster") node.query("ALTER ROW POLICY policy13 ON CLUSTER fake_cluster ON default.foo", exitcode=exitcode, message=message) - with Scenario("I alter row policy on cluster after table", flags=TE, requirements=[ + with Scenario("I alter row policy on cluster after table", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Alter_OnCluster("1.0"), RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]): try: diff --git a/tests/testflows/rbac/tests/syntax/alter_settings_profile.py b/tests/testflows/rbac/tests/syntax/alter_settings_profile.py index 4222b27954d..4533f6aea65 100755 --- a/tests/testflows/rbac/tests/syntax/alter_settings_profile.py +++ b/tests/testflows/rbac/tests/syntax/alter_settings_profile.py @@ -31,15 +31,15 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER user0") node.query(f"CREATE ROLE role0") - with Scenario("I alter settings profile with no options", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter("1.0")]): + with Scenario("I alter settings profile with no options", requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter("1.0")]): with When("I alter settings profile"): node.query("ALTER SETTINGS PROFILE profile0") - with Scenario("I alter settings profile short form", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter("1.0")]): + with Scenario("I alter settings profile short form", requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter("1.0")]): with When("I short form alter settings profile"): node.query("ALTER PROFILE profile0") - with Scenario("I alter settings profile that does not exist, throws exception", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter("1.0")]): + with Scenario("I alter settings profile that does not exist, throws exception", requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter("1.0")]): profile = "profile1" cleanup_profile(profile) @@ -48,11 +48,11 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER SETTINGS PROFILE {profile}", exitcode=exitcode, message=message) del profile - with Scenario("I alter settings profile if exists", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_IfExists("1.0")]): + with Scenario("I alter settings profile if exists", requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_IfExists("1.0")]): with When("I alter settings profile using if exists"): node.query("ALTER SETTINGS PROFILE IF EXISTS profile0") - with Scenario("I alter settings profile if exists, profile does not exist", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_IfExists("1.0")]): + with Scenario("I alter settings profile if exists, profile does not exist", requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_IfExists("1.0")]): profile = "profile1" cleanup_profile(profile) @@ -61,11 +61,11 @@ def feature(self, node="clickhouse1"): del profile - with Scenario("I alter settings profile to rename, target available", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_Rename("1.0")]): + with Scenario("I alter settings profile to rename, target available", requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_Rename("1.0")]): with When("I alter settings profile by renaming it"): node.query("ALTER SETTINGS PROFILE profile0 RENAME TO profile0") - with Scenario("I alter settings profile to rename, target unavailable", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_Rename("1.0")]): + with Scenario("I alter settings profile to rename, target unavailable", requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_Rename("1.0")]): new_profile = "profile1" try: @@ -81,52 +81,52 @@ def feature(self, node="clickhouse1"): del new_profile - with Scenario("I alter settings profile with a setting value", flags=TE, requirements=[ + with Scenario("I alter settings profile with a setting value", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables("1.0"), RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value("1.0")]): with When("I alter settings profile using settings"): node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage = 100000001") - with Scenario("I alter settings profile with a setting value, does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter settings profile with a setting value, does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables("1.0"), RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value("1.0")]): with When("I alter settings profile using settings and nonexistent value"): exitcode, message = errors.unknown_setting("fake_setting") node.query("ALTER SETTINGS PROFILE profile0 SETTINGS fake_setting = 100000001", exitcode=exitcode, message=message) - with Scenario("I alter settings profile with a min setting value", flags=TE, requirements=[ + with Scenario("I alter settings profile with a min setting value", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints("1.0")]): with When("I alter settings profile using 2 minimum formats"): node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage MIN 100000001") node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage MIN = 100000001") - with Scenario("I alter settings profile with a max setting value", flags=TE, requirements=[ + with Scenario("I alter settings profile with a max setting value", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints("1.0")]): with When("I alter settings profile using 2 maximum formats"): node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage MAX 100000001") node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage MAX = 100000001") - with Scenario("I alter settings profile with min and max setting values", flags=TE, requirements=[ + with Scenario("I alter settings profile with min and max setting values", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints("1.0")]): with When("I alter settings profile with both min and max"): node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage MIN 100000001 MAX 200000001") - with Scenario("I alter settings profile with a readonly setting", flags=TE, requirements=[ + with Scenario("I alter settings profile with a readonly setting", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints("1.0")]): with When("I alter settings profile with with readonly"): node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage READONLY") - with Scenario("I alter settings profile with a writable setting", flags=TE, requirements=[ + with Scenario("I alter settings profile with a writable setting", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints("1.0")]): with When("I alter settings profile with writable"): node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage WRITABLE") - with Scenario("I alter settings profile with inherited settings", flags=TE, requirements=[ + with Scenario("I alter settings profile with inherited settings", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_Inherit("1.0")]): with When("I alter settings profile with inherit"): node.query("ALTER SETTINGS PROFILE profile0 SETTINGS INHERIT 'default'") - with Scenario("I alter settings profile with inherit, parent profile does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter settings profile with inherit, parent profile does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_Inherit("1.0")]): profile = "profile3" with Given(f"I ensure that profile {profile} does not exist"): @@ -136,7 +136,7 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER PROFILE profile0 SETTINGS INHERIT {profile}", exitcode=exitcode, message=message) del profile - with Scenario("I alter settings profile with multiple settings", flags=TE, requirements=[ + with Scenario("I alter settings profile with multiple settings", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables("1.0"), RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value("1.0")]): with When("I alter settings profile with multiple settings"): @@ -144,7 +144,7 @@ def feature(self, node="clickhouse1"): " SETTINGS max_memory_usage = 100000001" " SETTINGS max_memory_usage_for_user = 100000001") - with Scenario("I alter settings profile with multiple settings short form", flags=TE, requirements=[ + with Scenario("I alter settings profile with multiple settings short form", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables("1.0"), RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value("1.0")]): with When("I alter settings profile with short form multiple settings"): @@ -152,12 +152,12 @@ def feature(self, node="clickhouse1"): " SETTINGS max_memory_usage = 100000001," " max_memory_usage_for_user = 100000001") - with Scenario("I alter settings profile assigned to one role", flags=TE, requirements=[ + with Scenario("I alter settings profile assigned to one role", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment("1.0")]): with When("I alter settings profile with assignment to role"): node.query("ALTER SETTINGS PROFILE profile0 TO role0") - with Scenario("I alter settings profile to assign to role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter settings profile to assign to role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment("1.0")]): role = "role1" with Given(f"I drop {role} if it exists"): @@ -167,7 +167,7 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER SETTINGS PROFILE profile0 TO {role}", exitcode=exitcode, message=message) del role - with Scenario("I alter settings profile to assign to all except role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter settings profile to assign to all except role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment("1.0")]): role = "role1" with Given(f"I drop {role} if it exists"): @@ -177,32 +177,32 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER SETTINGS PROFILE profile0 TO ALL EXCEPT {role}", exitcode=exitcode, message=message) del role - with Scenario("I alter settings profile assigned to multiple roles", flags=TE, requirements=[ + with Scenario("I alter settings profile assigned to multiple roles", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment("1.0")]): with When("I alter settings profile with assignment to multiple roles"): node.query("ALTER SETTINGS PROFILE profile0 TO role0, user0") - with Scenario("I alter settings profile assigned to all", flags=TE, requirements=[ + with Scenario("I alter settings profile assigned to all", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_All("1.0")]): with When("I alter settings profile with assignment to all"): node.query("ALTER SETTINGS PROFILE profile0 TO ALL") - with Scenario("I alter settings profile assigned to all except one role", flags=TE, requirements=[ + with Scenario("I alter settings profile assigned to all except one role", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_AllExcept("1.0")]): with When("I alter settings profile with assignment to all except a role"): node.query("ALTER SETTINGS PROFILE profile0 TO ALL EXCEPT role0") - with Scenario("I alter settings profile assigned to all except multiple roles", flags=TE, requirements=[ + with Scenario("I alter settings profile assigned to all except multiple roles", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_AllExcept("1.0")]): with When("I alter settings profile with assignmentto all except multiple roles"): node.query("ALTER SETTINGS PROFILE profile0 TO ALL EXCEPT role0, user0") - with Scenario("I alter settings profile assigned to none", flags=TE, requirements=[ + with Scenario("I alter settings profile assigned to none", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_None("1.0")]): with When("I alter settings profile with assignment to none"): node.query("ALTER SETTINGS PROFILE profile0 TO NONE") - with Scenario("I alter settings profile on cluster", flags=TE, requirements=[ + with Scenario("I alter settings profile on cluster", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_OnCluster("1.0")]): try: with Given("I have a settings profile on cluster"): @@ -219,7 +219,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the settings profile"): node.query("DROP SETTINGS PROFILE IF EXISTS profile1 ON CLUSTER sharded_cluster") - with Scenario("I alter settings profile on fake cluster, throws exception", flags=TE, requirements=[ + with Scenario("I alter settings profile on fake cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_OnCluster("1.0")]): with When("I run alter settings profile command"): exitcode, message = errors.cluster_not_found("fake_cluster") diff --git a/tests/testflows/rbac/tests/syntax/alter_user.py b/tests/testflows/rbac/tests/syntax/alter_user.py index 8a7ce8724eb..cf8a13008c9 100755 --- a/tests/testflows/rbac/tests/syntax/alter_user.py +++ b/tests/testflows/rbac/tests/syntax/alter_user.py @@ -30,28 +30,28 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER OR REPLACE {user}") yield finally: - with Finally("I drop the user", flags=TE): + with Finally("I drop the user"): node.query(f"DROP USER IF EXISTS {user}") - with Scenario("I alter user, base command", flags=TE, requirements=[ + with Scenario("I alter user, base command", requirements=[ RQ_SRS_006_RBAC_User_Alter("1.0")]): with setup("user0"): with When("I alter user"): node.query("ALTER USER user0") - with Scenario("I alter user that does not exist without if exists, throws exception", flags=TE, requirements=[ + with Scenario("I alter user that does not exist without if exists, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Alter("1.0")]): with When("I run alter user command, expecting error 192"): exitcode, message = errors.user_not_found_in_disk(name="user0") node.query(f"ALTER USER user0",exitcode=exitcode, message=message) - with Scenario("I alter user with if exists", flags=TE, requirements=[ + with Scenario("I alter user with if exists", requirements=[ RQ_SRS_006_RBAC_User_Alter_IfExists("1.0")]): with setup("user0"): with When(f"I alter user with if exists"): node.query(f"ALTER USER IF EXISTS user0") - with Scenario("I alter user that does not exist with if exists", flags=TE, requirements=[ + with Scenario("I alter user that does not exist with if exists", requirements=[ RQ_SRS_006_RBAC_User_Alter_IfExists("1.0")]): user = "user0" with Given("I don't have a user"): @@ -60,7 +60,7 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER USER IF EXISTS {user}") del user - with Scenario("I alter user on a cluster", flags=TE, requirements=[ + with Scenario("I alter user on a cluster", requirements=[ RQ_SRS_006_RBAC_User_Alter_Cluster("1.0")]): with Given("I have a user on a cluster"): node.query("CREATE USER OR REPLACE user0 ON CLUSTER sharded_cluster") @@ -69,19 +69,19 @@ def feature(self, node="clickhouse1"): with Finally("I drop user from cluster"): node.query("DROP USER IF EXISTS user0 ON CLUSTER sharded_cluster") - with Scenario("I alter user on a fake cluster, throws exception", flags=TE, requirements=[ + with Scenario("I alter user on a fake cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Alter_Cluster("1.0")]): with When("I alter user on a fake cluster"): exitcode, message = errors.cluster_not_found("fake_cluster") node.query("ALTER USER user0 ON CLUSTER fake_cluster", exitcode=exitcode, message=message) - with Scenario("I alter user to rename, target available", flags=TE, requirements=[ + with Scenario("I alter user to rename, target available", requirements=[ RQ_SRS_006_RBAC_User_Alter_Rename("1.0")]): with setup("user15"): with When("I alter user name"): node.query("ALTER USER user15 RENAME TO user15") - with Scenario("I alter user to rename, target unavailable", flags=TE, requirements=[ + with Scenario("I alter user to rename, target unavailable", requirements=[ RQ_SRS_006_RBAC_User_Alter_Rename("1.0")]): with setup("user15"): new_user = "user16" @@ -96,20 +96,20 @@ def feature(self, node="clickhouse1"): node.query(f"DROP USER IF EXISTS {new_user}") del new_user - with Scenario("I alter user password plaintext password", flags=TE, requirements=[ + with Scenario("I alter user password plaintext password", requirements=[ RQ_SRS_006_RBAC_User_Alter_Password_PlainText("1.0")]): with setup("user1"): with When("I alter user with plaintext password"): node.query("ALTER USER user1 IDENTIFIED WITH PLAINTEXT_PASSWORD BY 'mypassword'", step=When) - with Scenario("I alter user password to sha256", flags=TE, requirements=[ + with Scenario("I alter user password to sha256", requirements=[ RQ_SRS_006_RBAC_User_Alter_Password_Sha256Password("1.0")]): with setup("user2"): with When("I alter user with sha256_password"): password = hashlib.sha256("mypassword".encode("utf-8")).hexdigest() node.query(f"ALTER USER user2 IDENTIFIED WITH SHA256_PASSWORD BY '{password}'",step=When) - with Scenario("I alter user password to double_sha1_password", flags=TE, requirements=[ + with Scenario("I alter user password to double_sha1_password", requirements=[ RQ_SRS_006_RBAC_User_Alter_Password_DoubleSha1Password("1.0")]): with setup("user3"): with When("I alter user with double_sha1_password"): @@ -118,56 +118,56 @@ def feature(self, node="clickhouse1"): password = hash(hash("mypassword")) node.query(f"ALTER USER user3 IDENTIFIED WITH DOUBLE_SHA1_PASSWORD BY '{password}'", step=When) - with Scenario("I alter user host local", flags=TE, requirements=[ + with Scenario("I alter user host local", requirements=[ RQ_SRS_006_RBAC_User_Alter_Host_Local("1.0")]): with setup("user4"): with When("I alter user with host local"): node.query("ALTER USER user4 HOST LOCAL") - with Scenario("I alter user host name", flags=TE, requirements=[ + with Scenario("I alter user host name", requirements=[ RQ_SRS_006_RBAC_User_Alter_Host_Name("1.0")]): with setup("user5"): with When("I alter user with host name"): node.query("ALTER USER user5 HOST NAME 'localhost', NAME 'clickhouse.com'") - with Scenario("I alter user host regexp", flags=TE, requirements=[ + with Scenario("I alter user host regexp", requirements=[ RQ_SRS_006_RBAC_User_Alter_Host_Regexp("1.0")]): with setup("user6"): with When("I alter user with host regexp"): node.query("ALTER USER user6 HOST REGEXP 'lo..*host', 'lo*host'") - with Scenario("I alter user host ip", flags=TE, requirements=[ + with Scenario("I alter user host ip", requirements=[ RQ_SRS_006_RBAC_User_Alter_Host_IP("1.0")]): with setup("user7"): with When("I alter user with host ip"): node.query("ALTER USER user7 HOST IP '127.0.0.1', IP '127.0.0.2'") - with Scenario("I alter user host like", flags=TE, requirements=[ + with Scenario("I alter user host like", requirements=[ RQ_SRS_006_RBAC_User_Alter_Host_Like("1.0")]): with setup("user8"): with When("I alter user with host like"): node.query("ALTER USER user8 HOST LIKE '%.clickhouse.com'") - with Scenario("I alter user host any", flags=TE, requirements=[ + with Scenario("I alter user host any", requirements=[ RQ_SRS_006_RBAC_User_Alter_Host_Any("1.0")]): with setup("user9"): with When("I alter user with host any"): node.query("ALTER USER user9 HOST ANY") - with Scenario("I alter user host many hosts", flags=TE, requirements=[ + with Scenario("I alter user host many hosts", requirements=[ RQ_SRS_006_RBAC_User_Alter_Host_Like("1.0")]): with setup("user11"): with When("I alter user with multiple hosts"): node.query("ALTER USER user11 HOST LIKE '%.clickhouse.com', \ IP '127.0.0.2', NAME 'localhost', REGEXP 'lo*host'") - with Scenario("I alter user default role set to none", flags=TE, requirements=[ + with Scenario("I alter user default role set to none", requirements=[ RQ_SRS_006_RBAC_User_Alter_Host_None("1.0")]): with setup("user12"): with When("I alter user with default role none"): node.query("ALTER USER user12 DEFAULT ROLE NONE") - with Scenario("I alter user default role set to all", flags=TE, requirements=[ + with Scenario("I alter user default role set to all", requirements=[ RQ_SRS_006_RBAC_User_Alter_DefaultRole_All("1.0")]): with setup("user13"): with When("I alter user with all roles set to default"): @@ -183,7 +183,7 @@ def feature(self, node="clickhouse1"): with Finally(f"I drop the role {role}", flags=TE): node.query(f"DROP ROLE IF EXISTS {role}") - with Scenario("I alter user default role", flags=TE, requirements=[ + with Scenario("I alter user default role", requirements=[ RQ_SRS_006_RBAC_User_Alter_DefaultRole("1.0")]): with setup("user14"), setup_role("role2"): with Given("I have a user with a role"): @@ -191,7 +191,7 @@ def feature(self, node="clickhouse1"): with When("I alter user default role"): node.query("ALTER USER user14 DEFAULT ROLE role2") - with Scenario("I alter user default role, setting default role", flags=TE, requirements=[ + with Scenario("I alter user default role, setting default role", requirements=[ RQ_SRS_006_RBAC_User_Alter_DefaultRole("1.0")]): with setup("user14a"), setup_role("default"): with Given("I grant default role to the user"): @@ -199,7 +199,7 @@ def feature(self, node="clickhouse1"): with When("I alter user default role"): node.query("ALTER USER user14a DEFAULT ROLE default") - with Scenario("I alter user default role, role doesn't exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter user default role, role doesn't exist, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Alter_DefaultRole("1.0")]): with setup("user12"): role = "role0" @@ -210,7 +210,7 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER USER user12 DEFAULT ROLE {role}",exitcode=exitcode, message=message) del role - with Scenario("I alter user default role, all except role doesn't exist, throws exception", flags=TE, requirements=[ + with Scenario("I alter user default role, all except role doesn't exist, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Alter_DefaultRole("1.0")]): with setup("user12"): role = "role0" @@ -221,7 +221,7 @@ def feature(self, node="clickhouse1"): node.query(f"ALTER USER user12 DEFAULT ROLE ALL EXCEPT {role}",exitcode=exitcode, message=message) del role - with Scenario("I alter user default role multiple", flags=TE, requirements=[ + with Scenario("I alter user default role multiple", requirements=[ RQ_SRS_006_RBAC_User_Alter_DefaultRole("1.0")]): with setup("user15"), setup_role("second"), setup_role("third"): with Given("I have a user with multiple roles"): @@ -229,7 +229,7 @@ def feature(self, node="clickhouse1"): with When("I alter user default role to second, third"): node.query("ALTER USER user15 DEFAULT ROLE second, third") - with Scenario("I alter user default role set to all except", flags=TE, requirements=[ + with Scenario("I alter user default role set to all except", requirements=[ RQ_SRS_006_RBAC_User_Alter_DefaultRole_AllExcept("1.0")]): with setup("user16"), setup_role("second"): with Given("I have a user with a role"): @@ -237,7 +237,7 @@ def feature(self, node="clickhouse1"): with When("I alter user default role"): node.query("ALTER USER user16 DEFAULT ROLE ALL EXCEPT second") - with Scenario("I alter user default role multiple all except", flags=TE, requirements=[ + with Scenario("I alter user default role multiple all except", requirements=[ RQ_SRS_006_RBAC_User_Alter_DefaultRole_AllExcept("1.0")]): with setup("user17"), setup_role("second"), setup_role("third"): with Given("I have a user with multiple roles"): @@ -245,7 +245,7 @@ def feature(self, node="clickhouse1"): with When("I alter user default role to all except second"): node.query("ALTER USER user17 DEFAULT ROLE ALL EXCEPT second") - with Scenario("I alter user settings profile", flags=TE, requirements=[ + with Scenario("I alter user settings profile", requirements=[ RQ_SRS_006_RBAC_User_Alter_Settings("1.0"), \ RQ_SRS_006_RBAC_User_Alter_Settings_Profile("1.0")]): with setup("user18"): @@ -258,7 +258,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the profile"): node.query(f"DROP SETTINGS PROFILE profile10") - with Scenario("I alter user settings profile, fake profile, throws exception", flags=TE, requirements=[ + with Scenario("I alter user settings profile, fake profile, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Alter_Settings("1.0"), RQ_SRS_006_RBAC_User_Alter_Settings_Profile("1.0")]): with setup("user18a"): @@ -270,14 +270,14 @@ def feature(self, node="clickhouse1"): node.query("ALTER USER user18a SETTINGS PROFILE profile0", exitcode=exitcode, message=message) del profile - with Scenario("I alter user settings with a fake setting, throws exception", flags=TE, requirements=[ + with Scenario("I alter user settings with a fake setting, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Alter_Settings("1.0")]): with setup("user18b"): with When("I alter settings profile using settings and nonexistent value"): exitcode, message = errors.unknown_setting("fake_setting") node.query("ALTER USER user18b SETTINGS fake_setting = 100000001", exitcode=exitcode, message=message) - with Scenario("I alter user settings without profile (no equals)", flags=TE, requirements=[ + with Scenario("I alter user settings without profile (no equals)", requirements=[ RQ_SRS_006_RBAC_User_Alter_Settings("1.0"), RQ_SRS_006_RBAC_User_Alter_Settings_Min("1.0"), RQ_SRS_006_RBAC_User_Alter_Settings_Max("1.0")]): @@ -286,7 +286,7 @@ def feature(self, node="clickhouse1"): node.query("ALTER USER user19 SETTINGS max_memory_usage=10000000 MIN 100000 MAX 1000000000 READONLY") #equals sign (=) syntax verify - with Scenario("I alter user settings without profile (yes equals)", flags=TE, requirements=[ + with Scenario("I alter user settings without profile (yes equals)", requirements=[ RQ_SRS_006_RBAC_User_Alter_Settings("1.0"), RQ_SRS_006_RBAC_User_Alter_Settings_Min("1.0"), RQ_SRS_006_RBAC_User_Alter_Settings_Max("1.0")]): @@ -295,7 +295,7 @@ def feature(self, node="clickhouse1"): node.query("ALTER USER user20 SETTINGS max_memory_usage=10000000 MIN=100000 MAX=1000000000 READONLY") #Add requirement to host: add/drop - with Scenario("I alter user to add host", flags=TE, requirements=[ + with Scenario("I alter user to add host", requirements=[ RQ_SRS_006_RBAC_User_Alter_Host_AddDrop("1.0")]): with setup("user21"): with When("I alter user by adding local host"): @@ -309,7 +309,7 @@ def feature(self, node="clickhouse1"): with And("I alter user by adding host name"): node.query("ALTER USER user21 ADD HOST NAME 'localhost'") - with Scenario("I alter user to remove host", flags=TE, requirements=[ + with Scenario("I alter user to remove host", requirements=[ RQ_SRS_006_RBAC_User_Alter_Host_AddDrop("1.0")]): with setup("user22"): with When("I alter user by removing local host"): diff --git a/tests/testflows/rbac/tests/syntax/create_quota.py b/tests/testflows/rbac/tests/syntax/create_quota.py index 4945583a542..33dbbf9c153 100755 --- a/tests/testflows/rbac/tests/syntax/create_quota.py +++ b/tests/testflows/rbac/tests/syntax/create_quota.py @@ -41,13 +41,13 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER user0") node.query(f"CREATE ROLE role0") - with Scenario("I create quota with no options", flags=TE, requirements=[ + with Scenario("I create quota with no options", requirements=[ RQ_SRS_006_RBAC_Quota_Create("1.0")]): with cleanup("quota0"): with When("I create a quota with no options"): node.query("CREATE QUOTA quota0") - with Scenario("I create quota that already exists, throws exception", flags=TE, requirements=[ + with Scenario("I create quota that already exists, throws exception", requirements=[ RQ_SRS_006_RBAC_Quota_Create("1.0")]): quota = "quota0" with cleanup(quota): @@ -57,7 +57,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE QUOTA {quota}", exitcode=exitcode, message=message) del quota - with Scenario("I create quota if not exists, quota does not exist", flags=TE, requirements=[ + with Scenario("I create quota if not exists, quota does not exist", requirements=[ RQ_SRS_006_RBAC_Quota_Create_IfNotExists("1.0")]): quota = "quota1" with cleanup(quota): @@ -65,7 +65,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE QUOTA IF NOT EXISTS {quota}") del quota - with Scenario("I create quota if not exists, quota does exist", flags=TE, requirements=[ + with Scenario("I create quota if not exists, quota does exist", requirements=[ RQ_SRS_006_RBAC_Quota_Create_IfNotExists("1.0")]): quota = "quota1" with cleanup(quota): @@ -74,7 +74,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE QUOTA IF NOT EXISTS {quota}") del quota - with Scenario("I create quota or replace, quota does not exist", flags=TE, requirements=[ + with Scenario("I create quota or replace, quota does not exist", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Replace("1.0")]): quota = "quota2" with cleanup(quota): @@ -82,7 +82,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE QUOTA OR REPLACE {quota}") del quota - with Scenario("I create quota or replace, quota does exist", flags=TE, requirements=[ + with Scenario("I create quota or replace, quota does exist", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Replace("1.0")]): quota = "quota2" with cleanup(quota): @@ -93,7 +93,7 @@ def feature(self, node="clickhouse1"): keys = ['none', 'user name', 'ip address', 'client key', 'client key or user name', 'client key or ip address'] for i, key in enumerate(keys): - with Scenario(f"I create quota keyed by {key}", flags=TE, requirements=[ + with Scenario(f"I create quota keyed by {key}", requirements=[ RQ_SRS_006_RBAC_Quota_Create_KeyedBy("1.0"), RQ_SRS_006_RBAC_Quota_Create_KeyedByOptions("1.0")]): name = f'quota{3 + i}' @@ -101,7 +101,7 @@ def feature(self, node="clickhouse1"): with When(f"I create a quota with {key}"): node.query(f"CREATE QUOTA {name} KEYED BY '{key}'") - with Scenario("I create quota for randomized interval", flags=TE, requirements=[ + with Scenario("I create quota for randomized interval", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Interval_Randomized("1.0")]): with cleanup("quota9"): with When("I create a quota for randomized interval"): @@ -109,7 +109,7 @@ def feature(self, node="clickhouse1"): intervals = ['SECOND', 'MINUTE', 'HOUR', 'DAY', 'MONTH'] for i, interval in enumerate(intervals): - with Scenario(f"I create quota for interval {interval}", flags=TE, requirements=[ + with Scenario(f"I create quota for interval {interval}", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Interval("1.0")]): name = f'quota{10 + i}' with cleanup(name): @@ -120,7 +120,7 @@ def feature(self, node="clickhouse1"): 'MAX RESULT BYTES', 'MAX READ ROWS', 'MAX READ BYTES', 'MAX EXECUTION TIME', 'NO LIMITS', 'TRACKING ONLY'] for i, constraint in enumerate(constraints): - with Scenario(f"I create quota for {constraint.lower()}", flags=TE, requirements=[ + with Scenario(f"I create quota for {constraint.lower()}", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Queries("1.0"), RQ_SRS_006_RBAC_Quota_Create_Errors("1.0"), RQ_SRS_006_RBAC_Quota_Create_ResultRows("1.0"), @@ -135,7 +135,7 @@ def feature(self, node="clickhouse1"): with When(f"I create quota for {constraint.lower()}"): node.query(f"CREATE QUOTA {name} FOR INTERVAL 1 DAY {constraint}{' 1024' if constraint.startswith('MAX') else ''}") - with Scenario("I create quota for multiple constraints", flags=TE, requirements=[ + with Scenario("I create quota for multiple constraints", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Interval("1.0"), RQ_SRS_006_RBAC_Quota_Create_Queries("1.0")]): with cleanup("quota23"): @@ -145,13 +145,13 @@ def feature(self, node="clickhouse1"): FOR INTERVAL 2 DAY MAX QUERIES 124, \ FOR INTERVAL 1 HOUR TRACKING ONLY') - with Scenario("I create quota assigned to one role", flags=TE, requirements=[ + with Scenario("I create quota assigned to one role", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Assignment("1.0")]): with cleanup("quota24"): with When("I create quota for role"): node.query("CREATE QUOTA quota24 TO role0") - with Scenario("I create quota to assign to role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I create quota to assign to role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Assignment("1.0")]): role = "role1" with Given(f"I drop {role} if it exists"): @@ -161,7 +161,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE QUOTA quota0 TO {role}", exitcode=exitcode, message=message) del role - with Scenario("I create quota to assign to all except role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I create quota to assign to all except role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Assignment("1.0")]): role = "role1" with Given(f"I drop {role} if it exists"): @@ -171,36 +171,36 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE QUOTA quota0 TO ALL EXCEPT {role}", exitcode=exitcode, message=message) del role - with Scenario("I create quota assigned to no role", flags=TE, requirements=[ + with Scenario("I create quota assigned to no role", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Assignment_None("1.0")]): with When("I create quota for no role"): node.query("CREATE QUOTA quota24 TO NONE") - with Scenario("I create quota assigned to multiple roles", flags=TE, requirements=[ + with Scenario("I create quota assigned to multiple roles", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Assignment("1.0")]): with cleanup("quota25"): with When("I create quota for multiple roles"): node.query("CREATE QUOTA quota25 TO role0, user0") - with Scenario("I create quota assigned to all", flags=TE,requirements=[ + with Scenario("I create quota assigned to all", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Assignment_All("1.0")]): with cleanup("quota26"): with When("I create quota for all"): node.query("CREATE QUOTA quota26 TO ALL") - with Scenario("I create quota assigned to all except one role", flags=TE, requirements=[ + with Scenario("I create quota assigned to all except one role", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Assignment_Except("1.0")]): with cleanup("quota27"): with When("I create quota for all except one role"): node.query("CREATE QUOTA quota27 TO ALL EXCEPT role0") - with Scenario("I create quota assigned to all except multiple roles", flags=TE, requirements=[ + with Scenario("I create quota assigned to all except multiple roles", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Assignment_Except("1.0")]): with cleanup("quota28"): with When("I create quota for all except multiple roles"): node.query("CREATE QUOTA quota28 TO ALL EXCEPT role0, user0") - with Scenario("I create quota on cluster", flags=TE, requirements=[ + with Scenario("I create quota on cluster", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Cluster("1.0")]): try: with When("I run create quota command on cluster"): @@ -215,7 +215,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the quota from cluster"): node.query("DROP QUOTA IF EXISTS quota29 ON CLUSTER sharded_cluster") - with Scenario("I create quota on nonexistent cluster, throws exception", flags=TE, requirements=[ + with Scenario("I create quota on nonexistent cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_Quota_Create_Cluster("1.0")]): with When("I run create quota on a cluster"): exitcode, message = errors.cluster_not_found("fake_cluster") diff --git a/tests/testflows/rbac/tests/syntax/create_role.py b/tests/testflows/rbac/tests/syntax/create_role.py index 86db48691bd..1cb10077570 100755 --- a/tests/testflows/rbac/tests/syntax/create_role.py +++ b/tests/testflows/rbac/tests/syntax/create_role.py @@ -32,13 +32,13 @@ def feature(self, node="clickhouse1"): with Given(f"I ensure I do have role {role}"): node.query(f"CREATE ROLE OR REPLACE {role}") - with Scenario("I create role with no options", flags=TE, requirements=[ + with Scenario("I create role with no options", requirements=[ RQ_SRS_006_RBAC_Role_Create("1.0")]): with cleanup("role0"): with When("I create role"): node.query("CREATE ROLE role0") - with Scenario("I create role that already exists, throws exception", flags=TE, requirements=[ + with Scenario("I create role that already exists, throws exception", requirements=[ RQ_SRS_006_RBAC_Role_Create("1.0")]): role = "role0" with cleanup(role): @@ -49,7 +49,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROLE {role}", exitcode=exitcode, message=message) del role - with Scenario("I create role if not exists, role does not exist", flags=TE, requirements=[ + with Scenario("I create role if not exists, role does not exist", requirements=[ RQ_SRS_006_RBAC_Role_Create_IfNotExists("1.0")]): role = "role1" with cleanup(role): @@ -57,7 +57,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROLE IF NOT EXISTS {role}") del role - with Scenario("I create role if not exists, role does exist", flags=TE, requirements=[ + with Scenario("I create role if not exists, role does exist", requirements=[ RQ_SRS_006_RBAC_Role_Create_IfNotExists("1.0")]): role = "role1" with cleanup(role): @@ -66,7 +66,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROLE IF NOT EXISTS {role}") del role - with Scenario("I create role or replace, role does not exist", flags=TE, requirements=[ + with Scenario("I create role or replace, role does not exist", requirements=[ RQ_SRS_006_RBAC_Role_Create_Replace("1.0")]): role = "role2" with cleanup(role): @@ -74,7 +74,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROLE OR REPLACE {role}") del role - with Scenario("I create role or replace, role does exist", flags=TE, requirements=[ + with Scenario("I create role or replace, role does exist", requirements=[ RQ_SRS_006_RBAC_Role_Create_Replace("1.0")]): role = "role2" with cleanup(role): @@ -83,7 +83,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROLE OR REPLACE {role}") del role - with Scenario("I create role on cluster", flags=TE, requirements=[ + with Scenario("I create role on cluster", requirements=[ RQ_SRS_006_RBAC_Role_Create("1.0")]): try: with When("I have a role on a cluster"): @@ -96,19 +96,19 @@ def feature(self, node="clickhouse1"): with Finally("I drop the role"): node.query("DROP ROLE IF EXISTS role1,role2 ON CLUSTER sharded_cluster") - with Scenario("I create role on nonexistent cluster, throws exception", flags=TE, requirements=[ + with Scenario("I create role on nonexistent cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_Role_Create("1.0")]): with When("I run create role on a cluster"): exitcode, message = errors.cluster_not_found("fake_cluster") node.query("CREATE ROLE role1 ON CLUSTER fake_cluster", exitcode=exitcode, message=message) - with Scenario("I create role with settings profile", flags=TE, requirements=[ + with Scenario("I create role with settings profile", requirements=[ RQ_SRS_006_RBAC_Role_Create_Settings("1.0")]): with cleanup("role3"): with When("I create role with settings profile"): node.query("CREATE ROLE role3 SETTINGS PROFILE default, max_memory_usage=10000000 WRITABLE") - with Scenario("I create role settings profile, fake profile, throws exception", flags=TE, requirements=[ + with Scenario("I create role settings profile, fake profile, throws exception", requirements=[ RQ_SRS_006_RBAC_Role_Create_Settings("1.0")]): with cleanup("role4a"): with Given("I ensure profile profile0 does not exist"): @@ -117,7 +117,7 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.settings_profile_not_found_in_disk("profile0") node.query("CREATE ROLE role4a SETTINGS PROFILE profile0", exitcode=exitcode, message=message) - with Scenario("I create role with settings without profile", flags=TE, requirements=[ + with Scenario("I create role with settings without profile", requirements=[ RQ_SRS_006_RBAC_Role_Create_Settings("1.0")]): with cleanup("role4"): with When("I create role with settings without profile"): diff --git a/tests/testflows/rbac/tests/syntax/create_row_policy.py b/tests/testflows/rbac/tests/syntax/create_row_policy.py index 4f35f47ff4b..8bf83579dd5 100755 --- a/tests/testflows/rbac/tests/syntax/create_row_policy.py +++ b/tests/testflows/rbac/tests/syntax/create_row_policy.py @@ -41,21 +41,21 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROLE role0") node.query(f"CREATE ROLE role1") - with Scenario("I create row policy with no options", flags=TE, requirements=[ + with Scenario("I create row policy with no options", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy0"): with When("I create row policy"): node.query("CREATE ROW POLICY policy0 ON default.foo") - with Scenario("I create row policy using short syntax with no options", flags=TE, requirements=[ + with Scenario("I create row policy using short syntax with no options", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy1"): with When("I create row policy short form"): node.query("CREATE POLICY policy1 ON default.foo") - with Scenario("I create row policy that already exists, throws exception", flags=TE, requirements=[ + with Scenario("I create row policy that already exists, throws exception", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): policy = "policy0" @@ -66,14 +66,14 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROW POLICY {policy} ON default.foo", exitcode=exitcode, message=message) del policy - with Scenario("I create row policy if not exists, policy does not exist", flags=TE, requirements=[ + with Scenario("I create row policy if not exists, policy does not exist", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_IfNotExists("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy2"): with When("I create row policy with if not exists"): node.query("CREATE ROW POLICY IF NOT EXISTS policy2 ON default.foo") - with Scenario("I create row policy if not exists, policy does exist", flags=TE, requirements=[ + with Scenario("I create row policy if not exists, policy does exist", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_IfNotExists("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): policy = "policy2" @@ -83,14 +83,14 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROW POLICY IF NOT EXISTS {policy} ON default.foo") del policy - with Scenario("I create row policy or replace, policy does not exist", flags=TE, requirements=[ + with Scenario("I create row policy or replace, policy does not exist", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Replace("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy3"): with When("I create row policy with or replace"): node.query("CREATE ROW POLICY OR REPLACE policy3 ON default.foo") - with Scenario("I create row policy or replace, policy does exist", flags=TE, requirements=[ + with Scenario("I create row policy or replace, policy does exist", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Replace("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): policy = "policy3" @@ -100,21 +100,21 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROW POLICY OR REPLACE {policy} ON default.foo") del policy - with Scenario("I create row policy as permissive", flags=TE, requirements=[ + with Scenario("I create row policy as permissive", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Access_Permissive("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy4"): with When("I create row policy as permissive"): node.query("CREATE ROW POLICY policy4 ON default.foo AS PERMISSIVE") - with Scenario("I create row policy as restrictive", flags=TE, requirements=[ + with Scenario("I create row policy as restrictive", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Access_Restrictive("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy5"): with When("I create row policy as restrictive"): node.query("CREATE ROW POLICY policy5 ON default.foo AS RESTRICTIVE") - with Scenario("I create row policy for select", flags=TE, requirements=[ + with Scenario("I create row policy for select", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_ForSelect("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_Condition("1.0")]): @@ -122,21 +122,21 @@ def feature(self, node="clickhouse1"): with When("I create row policy with for select"): node.query("CREATE ROW POLICY policy6 ON default.foo FOR SELECT USING x > 10") - with Scenario("I create row policy using condition", flags=TE, requirements=[ + with Scenario("I create row policy using condition", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Condition("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy6"): with When("I create row policy with condition"): node.query("CREATE ROW POLICY policy6 ON default.foo USING x > 10") - with Scenario("I create row policy assigned to one role", flags=TE, requirements=[ + with Scenario("I create row policy assigned to one role", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Assignment("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy7"): with When("I create row policy for one role"): node.query("CREATE ROW POLICY policy7 ON default.foo TO role0") - with Scenario("I create row policy to assign to role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I create row policy to assign to role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Assignment("1.0")]): role = "role2" with cleanup("policy8a"): @@ -147,7 +147,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROW POLICY policy8a ON default.foo TO {role}", exitcode=exitcode, message=message) del role - with Scenario("I create row policy to assign to all excpet role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I create row policy to assign to all excpet role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Assignment("1.0")]): role = "role2" with cleanup("policy8a"): @@ -158,42 +158,42 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE ROW POLICY policy8a ON default.foo TO ALL EXCEPT {role}", exitcode=exitcode, message=message) del role - with Scenario("I create row policy assigned to multiple roles", flags=TE, requirements=[ + with Scenario("I create row policy assigned to multiple roles", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Assignment("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy8b"): with When("I create row policy for multiple roles"): node.query("CREATE ROW POLICY policy8b ON default.foo TO role0, role1") - with Scenario("I create row policy assigned to all", flags=TE, requirements=[ + with Scenario("I create row policy assigned to all", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_All("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy9"): with When("I create row policy for all"): node.query("CREATE ROW POLICY policy9 ON default.foo TO ALL") - with Scenario("I create row policy assigned to all except one role", flags=TE, requirements=[ + with Scenario("I create row policy assigned to all except one role", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_AllExcept("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy10"): with When("I create row policy for all except one"): node.query("CREATE ROW POLICY policy10 ON default.foo TO ALL EXCEPT role0") - with Scenario("I create row policy assigned to all except multiple roles", flags=TE, requirements=[ + with Scenario("I create row policy assigned to all except multiple roles", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_AllExcept("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy11"): with When("I create row policy for all except multiple roles"): node.query("CREATE ROW POLICY policy11 ON default.foo TO ALL EXCEPT role0, role1") - with Scenario("I create row policy assigned to none", flags=TE, requirements=[ + with Scenario("I create row policy assigned to none", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_None("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with cleanup("policy11"): with When("I create row policy for none"): node.query("CREATE ROW POLICY policy11 ON default.foo TO NONE") - with Scenario("I create row policy on cluster", flags=TE, requirements=[ + with Scenario("I create row policy on cluster", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_OnCluster("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): try: @@ -203,14 +203,14 @@ def feature(self, node="clickhouse1"): with Finally("I drop the row policy from cluster"): node.query("DROP ROW POLICY IF EXISTS policy12 ON default.foo ON CLUSTER sharded_cluster") - with Scenario("I create row policy on fake cluster, throws exception", flags=TE, requirements=[ + with Scenario("I create row policy on fake cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_OnCluster("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): with When("I run create row policy command"): exitcode, message = errors.cluster_not_found("fake_cluster") node.query("CREATE ROW POLICY policy13 ON CLUSTER fake_cluster ON default.foo", exitcode=exitcode, message=message) - with Scenario("I create row policy on cluster after table", flags=TE, requirements=[ + with Scenario("I create row policy on cluster after table", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Create_OnCluster("1.0"), RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]): try: diff --git a/tests/testflows/rbac/tests/syntax/create_settings_profile.py b/tests/testflows/rbac/tests/syntax/create_settings_profile.py index 6d720af21bc..8976ce6843a 100755 --- a/tests/testflows/rbac/tests/syntax/create_settings_profile.py +++ b/tests/testflows/rbac/tests/syntax/create_settings_profile.py @@ -39,13 +39,13 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER user0") node.query(f"CREATE ROLE role0") - with Scenario("I create settings profile with no options", flags=TE, requirements=[ + with Scenario("I create settings profile with no options", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create("1.0")]): with cleanup("profile0"): with When("I create settings profile"): node.query("CREATE SETTINGS PROFILE profile0") - with Scenario("I create settings profile that already exists, throws exception", flags=TE, requirements=[ + with Scenario("I create settings profile that already exists, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create("1.0")]): profile = "profile0" with cleanup(profile): @@ -55,13 +55,13 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE SETTINGS PROFILE {profile}", exitcode=exitcode, message=message) del profile - with Scenario("I create settings profile if not exists, profile does not exist", flags=TE, requirements=[ + with Scenario("I create settings profile if not exists, profile does not exist", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_IfNotExists("1.0")]): with cleanup("profile1"): with When("I create settings profile with if not exists"): node.query("CREATE SETTINGS PROFILE IF NOT EXISTS profile1") - with Scenario("I create settings profile if not exists, profile does exist", flags=TE, requirements=[ + with Scenario("I create settings profile if not exists, profile does exist", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_IfNotExists("1.0")]): profile = "profile1" with cleanup(profile): @@ -70,78 +70,78 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE SETTINGS PROFILE IF NOT EXISTS {profile}") del profile - with Scenario("I create settings profile or replace, profile does not exist", flags=TE, requirements=[ + with Scenario("I create settings profile or replace, profile does not exist", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Replace("1.0")]): with cleanup("profile2"): with When("I create settings policy with or replace"): node.query("CREATE SETTINGS PROFILE OR REPLACE profile2") - with Scenario("I create settings profile or replace, profile does exist", flags=TE, requirements=[ + with Scenario("I create settings profile or replace, profile does exist", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Replace("1.0")]): with cleanup("profile2"): create_profile("profile2") with When("I create settings policy with or replace"): node.query("CREATE SETTINGS PROFILE OR REPLACE profile2") - with Scenario("I create settings profile short form", flags=TE, requirements=[ + with Scenario("I create settings profile short form", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create("1.0")]): with cleanup("profile3"): with When("I create settings profile short form"): node.query("CREATE PROFILE profile3") - with Scenario("I create settings profile with a setting value", flags=TE, requirements=[ + with Scenario("I create settings profile with a setting value", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Variables("1.0"), RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Value("1.0")]): with cleanup("profile4"): with When("I create settings profile with settings"): node.query("CREATE SETTINGS PROFILE profile4 SETTINGS max_memory_usage = 100000001") - with Scenario("I create settings profile with a setting value, does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I create settings profile with a setting value, does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Variables("1.0"), RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Value("1.0")]): with When("I create settings profile using settings and nonexistent value"): exitcode, message = errors.unknown_setting("fake_setting") node.query("CREATE SETTINGS PROFILE profile0 SETTINGS fake_setting = 100000001", exitcode=exitcode, message=message) - with Scenario("I create settings profile with a min setting value", flags=TE, requirements=[ + with Scenario("I create settings profile with a min setting value", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]): with cleanup("profile5"), cleanup("profile6"): with When("I create settings profile with min setting with and without equals"): node.query("CREATE SETTINGS PROFILE profile5 SETTINGS max_memory_usage MIN 100000001") node.query("CREATE SETTINGS PROFILE profile6 SETTINGS max_memory_usage MIN = 100000001") - with Scenario("I create settings profile with a max setting value", flags=TE, requirements=[ + with Scenario("I create settings profile with a max setting value", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]): with cleanup("profile7"), cleanup("profile8"): with When("I create settings profile with max setting with and without equals"): node.query("CREATE SETTINGS PROFILE profile7 SETTINGS max_memory_usage MAX 100000001") node.query("CREATE SETTINGS PROFILE profile8 SETTINGS max_memory_usage MAX = 100000001") - with Scenario("I create settings profile with min and max setting values", flags=TE, requirements=[ + with Scenario("I create settings profile with min and max setting values", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]): with cleanup("profile9"): with When("I create settings profile with min and max setting"): node.query("CREATE SETTINGS PROFILE profile9 SETTINGS max_memory_usage MIN 100000001 MAX 200000001") - with Scenario("I create settings profile with a readonly setting", flags=TE, requirements=[ + with Scenario("I create settings profile with a readonly setting", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]): with cleanup("profile10"): with When("I create settings profile with readonly"): node.query("CREATE SETTINGS PROFILE profile10 SETTINGS max_memory_usage READONLY") - with Scenario("I create settings profile with a writable setting", flags=TE, requirements=[ + with Scenario("I create settings profile with a writable setting", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]): with cleanup("profile21"): with When("I create settings profile with writable"): node.query("CREATE SETTINGS PROFILE profile21 SETTINGS max_memory_usage WRITABLE") - with Scenario("I create settings profile with inherited settings", flags=TE, requirements=[ + with Scenario("I create settings profile with inherited settings", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Inherit("1.0")]): with cleanup("profile11"): with When("I create settings profile with inherit"): node.query("CREATE SETTINGS PROFILE profile11 SETTINGS INHERIT 'default'") - with Scenario("I create settings profile with inherit/from profile, fake profile, throws exception", flags=TE, requirements=[ + with Scenario("I create settings profile with inherit/from profile, fake profile, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Inherit("1.0")]): profile = "profile3" with Given(f"I ensure that profile {profile} does not exist"): @@ -153,13 +153,13 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE PROFILE profile0 SETTINGS {source} {profile}", exitcode=exitcode, message=message) del profile - with Scenario("I create settings profile with inherited settings other form", flags=TE, requirements=[ + with Scenario("I create settings profile with inherited settings other form", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Inherit("1.0")]): with cleanup("profile12"): with When("I create settings profile with inherit short form"): node.query("CREATE PROFILE profile12 SETTINGS PROFILE 'default'") - with Scenario("I create settings profile with multiple settings", flags=TE, requirements=[ + with Scenario("I create settings profile with multiple settings", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]): with cleanup("profile13"): with When("I create settings profile with multiple settings"): @@ -167,7 +167,7 @@ def feature(self, node="clickhouse1"): " SETTINGS max_memory_usage = 100000001" " SETTINGS max_memory_usage_for_user = 100000001") - with Scenario("I create settings profile with multiple settings short form", flags=TE, requirements=[ + with Scenario("I create settings profile with multiple settings short form", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]): with cleanup("profile14"): with When("I create settings profile with multiple settings short form"): @@ -175,13 +175,13 @@ def feature(self, node="clickhouse1"): " SETTINGS max_memory_usage = 100000001," " max_memory_usage_for_user = 100000001") - with Scenario("I create settings profile assigned to one role", flags=TE, requirements=[ + with Scenario("I create settings profile assigned to one role", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment("1.0")]): with cleanup("profile15"): with When("I create settings profile for a role"): node.query("CREATE SETTINGS PROFILE profile15 TO role0") - with Scenario("I create settings profile to assign to role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I create settings profile to assign to role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment("1.0")]): role = "role1" with Given(f"I drop {role} if it exists"): @@ -191,7 +191,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE SETTINGS PROFILE profile0 TO {role}", exitcode=exitcode, message=message) del role - with Scenario("I create settings profile to assign to all except role that does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I create settings profile to assign to all except role that does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment("1.0")]): role = "role1" with Given(f"I drop {role} if it exists"): @@ -201,37 +201,37 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE SETTINGS PROFILE profile0 TO ALL EXCEPT {role}", exitcode=exitcode, message=message) del role - with Scenario("I create settings profile assigned to multiple roles", flags=TE, requirements=[ + with Scenario("I create settings profile assigned to multiple roles", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment("1.0")]): with cleanup("profile16"): with When("I create settings profile for multiple roles"): node.query("CREATE SETTINGS PROFILE profile16 TO role0, user0") - with Scenario("I create settings profile assigned to all", flags=TE, requirements=[ + with Scenario("I create settings profile assigned to all", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_All("1.0")]): with cleanup("profile17"): with When("I create settings profile for all"): node.query("CREATE SETTINGS PROFILE profile17 TO ALL") - with Scenario("I create settings profile assigned to all except one role", flags=TE,requirements=[ + with Scenario("I create settings profile assigned to all except one role",requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_AllExcept("1.0")]): with cleanup("profile18"): with When("I create settings profile for all except one role"): node.query("CREATE SETTINGS PROFILE profile18 TO ALL EXCEPT role0") - with Scenario("I create settings profile assigned to all except multiple roles", flags=TE, requirements=[ + with Scenario("I create settings profile assigned to all except multiple roles", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_AllExcept("1.0")]): with cleanup("profile19"): with When("I create settings profile for all except multiple roles"): node.query("CREATE SETTINGS PROFILE profile19 TO ALL EXCEPT role0, user0") - with Scenario("I create settings profile assigned to none", flags=TE, requirements=[ + with Scenario("I create settings profile assigned to none", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_None("1.0")]): with cleanup("profile22"): with When("I create settings profile for none"): node.query("CREATE SETTINGS PROFILE profile22 TO NONE") - with Scenario("I create settings profile on cluster", flags=TE, requirements=[ + with Scenario("I create settings profile on cluster", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_OnCluster("1.0")]): try: with When("I run create settings profile command"): @@ -243,7 +243,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the settings profile"): node.query("DROP SETTINGS PROFILE IF EXISTS profile20 ON CLUSTER sharded_cluster") - with Scenario("I create settings profile on fake cluster, throws exception", flags=TE, requirements=[ + with Scenario("I create settings profile on fake cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Create_OnCluster("1.0")]): with When("I run create settings profile command"): exitcode, message = errors.cluster_not_found("fake_cluster") diff --git a/tests/testflows/rbac/tests/syntax/create_user.py b/tests/testflows/rbac/tests/syntax/create_user.py index d410dd1ab6e..326446e4620 100755 --- a/tests/testflows/rbac/tests/syntax/create_user.py +++ b/tests/testflows/rbac/tests/syntax/create_user.py @@ -25,7 +25,7 @@ def feature(self, node="clickhouse1"): @contextmanager def cleanup(user): try: - with Given("I ensure the user does not already exist", flags=TE): + with Given("I ensure the user does not already exist"): node.query(f"DROP USER IF EXISTS {user}") yield finally: @@ -36,14 +36,14 @@ def feature(self, node="clickhouse1"): with Given(f"I ensure I do have user {user}"): node.query(f"CREATE USER OR REPLACE {user}") - with Scenario("I create user with no options", flags=TE, requirements=[ + with Scenario("I create user with no options", requirements=[ RQ_SRS_006_RBAC_User_Create("1.0"), RQ_SRS_006_RBAC_User_Create_Host_Default("1.0")]): with cleanup("user0"): with When("I create a user with no options"): node.query("CREATE USER user0") - with Scenario("I create user that already exists, throws exception", flags=TE, requirements=[ + with Scenario("I create user that already exists, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Create("1.0"), RQ_SRS_006_RBAC_User_Create_Host_Default("1.0")]): user = "user0" @@ -54,7 +54,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER {user}", exitcode=exitcode, message=message) del user - with Scenario("I create user with if not exists, user does not exist", flags=TE, requirements=[ + with Scenario("I create user with if not exists, user does not exist", requirements=[ RQ_SRS_006_RBAC_User_Create_IfNotExists("1.0")]): user = "user0" with cleanup(user): @@ -63,7 +63,7 @@ def feature(self, node="clickhouse1"): del user #Bug exists, mark as xfail - with Scenario("I create user with if not exists, user does exist", flags=TE, requirements=[ + with Scenario("I create user with if not exists, user does exist", requirements=[ RQ_SRS_006_RBAC_User_Create_IfNotExists("1.0")]): user = "user0" with cleanup(user): @@ -72,7 +72,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER IF NOT EXISTS {user}") del user - with Scenario("I create user or replace, user does not exist", flags=TE, requirements=[ + with Scenario("I create user or replace, user does not exist", requirements=[ RQ_SRS_006_RBAC_User_Create_Replace("1.0")]): user = "user0" with cleanup(user): @@ -80,7 +80,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER OR REPLACE {user}") del user - with Scenario("I create user or replace, user does exist", flags=TE, requirements=[ + with Scenario("I create user or replace, user does exist", requirements=[ RQ_SRS_006_RBAC_User_Create_Replace("1.0")]): user = "user0" with cleanup(user): @@ -89,33 +89,33 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER OR REPLACE {user}") del user - with Scenario("I create user with no password", flags=TE, requirements=[ + with Scenario("I create user with no password", requirements=[ RQ_SRS_006_RBAC_User_Create_Password_NoPassword("1.0")]): with cleanup("user1"): with When("I create a user with no password"): node.query("CREATE USER user1 IDENTIFIED WITH NO_PASSWORD") - with Scenario("I create user with plaintext password", flags=TE, requirements=[ + with Scenario("I create user with plaintext password", requirements=[ RQ_SRS_006_RBAC_User_Create_Password_PlainText("1.0")]): with cleanup("user1"): with When("I create a user with plaintext password"): node.query("CREATE USER user1 IDENTIFIED WITH PLAINTEXT_PASSWORD BY 'mypassword'") - with Scenario("I create user with sha256 password", flags=TE, requirements=[ + with Scenario("I create user with sha256 password", requirements=[ RQ_SRS_006_RBAC_User_Create_Password_Sha256Password("1.0")]): with cleanup("user2"): with When("I create a user with sha256 password"): password = hashlib.sha256("mypassword".encode("utf-8")).hexdigest() node.query(f"CREATE USER user2 IDENTIFIED WITH SHA256_PASSWORD BY '{password}'") - with Scenario("I create user with sha256 password using IDENTIFIED BY", flags=TE, requirements=[ + with Scenario("I create user with sha256 password using IDENTIFIED BY", requirements=[ RQ_SRS_006_RBAC_User_Create_Password_Sha256Password("1.0")]): with cleanup("user2"): with When("I create a user with sha256 password using short form"): password = hashlib.sha256("mypassword".encode("utf-8")).hexdigest() node.query(f"CREATE USER user2 IDENTIFIED BY '{password}'") - with Scenario("I create user with sha256_hash password", flags=TE, requirements=[ + with Scenario("I create user with sha256_hash password", requirements=[ RQ_SRS_006_RBAC_User_Create_Password_Sha256Hash("1.0")]): with cleanup("user3"): with When("I create a user with sha256_hash"): @@ -124,13 +124,13 @@ def feature(self, node="clickhouse1"): password = hash(hash("mypassword")) node.query(f"CREATE USER user3 IDENTIFIED WITH SHA256_HASH BY '{password}'") - with Scenario("I create user with double sha1 password", flags=TE, requirements=[ + with Scenario("I create user with double sha1 password", requirements=[ RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Password("1.0")]): with cleanup("user3"): with When("I create a user with double_sha1_password"): node.query(f"CREATE USER user3 IDENTIFIED WITH DOUBLE_SHA1_PASSWORD BY 'mypassword'") - with Scenario("I create user with double sha1 hash", flags=TE, requirements=[ + with Scenario("I create user with double sha1 hash", requirements=[ RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Hash("1.0")]): with cleanup("user3"): with When("I create a user with double_sha1_hash"): @@ -139,55 +139,55 @@ def feature(self, node="clickhouse1"): password = hash(hash("mypassword")) node.query(f"CREATE USER user3 IDENTIFIED WITH DOUBLE_SHA1_HASH BY '{password}'") - with Scenario("I create user with host name", flags=TE, requirements=[ + with Scenario("I create user with host name", requirements=[ RQ_SRS_006_RBAC_User_Create_Host_Name("1.0")]): with cleanup("user4"): with When("I create a user with host name"): node.query("CREATE USER user4 HOST NAME 'localhost', NAME 'clickhouse.com'") - with Scenario("I create user with host regexp", flags=TE, requirements=[ + with Scenario("I create user with host regexp", requirements=[ RQ_SRS_006_RBAC_User_Create_Host_Regexp("1.0")]): with cleanup("user5"): with When("I create a user with host regexp"): node.query("CREATE USER user5 HOST REGEXP 'lo.?*host', REGEXP 'lo*host'") - with Scenario("I create user with host ip", flags=TE, requirements=[ + with Scenario("I create user with host ip", requirements=[ RQ_SRS_006_RBAC_User_Create_Host_IP("1.0")]): with cleanup("user6"): with When("I create a user with host ip"): node.query("CREATE USER user6 HOST IP '127.0.0.1', IP '127.0.0.2'") - with Scenario("I create user with host like", flags=TE, requirements=[ + with Scenario("I create user with host like", requirements=[ RQ_SRS_006_RBAC_User_Create_Host_Like("1.0")]): with cleanup("user7"): with When("I create a user with host like"): node.query("CREATE USER user7 HOST LIKE 'local%'") - with Scenario("I create user with host none", flags=TE, requirements=[ + with Scenario("I create user with host none", requirements=[ RQ_SRS_006_RBAC_User_Create_Host_None("1.0")]): with cleanup("user7"): with When("I create a user with host none"): node.query("CREATE USER user7 HOST NONE") - with Scenario("I create user with host local", flags=TE, requirements=[ + with Scenario("I create user with host local", requirements=[ RQ_SRS_006_RBAC_User_Create_Host_Local("1.0")]): with cleanup("user7"): with When("I create a user with host local"): node.query("CREATE USER user7 HOST LOCAL") - with Scenario("I create user with host any", flags=TE, requirements=[ + with Scenario("I create user with host any", requirements=[ RQ_SRS_006_RBAC_User_Create_Host_Any("1.0")]): with cleanup("user7"): with When("I create a user with host any"): node.query("CREATE USER user7 HOST ANY") - with Scenario("I create user with default role set to none", flags=TE, requirements=[ + with Scenario("I create user with default role set to none", requirements=[ RQ_SRS_006_RBAC_User_Create_DefaultRole_None("1.0")]): with cleanup("user8"): with When("I create a user with no default role"): node.query("CREATE USER user8 DEFAULT ROLE NONE") - with Scenario("I create user with default role", flags=TE, requirements=[ + with Scenario("I create user with default role", requirements=[ RQ_SRS_006_RBAC_User_Create_DefaultRole("1.0")]): with Given("I have a role"): node.query("CREATE ROLE default") @@ -197,7 +197,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the role"): node.query("DROP ROLE default") - with Scenario("I create user default role, role doesn't exist, throws exception", flags=TE, requirements=[ + with Scenario("I create user default role, role doesn't exist, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Create_DefaultRole("1.0")]): with cleanup("user12"): role = "role0" @@ -208,7 +208,7 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER user12 DEFAULT ROLE {role}",exitcode=exitcode, message=message) del role - with Scenario("I create user default role, all except role doesn't exist, throws exception", flags=TE, requirements=[ + with Scenario("I create user default role, all except role doesn't exist, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Create_DefaultRole("1.0")]): with cleanup("user12"): role = "role0" @@ -219,19 +219,19 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER user12 DEFAULT ROLE ALL EXCEPT {role}",exitcode=exitcode, message=message) del role - with Scenario("I create user with all roles set to default", flags=TE, requirements=[ + with Scenario("I create user with all roles set to default", requirements=[ RQ_SRS_006_RBAC_User_Create_DefaultRole_All("1.0")]): with cleanup("user10"): with When("I create a user with all roles as default"): node.query("CREATE USER user10 DEFAULT ROLE ALL") - with Scenario("I create user with settings profile", flags=TE, requirements=[ + with Scenario("I create user with settings profile", requirements=[ RQ_SRS_006_RBAC_User_Create_Settings("1.0")]): with cleanup("user11"): with When("I create a user with a settings profile"): node.query("CREATE USER user11 SETTINGS PROFILE default, max_memory_usage=10000000 READONLY") - with Scenario("I create user settings profile, fake profile, throws exception", flags=TE, requirements=[ + with Scenario("I create user settings profile, fake profile, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Create_Settings("1.0")]): with cleanup("user18a"): profile = "profile0" @@ -242,20 +242,20 @@ def feature(self, node="clickhouse1"): node.query("CREATE USER user18a SETTINGS PROFILE profile0", exitcode=exitcode, message=message) del profile - with Scenario("I create user settings with a fake setting, throws exception", flags=TE, requirements=[ + with Scenario("I create user settings with a fake setting, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Create_Settings("1.0")]): with cleanup("user18b"): with When("I create settings profile using settings and nonexistent value"): exitcode, message = errors.unknown_setting("fake_setting") node.query("CREATE USER user18b SETTINGS fake_setting = 100000001", exitcode=exitcode, message=message) - with Scenario("I create user with settings without profile", flags=TE, requirements=[ + with Scenario("I create user with settings without profile", requirements=[ RQ_SRS_006_RBAC_User_Create_Settings("1.0")]): with cleanup("user12"): with When("I create a user with settings and no profile"): node.query("CREATE USER user12 SETTINGS max_memory_usage=10000000 READONLY") - with Scenario("I create user on cluster", flags=TE, requirements=[ + with Scenario("I create user on cluster", requirements=[ RQ_SRS_006_RBAC_User_Create_OnCluster("1.0")]): try: with When("I create user on cluster"): @@ -264,7 +264,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the user"): node.query("DROP USER user13 ON CLUSTER sharded_cluster") - with Scenario("I create user on fake cluster, throws exception", flags=TE, requirements=[ + with Scenario("I create user on fake cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Create_OnCluster("1.0")]): with When("I create user on fake cluster"): exitcode, message = errors.cluster_not_found("fake_cluster") diff --git a/tests/testflows/rbac/tests/syntax/drop_quota.py b/tests/testflows/rbac/tests/syntax/drop_quota.py index 099951e3f19..879964e46fb 100755 --- a/tests/testflows/rbac/tests/syntax/drop_quota.py +++ b/tests/testflows/rbac/tests/syntax/drop_quota.py @@ -23,20 +23,20 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE QUOTA {quota}") yield finally: - with Finally("I drop the quota"): + with Finally("I drop the quota", flags=TE): node.query(f"DROP QUOTA IF EXISTS {quota}") def cleanup_quota(quota): with Given(f"I ensure that quota {quota} does not exist"): node.query(f"DROP QUOTA IF EXISTS {quota}") - with Scenario("I drop quota with no options", flags=TE, requirements=[ + with Scenario("I drop quota with no options", requirements=[ RQ_SRS_006_RBAC_Quota_Drop("1.0")]): with cleanup("quota0"): with When("I run drop quota command"): node.query("DROP QUOTA quota0") - with Scenario("I drop quota, does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I drop quota, does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_Quota_Drop("1.0")]): quota = "quota0" cleanup_quota(quota) @@ -45,31 +45,31 @@ def feature(self, node="clickhouse1"): node.query(f"DROP QUOTA {quota}", exitcode=exitcode, message=message) del quota - with Scenario("I drop quota if exists, quota exists", flags=TE, requirements=[ + with Scenario("I drop quota if exists, quota exists", requirements=[ RQ_SRS_006_RBAC_Quota_Drop_IfExists("1.0")]): with cleanup("quota1"): with When("I run drop quota command"): node.query("DROP QUOTA IF EXISTS quota1") - with Scenario("I drop quota if exists, quota does not exist", flags=TE, requirements=[ + with Scenario("I drop quota if exists, quota does not exist", requirements=[ RQ_SRS_006_RBAC_Quota_Drop_IfExists("1.0")]): cleanup_quota("quota2") with When("I run drop quota command, quota does not exist"): node.query("DROP QUOTA IF EXISTS quota2") - with Scenario("I drop default quota, throws error", flags=TE, requirements=[ + with Scenario("I drop default quota, throws error", requirements=[ RQ_SRS_006_RBAC_Quota_Drop("1.0")]): with When("I drop default quota"): exitcode, message = errors.cannot_remove_quota_default() node.query("DROP QUOTA default", exitcode=exitcode, message=message) - with Scenario("I drop multiple quotas", flags=TE, requirements=[ + with Scenario("I drop multiple quotas", requirements=[ RQ_SRS_006_RBAC_Quota_Drop("1.0")]): with cleanup("quota2"), cleanup("quota3"): with When("I run drop quota command"): node.query("DROP QUOTA quota2, quota3") - with Scenario("I drop quota on cluster", flags=TE, requirements=[ + with Scenario("I drop quota on cluster", requirements=[ RQ_SRS_006_RBAC_Quota_Drop_Cluster("1.0")]): try: with Given("I have a quota"): @@ -80,7 +80,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the quota in case it still exists"): node.query("DROP QUOTA IF EXISTS quota4 ON CLUSTER sharded_cluster") - with Scenario("I drop quota on fake cluster", flags=TE, requirements=[ + with Scenario("I drop quota on fake cluster", requirements=[ RQ_SRS_006_RBAC_Quota_Drop_Cluster("1.0")]): with When("I run drop quota command"): exitcode, message = errors.cluster_not_found("fake_cluster") diff --git a/tests/testflows/rbac/tests/syntax/drop_role.py b/tests/testflows/rbac/tests/syntax/drop_role.py index 0e6d0134649..87810dc0184 100755 --- a/tests/testflows/rbac/tests/syntax/drop_role.py +++ b/tests/testflows/rbac/tests/syntax/drop_role.py @@ -31,13 +31,13 @@ def feature(self, node="clickhouse1"): node.query(f"DROP ROLE IF EXISTS {role}") - with Scenario("I drop role with no options", flags=TE, requirements=[ + with Scenario("I drop role with no options", requirements=[ RQ_SRS_006_RBAC_Role_Drop("1.0")]): with setup("role0"): with When("I drop role"): node.query("DROP ROLE role0") - with Scenario("I drop role that doesn't exist, throws exception", flags=TE, requirements=[ + with Scenario("I drop role that doesn't exist, throws exception", requirements=[ RQ_SRS_006_RBAC_Role_Drop("1.0")]): role = "role0" cleanup_role(role) @@ -46,38 +46,38 @@ def feature(self, node="clickhouse1"): node.query(f"DROP ROLE {role}", exitcode=exitcode, message=message) del role - with Scenario("I drop multiple roles", flags=TE, requirements=[ + with Scenario("I drop multiple roles", requirements=[ RQ_SRS_006_RBAC_Role_Drop("1.0")]): with setup("role1"), setup("role2"): with When("I drop multiple roles"): node.query("DROP ROLE role1, role2") - with Scenario("I drop role that does not exist, using if exists", flags=TE, requirements=[ + with Scenario("I drop role that does not exist, using if exists", requirements=[ RQ_SRS_006_RBAC_Role_Drop_IfExists("1.0")]): with When("I drop role if exists"): node.query("DROP ROLE IF EXISTS role3") - with Scenario("I drop multiple roles where one does not exist", flags=TE, requirements=[ + with Scenario("I drop multiple roles where one does not exist", requirements=[ RQ_SRS_006_RBAC_Role_Drop_IfExists("1.0")]): with setup("role5"): with When("I drop multiple roles where one doesnt exist"): node.query("DROP ROLE IF EXISTS role3, role5") - with Scenario("I drop multiple roles where both do not exist", flags = TE, requirements=[ + with Scenario("I drop multiple roles where both do not exist", requirements=[ RQ_SRS_006_RBAC_Role_Drop_IfExists("1.0")]): with Given("I ensure role does not exist"): node.query("DROP ROLE IF EXISTS role6") with When("I drop the nonexistant roles"): node.query("DROP USER IF EXISTS role5, role6") - with Scenario("I drop role on cluster", flags=TE, requirements=[ + with Scenario("I drop role on cluster", requirements=[ RQ_SRS_006_RBAC_Role_Drop_Cluster("1.0")]): with Given("I have a role on cluster"): node.query("CREATE ROLE OR REPLACE role0 ON CLUSTER sharded_cluster") with When("I drop the role from the cluster"): node.query("DROP ROLE IF EXISTS role0 ON CLUSTER sharded_cluster") - with Scenario("I drop role on fake cluster", flags=TE, requirements=[ + with Scenario("I drop role on fake cluster", requirements=[ RQ_SRS_006_RBAC_Role_Drop_Cluster("1.0")]): with When("I run drop role command"): exitcode, message = errors.cluster_not_found("fake_cluster") diff --git a/tests/testflows/rbac/tests/syntax/drop_row_policy.py b/tests/testflows/rbac/tests/syntax/drop_row_policy.py index 2f04450a16a..357f5084bb3 100755 --- a/tests/testflows/rbac/tests/syntax/drop_row_policy.py +++ b/tests/testflows/rbac/tests/syntax/drop_row_policy.py @@ -39,21 +39,21 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE TABLE default.foo (x UInt64, y String) Engine=Memory") node.query(f"CREATE TABLE default.foo2 (x UInt64, y String) Engine=Memory") - with Scenario("I drop row policy with no options", flags=TE, requirements=[ + with Scenario("I drop row policy with no options", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): with cleanup(["policy1"]): with When("I drop row policy"): node.query("DROP ROW POLICY policy1 ON default.foo") - with Scenario("I drop row policy using short syntax with no options", flags=TE, requirements=[ + with Scenario("I drop row policy using short syntax with no options", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): with cleanup(["policy2"]): with When("I drop row policy short form"): node.query("DROP POLICY policy2 ON default.foo") - with Scenario("I drop row policy, does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I drop row policy, does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): policy = "policy1" @@ -63,42 +63,42 @@ def feature(self, node="clickhouse1"): node.query(f"DROP ROW POLICY {policy} ON default.foo", exitcode=exitcode, message=message) del policy - with Scenario("I drop row policy if exists, policy does exist", flags=TE, requirements=[ + with Scenario("I drop row policy if exists, policy does exist", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop_IfExists("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): with cleanup(["policy3"]): with When("I drop row policy if exists"): node.query("DROP ROW POLICY IF EXISTS policy3 ON default.foo") - with Scenario("I drop row policy if exists, policy doesn't exist", flags=TE, requirements=[ + with Scenario("I drop row policy if exists, policy doesn't exist", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop_IfExists("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): cleanup_policy("policy3") with When("I drop row policy if exists"): node.query("DROP ROW POLICY IF EXISTS policy3 ON default.foo") - with Scenario("I drop multiple row policies", flags=TE, requirements=[ + with Scenario("I drop multiple row policies", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): with cleanup(["policy3", "policy4"]): with When("I drop multiple row policies"): node.query("DROP ROW POLICY policy3, policy4 ON default.foo") - with Scenario("I drop row policy on multiple tables", flags=TE, requirements=[ + with Scenario("I drop row policy on multiple tables", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): with cleanup(["policy3"], ["default.foo","default.foo2"]): with When("I drop row policy on multiple tables"): node.query("DROP ROW POLICY policy3 ON default.foo, default.foo2") - with Scenario("I drop multiple row policies on multiple tables", flags=TE, requirements=[ + with Scenario("I drop multiple row policies on multiple tables", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): with cleanup(["policy3", "policy4"], ["default.foo","default.foo2"]): with When("I drop the row policies from the tables"): node.query("DROP ROW POLICY policy3 ON default.foo, policy4 ON default.foo2") - with Scenario("I drop row policy on cluster", flags=TE, requirements=[ + with Scenario("I drop row policy on cluster", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop_OnCluster("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): try: @@ -110,7 +110,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the row policy in case it still exists"): node.query("DROP ROW POLICY IF EXISTS policy13 ON default.foo ON CLUSTER sharded_cluster") - with Scenario("I drop row policy on cluster after table", flags=TE, requirements=[ + with Scenario("I drop row policy on cluster after table", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop_OnCluster("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): try: @@ -122,7 +122,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the row policy in case it still exists"): node.query("DROP ROW POLICY IF EXISTS policy12 ON default.foo ON CLUSTER sharded_cluster") - with Scenario("I drop row policy on fake cluster throws exception", flags=TE, requirements=[ + with Scenario("I drop row policy on fake cluster throws exception", requirements=[ RQ_SRS_006_RBAC_RowPolicy_Drop_OnCluster("1.0"), RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]): with When("I run drop row policy command"): diff --git a/tests/testflows/rbac/tests/syntax/drop_settings_profile.py b/tests/testflows/rbac/tests/syntax/drop_settings_profile.py index cb17815127f..514c3042679 100755 --- a/tests/testflows/rbac/tests/syntax/drop_settings_profile.py +++ b/tests/testflows/rbac/tests/syntax/drop_settings_profile.py @@ -30,13 +30,13 @@ def feature(self, node="clickhouse1"): with Given(f"I ensure that profile {profile} does not exist"): node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}") - with Scenario("I drop settings profile with no options", flags=TE, requirements=[ + with Scenario("I drop settings profile with no options", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Drop("1.0")]): with cleanup("profile0"): with When("I drop settings profile"): node.query("DROP SETTINGS PROFILE profile0") - with Scenario("I drop settings profile, does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I drop settings profile, does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Drop("1.0")]): profile = "profile0" cleanup_profile(profile) @@ -45,19 +45,19 @@ def feature(self, node="clickhouse1"): node.query("DROP SETTINGS PROFILE profile0", exitcode=exitcode, message=message) del profile - with Scenario("I drop settings profile short form", flags=TE, requirements=[ + with Scenario("I drop settings profile short form", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Drop("1.0")]): with cleanup("profile1"): with When("I drop settings profile short form"): node.query("DROP PROFILE profile1") - with Scenario("I drop settings profile if exists, profile does exist", flags=TE, requirements=[ + with Scenario("I drop settings profile if exists, profile does exist", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Drop_IfExists("1.0")]): with cleanup("profile2"): with When("I drop settings profile if exists"): node.query("DROP SETTINGS PROFILE IF EXISTS profile2") - with Scenario("I drop settings profile if exists, profile does not exist", flags=TE, requirements=[ + with Scenario("I drop settings profile if exists, profile does not exist", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Drop_IfExists("1.0")]): cleanup_profile("profile2") with When("I drop settings profile if exists"): @@ -69,13 +69,13 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.cannot_remove_settings_profile_default() node.query("DROP SETTINGS PROFILE default", exitcode=exitcode, message=message) - with Scenario("I drop multiple settings profiles", flags=TE, requirements=[ + with Scenario("I drop multiple settings profiles", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Drop("1.0")]): with cleanup("profile3"), cleanup("profile4"): with When("I drop multiple settings profiles"): node.query("DROP SETTINGS PROFILE profile3, profile4") - with Scenario("I drop settings profile on cluster", flags=TE, requirements=[ + with Scenario("I drop settings profile on cluster", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Drop_OnCluster("1.0")]): try: with Given("I have a settings profile"): @@ -86,7 +86,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the profile in case it still exists"): node.query("DROP SETTINGS PROFILE IF EXISTS profile5 ON CLUSTER sharded_cluster") - with Scenario("I drop settings profile on fake cluster, throws exception", flags=TE, requirements=[ + with Scenario("I drop settings profile on fake cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_Drop_OnCluster("1.0")]): with When("I run drop settings profile command"): exitcode, message = errors.cluster_not_found("fake_cluster") diff --git a/tests/testflows/rbac/tests/syntax/drop_user.py b/tests/testflows/rbac/tests/syntax/drop_user.py index 13f0093080a..9bd2433d487 100755 --- a/tests/testflows/rbac/tests/syntax/drop_user.py +++ b/tests/testflows/rbac/tests/syntax/drop_user.py @@ -30,13 +30,13 @@ def feature(self, node="clickhouse1"): with Given(f"I ensure that user {user} does not exist"): node.query(f"DROP USER IF EXISTS {user}") - with Scenario("I drop user with no options", flags=TE, requirements=[ + with Scenario("I drop user with no options", requirements=[ RQ_SRS_006_RBAC_User_Drop("1.0")]): with setup("user0"): with When("I drop user"): node.query("DROP USER user0") - with Scenario("I drop user, does not exist, throws exception", flags=TE, requirements=[ + with Scenario("I drop user, does not exist, throws exception", requirements=[ RQ_SRS_006_RBAC_User_Drop("1.0")]): user = "user0" cleanup_user(user) @@ -45,31 +45,31 @@ def feature(self, node="clickhouse1"): node.query(f"DROP USER {user}", exitcode=exitcode, message=message) del user - with Scenario("I drop multiple users", flags=TE, requirements=[ + with Scenario("I drop multiple users", requirements=[ RQ_SRS_006_RBAC_User_Drop("1.0")]): with setup("user1"), setup("user2"): with When("I drop multiple users"): node.query("DROP USER user1, user2") - with Scenario("I drop user if exists, user does exist", flags=TE, requirements=[ + with Scenario("I drop user if exists, user does exist", requirements=[ RQ_SRS_006_RBAC_User_Drop_IfExists("1.0")]): with setup("user3"): with When("I drop user that exists"): node.query("DROP USER IF EXISTS user3") - with Scenario("I drop user if exists, user does not exist", flags=TE, requirements=[ + with Scenario("I drop user if exists, user does not exist", requirements=[ RQ_SRS_006_RBAC_User_Drop_IfExists("1.0")]): cleanup_user("user3") with When("I drop nonexistant user"): node.query("DROP USER IF EXISTS user3") - with Scenario("I drop default user, throws error", flags=TE, requirements=[ + with Scenario("I drop default user, throws error", requirements=[ RQ_SRS_006_RBAC_User_Drop("1.0")]): with When("I drop user"): exitcode, message = errors.cannot_remove_user_default() node.query("DROP USER default", exitcode=exitcode, message=message) - with Scenario("I drop multiple users where one does not exist", flags=TE, requirements=[ + with Scenario("I drop multiple users where one does not exist", requirements=[ RQ_SRS_006_RBAC_User_Drop_IfExists("1.0")]): with setup("user3"): with When("I drop multiple users where one does not exist"): @@ -80,7 +80,7 @@ def feature(self, node="clickhouse1"): with When("I drop the nonexistant users"): node.query("DROP USER IF EXISTS user5, user6") - with Scenario("I drop user from specific cluster", flags=TE, requirements=[ + with Scenario("I drop user from specific cluster", requirements=[ RQ_SRS_006_RBAC_User_Drop_OnCluster("1.0")]): try: with Given("I have a user on cluster"): @@ -91,7 +91,7 @@ def feature(self, node="clickhouse1"): with Finally("I make sure the user is dropped"): node.query("DROP USER IF EXISTS user4 ON CLUSTER sharded_cluster") - with Scenario("I drop user from fake cluster", flags=TE, requirements=[ + with Scenario("I drop user from fake cluster", requirements=[ RQ_SRS_006_RBAC_User_Drop_OnCluster("1.0")]): with When("I drop a user from the fake cluster"): exitcode, message = errors.cluster_not_found("fake_cluster") diff --git a/tests/testflows/rbac/tests/syntax/feature.py b/tests/testflows/rbac/tests/syntax/feature.py index aac786ff85c..b7c23f8d7ee 100755 --- a/tests/testflows/rbac/tests/syntax/feature.py +++ b/tests/testflows/rbac/tests/syntax/feature.py @@ -3,32 +3,32 @@ from testflows.core import * @TestFeature @Name("syntax") def feature(self): - Feature(run=load("rbac.tests.syntax.create_user", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.alter_user", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.drop_user", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.show_create_user", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.create_role", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.alter_role", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.drop_role", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.show_create_role", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.grant_role", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.grant_privilege","feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.show_grants", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.revoke_role", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.revoke_privilege","feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.create_row_policy", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.alter_row_policy", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.drop_row_policy", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.show_create_row_policy", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.show_row_policies", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.create_quota", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.alter_quota", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.drop_quota", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.show_create_quota", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.show_quotas", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.create_settings_profile", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.alter_settings_profile", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.drop_settings_profile", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.show_create_settings_profile", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.set_default_role", "feature"), flags=TE) - Feature(run=load("rbac.tests.syntax.set_role","feature"), flags=TE) \ No newline at end of file + Feature(run=load("rbac.tests.syntax.create_user", "feature")) + Feature(run=load("rbac.tests.syntax.alter_user", "feature")) + Feature(run=load("rbac.tests.syntax.drop_user", "feature")) + Feature(run=load("rbac.tests.syntax.show_create_user", "feature")) + Feature(run=load("rbac.tests.syntax.create_role", "feature")) + Feature(run=load("rbac.tests.syntax.alter_role", "feature")) + Feature(run=load("rbac.tests.syntax.drop_role", "feature")) + Feature(run=load("rbac.tests.syntax.show_create_role", "feature")) + Feature(run=load("rbac.tests.syntax.grant_role", "feature")) + Feature(run=load("rbac.tests.syntax.grant_privilege","feature")) + Feature(run=load("rbac.tests.syntax.show_grants", "feature")) + Feature(run=load("rbac.tests.syntax.revoke_role", "feature")) + Feature(run=load("rbac.tests.syntax.revoke_privilege","feature")) + Feature(run=load("rbac.tests.syntax.create_row_policy", "feature")) + Feature(run=load("rbac.tests.syntax.alter_row_policy", "feature")) + Feature(run=load("rbac.tests.syntax.drop_row_policy", "feature")) + Feature(run=load("rbac.tests.syntax.show_create_row_policy", "feature")) + Feature(run=load("rbac.tests.syntax.show_row_policies", "feature")) + Feature(run=load("rbac.tests.syntax.create_quota", "feature")) + Feature(run=load("rbac.tests.syntax.alter_quota", "feature")) + Feature(run=load("rbac.tests.syntax.drop_quota", "feature")) + Feature(run=load("rbac.tests.syntax.show_create_quota", "feature")) + Feature(run=load("rbac.tests.syntax.show_quotas", "feature")) + Feature(run=load("rbac.tests.syntax.create_settings_profile", "feature")) + Feature(run=load("rbac.tests.syntax.alter_settings_profile", "feature")) + Feature(run=load("rbac.tests.syntax.drop_settings_profile", "feature")) + Feature(run=load("rbac.tests.syntax.show_create_settings_profile", "feature")) + Feature(run=load("rbac.tests.syntax.set_default_role", "feature")) + Feature(run=load("rbac.tests.syntax.set_role","feature")) \ No newline at end of file diff --git a/tests/testflows/rbac/tests/syntax/grant_privilege.py b/tests/testflows/rbac/tests/syntax/grant_privilege.py index 2108b101c44..817a70498f4 100755 --- a/tests/testflows/rbac/tests/syntax/grant_privilege.py +++ b/tests/testflows/rbac/tests/syntax/grant_privilege.py @@ -82,7 +82,7 @@ def feature(self, node="clickhouse1"): Scenario(run=grant_privileges) # with nonexistant object name, GRANT assumes type role - with Scenario("I grant privilege to role that does not exist", flags=TE, requirements=[ + with Scenario("I grant privilege to role that does not exist", requirements=[ RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]): with Given("I ensure that role does not exist"): node.query("DROP ROLE IF EXISTS role0") @@ -90,35 +90,35 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.role_not_found_in_disk(name="role0") node.query("GRANT NONE TO role0", exitcode=exitcode, message=message) - with Scenario("I grant privilege ON CLUSTER", flags=TE, requirements=[ + with Scenario("I grant privilege ON CLUSTER", requirements=[ RQ_SRS_006_RBAC_Grant_Privilege_OnCluster("1.0"), RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]): with setup(node): with When("I grant privilege ON CLUSTER"): node.query("GRANT ON CLUSTER sharded_cluster NONE TO user0") - with Scenario("I grant privilege on fake cluster, throws exception", flags=TE, requirements=[ + with Scenario("I grant privilege on fake cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_Grant_Privilege_OnCluster("1.0")]): with setup(node): with When("I grant privilege ON CLUSTER"): exitcode, message = errors.cluster_not_found("fake_cluster") node.query("GRANT ON CLUSTER fake_cluster NONE TO user0", exitcode=exitcode, message=message) - with Scenario("I grant privilege to multiple users and roles", flags=TE, requirements=[ + with Scenario("I grant privilege to multiple users and roles", requirements=[ RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"), RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]): with setup(node): with When("I grant privilege to several users"): node.query("GRANT NONE TO user0, user1, role1") - with Scenario("I grant privilege to current user", flags=TE, requirements=[ + with Scenario("I grant privilege to current user", requirements=[ RQ_SRS_006_RBAC_Grant_Privilege_ToCurrentUser("1.0"), RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]): with setup(node): with When("I grant privilege to current user"): node.query("GRANT NONE TO CURRENT_USER", settings = [("user","user0")]) - with Scenario("I grant privilege NONE to default user, throws exception", flags=TE, requirements=[ + with Scenario("I grant privilege NONE to default user, throws exception", requirements=[ RQ_SRS_006_RBAC_Grant_Privilege_ToCurrentUser("1.0"), RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]): with setup(node): @@ -126,7 +126,7 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.cannot_update_default() node.query("GRANT NONE TO CURRENT_USER", exitcode=exitcode, message=message) - with Scenario("I grant privilege with grant option", flags=TE, requirements=[ + with Scenario("I grant privilege with grant option", requirements=[ RQ_SRS_006_RBAC_Grant_Privilege_GrantOption("1.0"), RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]): with setup(node): diff --git a/tests/testflows/rbac/tests/syntax/grant_role.py b/tests/testflows/rbac/tests/syntax/grant_role.py index 26c9fb619e9..af69e5f3751 100755 --- a/tests/testflows/rbac/tests/syntax/grant_role.py +++ b/tests/testflows/rbac/tests/syntax/grant_role.py @@ -33,7 +33,7 @@ def feature(self, node="clickhouse1"): for j in range(roles): node.query(f"DROP ROLE IF EXISTS role{j}") - with Scenario("I grant a role to a user",flags=TE, requirements=[ + with Scenario("I grant a role to a user", requirements=[ RQ_SRS_006_RBAC_Grant_Role("1.0")]): with setup(1,1): with When("I grant a role"): @@ -61,19 +61,19 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.role_not_found_in_disk(name="role0") node.query("GRANT role0 TO user0", exitcode=exitcode, message=message) - with Scenario("I grant a role to multiple users", flags=TE, requirements=[ + with Scenario("I grant a role to multiple users", requirements=[ RQ_SRS_006_RBAC_Grant_Role("1.0")]): with setup(2,1): with When("I grant role to a multiple users"): node.query("GRANT role0 TO user0, user1") - with Scenario("I grant multiple roles to multiple users", flags=TE, requirements=[ + with Scenario("I grant multiple roles to multiple users", requirements=[ RQ_SRS_006_RBAC_Grant_Role("1.0")]): with setup(2,2): with When("I grant multiple roles to multiple users"): node.query("GRANT role0, role1 TO user0, user1") - with Scenario("I grant role to current user", flags=TE, requirements=[ + with Scenario("I grant role to current user", requirements=[ RQ_SRS_006_RBAC_Grant_Role_CurrentUser("1.0")]): with setup(1,1): with Given("I have a user with access management privilege"): @@ -81,20 +81,20 @@ def feature(self, node="clickhouse1"): with When("I grant role to current user"): node.query("GRANT role0 TO CURRENT_USER", settings = [("user","user0")]) - with Scenario("I grant role to default user, throws exception", flags=TE, requirements=[ + with Scenario("I grant role to default user, throws exception", requirements=[ RQ_SRS_006_RBAC_Grant_Role_CurrentUser("1.0")]): with setup(1,1): with When("I grant role to default user"): exitcode, message = errors.cannot_update_default() node.query("GRANT role0 TO CURRENT_USER", exitcode=exitcode, message=message) - with Scenario("I grant role to user with admin option", flags=TE, requirements=[ + with Scenario("I grant role to user with admin option", requirements=[ RQ_SRS_006_RBAC_Grant_Role_AdminOption("1.0")]): with setup(1,1): with When("I grant role to a user with admin option"): node.query("GRANT role0 TO user0 WITH ADMIN OPTION") - with Scenario("I grant role to user on cluster", flags=TE, requirements=[ + with Scenario("I grant role to user on cluster", requirements=[ RQ_SRS_006_RBAC_Grant_Role_OnCluster("1.0")]): try: with Given("I have a user and a role on a cluster"): @@ -107,7 +107,7 @@ def feature(self, node="clickhouse1"): node.query("DROP USER IF EXISTS user0 ON CLUSTER sharded_cluster") node.query("DROP ROLE IF EXISTS role0 ON CLUSTER sharded_cluster") - with Scenario("I grant role to user on fake cluster, throws exception", flags=TE, requirements=[ + with Scenario("I grant role to user on fake cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_Grant_Role_OnCluster("1.0")]): with setup(1,1): with When("I grant the role to the user"): diff --git a/tests/testflows/rbac/tests/syntax/revoke_privilege.py b/tests/testflows/rbac/tests/syntax/revoke_privilege.py index a0fb714c823..3e23f2ddfc9 100755 --- a/tests/testflows/rbac/tests/syntax/revoke_privilege.py +++ b/tests/testflows/rbac/tests/syntax/revoke_privilege.py @@ -43,7 +43,9 @@ def revoke_privileges(self, privilege, on, allow_column, allow_introspection, no revoke_privilege(privilege=privilege, on=on, allow_column=allow_column, allow_introspection=allow_introspection, node=node) @TestOutline(Scenario) -@Requirements([RQ_SRS_006_RBAC_Revoke_Privilege_Any("1.0") , RQ_SRS_006_RBAC_Revoke_Privilege_PrivelegeColumns("1.0")]) +@Requirements( + RQ_SRS_006_RBAC_Revoke_Privilege_PrivilegeColumns("1.0"), +) def revoke_privilege(self, privilege, on, allow_column, allow_introspection, node="clickhouse1"): node = self.context.cluster.node(node) for on_ in on: @@ -78,14 +80,14 @@ def feature(self, node="clickhouse1"): Scenario(run=revoke_privileges) - with Scenario("I revoke privilege ON CLUSTER", flags=TE, requirements=[ + with Scenario("I revoke privilege ON CLUSTER", requirements=[ RQ_SRS_006_RBAC_Revoke_Privilege_Cluster("1.0"), RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]): with setup(node): with When("I revoke privilege ON CLUSTER"): node.query("REVOKE ON CLUSTER sharded_cluster NONE FROM user0") - with Scenario("I revoke privilege ON fake CLUSTER, throws exception", flags=TE, requirements=[ + with Scenario("I revoke privilege ON fake CLUSTER, throws exception", requirements=[ RQ_SRS_006_RBAC_Revoke_Privilege_Cluster("1.0"), RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]): with setup(node): @@ -94,21 +96,21 @@ def feature(self, node="clickhouse1"): node.query("REVOKE ON CLUSTER fake_cluster NONE FROM user0", exitcode=exitcode, message=message) - with Scenario("I revoke privilege from multiple users and roles", flags=TE, requirements=[ + with Scenario("I revoke privilege from multiple users and roles", requirements=[ RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"), RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]): with setup(node): with When("I revoke privilege from multiple users"): node.query("REVOKE NONE FROM user0, user1, role1") - with Scenario("I revoke privilege from current user", flags=TE, requirements=[ + with Scenario("I revoke privilege from current user", requirements=[ RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"), RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]): with setup(node): with When("I revoke privilege from current user"): node.query("REVOKE NONE FROM CURRENT_USER", settings = [("user","user0")]) - with Scenario("I revoke privilege from all users", flags=TE, requirements=[ + with Scenario("I revoke privilege from all users", requirements=[ RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"), RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]): with setup(node): @@ -116,7 +118,7 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.cannot_update_default() node.query("REVOKE NONE FROM ALL", exitcode=exitcode,message=message) - with Scenario("I revoke privilege from default user", flags=TE, requirements=[ + with Scenario("I revoke privilege from default user", requirements=[ RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"), RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]): with setup(node): @@ -125,7 +127,7 @@ def feature(self, node="clickhouse1"): node.query("REVOKE NONE FROM default", exitcode=exitcode,message=message) #By default, ClickHouse treats unnamed object as role - with Scenario("I revoke privilege from nonexistent role, throws exception", flags=TE, requirements=[ + with Scenario("I revoke privilege from nonexistent role, throws exception", requirements=[ RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"), RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]): role = "role5" @@ -135,7 +137,7 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.role_not_found_in_disk(role) node.query(f"REVOKE NONE FROM {role}", exitcode=exitcode,message=message) - with Scenario("I revoke privilege from ALL EXCEPT nonexistent role, throws exception", flags=TE, requirements=[ + with Scenario("I revoke privilege from ALL EXCEPT nonexistent role, throws exception", requirements=[ RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"), RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]): role = "role5" @@ -145,14 +147,14 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.role_not_found_in_disk(role) node.query(f"REVOKE NONE FROM ALL EXCEPT {role}", exitcode=exitcode,message=message) - with Scenario("I revoke privilege from all except some users and roles", flags=TE, requirements=[ + with Scenario("I revoke privilege from all except some users and roles", requirements=[ RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"), RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]): with setup(node): with When("I revoke privilege all except some users"): node.query("REVOKE NONE FROM ALL EXCEPT default, user0, role1") - with Scenario("I revoke privilege from all except current user", flags=TE, requirements=[ + with Scenario("I revoke privilege from all except current user", requirements=[ RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"), RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]): with setup(node): diff --git a/tests/testflows/rbac/tests/syntax/revoke_role.py b/tests/testflows/rbac/tests/syntax/revoke_role.py index 9d87257b054..4acdf127cec 100755 --- a/tests/testflows/rbac/tests/syntax/revoke_role.py +++ b/tests/testflows/rbac/tests/syntax/revoke_role.py @@ -37,7 +37,7 @@ def feature(self, node="clickhouse1"): for i in range(roles): node.query(f"DROP ROLE IF EXISTS role{i}") - with Scenario("I revoke a role from a user",flags=TE, requirements=[ + with Scenario("I revoke a role from a user", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0")]): with setup(): with When("I revoke a role"): @@ -73,19 +73,19 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.role_not_found_in_disk(name="role0") node.query("REVOKE role0 FROM user0", exitcode=exitcode, message=message) - with Scenario("I revoke a role from multiple users", flags=TE, requirements=[ + with Scenario("I revoke a role from multiple users", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0")]): with setup(): with When("I revoke a role from multiple users"): node.query("REVOKE role0 FROM user0, user1") - with Scenario("I revoke multiple roles from multiple users", flags=TE, requirements=[ + with Scenario("I revoke multiple roles from multiple users", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0")]): with setup(): node.query("REVOKE role0, role1 FROM user0, user1") #user is default, expect exception - with Scenario("I revoke a role from default user", flags=TE, requirements=[ + with Scenario("I revoke a role from default user", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0"), RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]): with setup(): @@ -94,7 +94,7 @@ def feature(self, node="clickhouse1"): node.query("REVOKE role0 FROM CURRENT_USER", exitcode=exitcode, message=message) #user is user0 - with Scenario("I revoke a role from current user", flags=TE, requirements=[ + with Scenario("I revoke a role from current user", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0"), RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]): with setup(): @@ -102,7 +102,7 @@ def feature(self, node="clickhouse1"): node.query("REVOKE role0 FROM CURRENT_USER", settings = [("user","user0")]) #user is default, expect exception - with Scenario("I revoke a role from all", flags=TE, requirements=[ + with Scenario("I revoke a role from all", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0"), RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]): with setup(): @@ -111,7 +111,7 @@ def feature(self, node="clickhouse1"): node.query("REVOKE role0 FROM ALL", exitcode=exitcode, message=message) #user is default, expect exception - with Scenario("I revoke multiple roles from all", flags=TE, requirements=[ + with Scenario("I revoke multiple roles from all", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0"), RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]): with setup(): @@ -119,14 +119,14 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.cannot_update_default() node.query("REVOKE role0, role1 FROM ALL", exitcode=exitcode, message=message) - with Scenario("I revoke a role from all but current user", flags=TE, requirements=[ + with Scenario("I revoke a role from all but current user", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0"), RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]): with setup(): with When("I revoke a role from all except current"): node.query("REVOKE role0 FROM ALL EXCEPT CURRENT_USER") - with Scenario("I revoke a role from all but default user", flags=TE, requirements=[ + with Scenario("I revoke a role from all but default user", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0"), RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]): with setup(): @@ -134,26 +134,26 @@ def feature(self, node="clickhouse1"): node.query("REVOKE role0 FROM ALL EXCEPT default", settings = [("user","user0")]) - with Scenario("I revoke multiple roles from all but default user", flags=TE, requirements=[ + with Scenario("I revoke multiple roles from all but default user", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0"), RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]): with setup(): with When("I revoke multiple roles from all except default"): node.query("REVOKE role0, role1 FROM ALL EXCEPT default", settings = [("user","user0")]) - with Scenario("I revoke a role from a role", flags=TE, requirements=[ + with Scenario("I revoke a role from a role", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0")]): with setup(): with When("I revoke a role from a role"): node.query("REVOKE role0 FROM role1") - with Scenario("I revoke a role from a role and a user", flags=TE, requirements=[ + with Scenario("I revoke a role from a role and a user", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0")]): with setup(): with When("I revoke a role from multiple roles"): node.query("REVOKE role0 FROM role1, user0") - with Scenario("I revoke a role from a user on cluster", flags=TE, requirements=[ + with Scenario("I revoke a role from a user on cluster", requirements=[ RQ_SRS_006_RBAC_Revoke_Role_Cluster("1.0")]): with Given("I have a role and a user on a cluster"): node.query("CREATE USER OR REPLACE user0 ON CLUSTER sharded_cluster") @@ -164,13 +164,13 @@ def feature(self, node="clickhouse1"): node.query("DROP USER IF EXISTS user0 ON CLUSTER sharded_cluster") node.query("DROP ROLE IF EXISTS role0 ON CLUSTER sharded_cluster") - with Scenario("I revoke a role on fake cluster, throws exception", flags=TE, requirements=[ + with Scenario("I revoke a role on fake cluster, throws exception", requirements=[ RQ_SRS_006_RBAC_Revoke_Role_Cluster("1.0")]): with When("I revoke a role from user on a cluster"): exitcode, message = errors.cluster_not_found("fake_cluster") node.query("REVOKE ON CLUSTER fake_cluster role0 FROM user0", exitcode=exitcode, message=message) - with Scenario("I revoke multiple roles from multiple users on cluster", flags=TE, requirements=[ + with Scenario("I revoke multiple roles from multiple users on cluster", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0"), RQ_SRS_006_RBAC_Revoke_Role_Cluster("1.0")]): with Given("I have multiple roles and multiple users on a cluster"): @@ -184,13 +184,13 @@ def feature(self, node="clickhouse1"): node.query(f"DROP USER IF EXISTS user{i} ON CLUSTER sharded_cluster") node.query(f"DROP ROLE IF EXISTS role{i} ON CLUSTER sharded_cluster") - with Scenario("I revoke admin option for role from a user", flags=TE, requirements=[ + with Scenario("I revoke admin option for role from a user", requirements=[ RQ_SRS_006_RBAC_Revoke_AdminOption("1.0")]): with setup(): with When("I revoke admin option for role from a user"): node.query("REVOKE ADMIN OPTION FOR role0 FROM user0") - with Scenario("I revoke admin option for multiple roles from multiple users", flags=TE, requirements=[ + with Scenario("I revoke admin option for multiple roles from multiple users", requirements=[ RQ_SRS_006_RBAC_Revoke_Role("1.0"), RQ_SRS_006_RBAC_Revoke_AdminOption("1.0")]): with setup(): diff --git a/tests/testflows/rbac/tests/syntax/set_default_role.py b/tests/testflows/rbac/tests/syntax/set_default_role.py index a7801e04b23..ed50810eba7 100755 --- a/tests/testflows/rbac/tests/syntax/set_default_role.py +++ b/tests/testflows/rbac/tests/syntax/set_default_role.py @@ -71,43 +71,43 @@ def feature(self, node="clickhouse1"): node.query(f"CREATE USER user{i}") node.query(f"GRANT role0, role1 TO user0, user1") - with Scenario("I set default role for a user to none", flags = TE, requirements=[ + with Scenario("I set default role for a user to none", requirements=[ RQ_SRS_006_RBAC_SetDefaultRole_None("1.0")]): with When("I set no roles default for user"): node.query("SET DEFAULT ROLE NONE TO user0") - with Scenario("I set one default role for a user", flags = TE, requirements=[ + with Scenario("I set one default role for a user", requirements=[ RQ_SRS_006_RBAC_SetDefaultRole("1.0")]): with When("I set a default role for user "): node.query("SET DEFAULT ROLE role0 TO user0") - with Scenario("I set one default role for user default, throws exception", flags = TE, requirements=[ + with Scenario("I set one default role for user default, throws exception", requirements=[ RQ_SRS_006_RBAC_SetDefaultRole("1.0")]): with When("I set a default role for default"): exitcode, message = errors.cannot_update_default() node.query("SET DEFAULT ROLE role0 TO default", exitcode=exitcode, message=message) - with Scenario("I set multiple default roles for a user", flags = TE, requirements=[ + with Scenario("I set multiple default roles for a user", requirements=[ RQ_SRS_006_RBAC_SetDefaultRole("1.0")]): with When("I set multiple default roles to user"): node.query("SET DEFAULT ROLE role0, role1 TO user0") - with Scenario("I set multiple default roles for multiple users", flags = TE, requirements=[ + with Scenario("I set multiple default roles for multiple users", requirements=[ RQ_SRS_006_RBAC_SetDefaultRole("1.0")]): with When("I set multiple default roles to multiple users"): node.query("SET DEFAULT ROLE role0, role1 TO user0, user1") - with Scenario("I set all roles as default for a user", flags = TE, requirements=[ + with Scenario("I set all roles as default for a user", requirements=[ RQ_SRS_006_RBAC_SetDefaultRole_All("1.0")]): with When("I set all roles default to user"): node.query("SET DEFAULT ROLE ALL TO user0") - with Scenario("I set all roles except one for a user", flags = TE, requirements=[ + with Scenario("I set all roles except one for a user", requirements=[ RQ_SRS_006_RBAC_SetDefaultRole_AllExcept("1.0")]): with When("I set all except one role default to user"): node.query("SET DEFAULT ROLE ALL EXCEPT role0 TO user0") - with Scenario("I set default role for current user", flags = TE, requirements=[ + with Scenario("I set default role for current user", requirements=[ RQ_SRS_006_RBAC_SetDefaultRole_CurrentUser("1.0")]): with When("I set default role to current user"): node.query("GRANT ACCESS MANAGEMENT ON *.* TO user0") diff --git a/tests/testflows/rbac/tests/syntax/set_role.py b/tests/testflows/rbac/tests/syntax/set_role.py index 97a121797ac..3d3d4d00fac 100755 --- a/tests/testflows/rbac/tests/syntax/set_role.py +++ b/tests/testflows/rbac/tests/syntax/set_role.py @@ -29,17 +29,17 @@ def feature(self, node="clickhouse1"): for i in range(roles): node.query(f"DROP ROLE IF EXISTS role{i}") - with Scenario("I set default role for current user", flags = TE, requirements=[ + with Scenario("I set default role for current user", requirements=[ RQ_SRS_006_RBAC_SetRole_Default("1.0")]): with When("I set default role for current user"): node.query("SET ROLE DEFAULT") - with Scenario("I set no role for current user", flags = TE, requirements=[ + with Scenario("I set no role for current user", requirements=[ RQ_SRS_006_RBAC_SetRole_None("1.0")]): with When("I set no role for current user"): node.query("SET ROLE NONE") - with Scenario("I set nonexistent role, throws exception", flags = TE, requirements=[ + with Scenario("I set nonexistent role, throws exception", requirements=[ RQ_SRS_006_RBAC_SetRole_None("1.0")]): with Given("I ensure that role role5 does not exist"): node.query("DROP ROLE IF EXISTS role5") @@ -47,7 +47,7 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.role_not_found_in_disk("role5") node.query("SET ROLE role5", exitcode=exitcode, message=message) - with Scenario("I set nonexistent role, throws exception", flags = TE, requirements=[ + with Scenario("I set nonexistent role, throws exception", requirements=[ RQ_SRS_006_RBAC_SetRole_None("1.0")]): with Given("I ensure that role role5 does not exist"): node.query("DROP ROLE IF EXISTS role5") @@ -55,7 +55,7 @@ def feature(self, node="clickhouse1"): exitcode, message = errors.role_not_found_in_disk("role5") node.query("SET ROLE ALL EXCEPT role5", exitcode=exitcode, message=message) - with Scenario("I set one role for current user", flags = TE, requirements=[ + with Scenario("I set one role for current user", requirements=[ RQ_SRS_006_RBAC_SetRole("1.0")]): with setup(1): with Given("I have a user"): @@ -67,7 +67,7 @@ def feature(self, node="clickhouse1"): with Finally("I drop the user"): node.query("DROP USER user0") - with Scenario("I set multiple roles for current user", flags = TE, requirements=[ + with Scenario("I set multiple roles for current user", requirements=[ RQ_SRS_006_RBAC_SetRole("1.0")]): with setup(2): with Given("I have a user"): @@ -79,12 +79,12 @@ def feature(self, node="clickhouse1"): with Finally("I drop the user"): node.query("DROP USER user0") - with Scenario("I set all roles for current user", flags = TE, requirements=[ + with Scenario("I set all roles for current user", requirements=[ RQ_SRS_006_RBAC_SetRole_All("1.0")]): with When("I set all roles for current user"): node.query("SET ROLE ALL") - with Scenario("I set all roles except one for current user", flags = TE, requirements=[ + with Scenario("I set all roles except one for current user", requirements=[ RQ_SRS_006_RBAC_SetRole_AllExcept("1.0")]): with setup(1): with When("I run set role command"): diff --git a/tests/testflows/rbac/tests/syntax/show_create_quota.py b/tests/testflows/rbac/tests/syntax/show_create_quota.py index 0954a24d2db..f29b3f5bcc6 100755 --- a/tests/testflows/rbac/tests/syntax/show_create_quota.py +++ b/tests/testflows/rbac/tests/syntax/show_create_quota.py @@ -25,19 +25,19 @@ def feature(self, node="clickhouse1"): with Finally("I drop the quota"): node.query(f"DROP QUOTA IF EXISTS {quota}") - with Scenario("I show create quota", flags=TE, requirements=[ + with Scenario("I show create quota", requirements=[ RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Name("1.0")]): with cleanup("quota0"): with When("I run show create quota command"): node.query("SHOW CREATE QUOTA quota0") - with Scenario("I show create quota current", flags=TE, requirements=[ + with Scenario("I show create quota current", requirements=[ RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Current("1.0")]): with cleanup("quota1"): with When("I run show create quota command"): node.query("SHOW CREATE QUOTA CURRENT") - with Scenario("I show create quota current short form", flags=TE, requirements=[ + with Scenario("I show create quota current short form", requirements=[ RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Current("1.0")]): with cleanup("quota2"): with When("I run show create quota command"): diff --git a/tests/testflows/rbac/tests/syntax/show_create_role.py b/tests/testflows/rbac/tests/syntax/show_create_role.py index 11ce7371ba2..0b2adba96e2 100755 --- a/tests/testflows/rbac/tests/syntax/show_create_role.py +++ b/tests/testflows/rbac/tests/syntax/show_create_role.py @@ -26,13 +26,13 @@ def feature(self, node="clickhouse1"): with Finally("I drop the role"): node.query(f"DROP ROLE IF EXISTS {role}") - with Scenario("I show create role", flags=TE, requirements=[ + with Scenario("I show create role", requirements=[ RQ_SRS_006_RBAC_Role_ShowCreate("1.0")]): with setup("role0"): with When("I run show create role command"): node.query("SHOW CREATE ROLE role0") - with Scenario("I show create role, role doesn't exist, exception", flags=TE, requirements=[ + with Scenario("I show create role, role doesn't exist, exception", requirements=[ RQ_SRS_006_RBAC_Role_ShowCreate("1.0")]): with When("I run show create role to catch an exception"): exitcode, message = errors.role_not_found_in_disk(name="role0") diff --git a/tests/testflows/rbac/tests/syntax/show_create_row_policy.py b/tests/testflows/rbac/tests/syntax/show_create_row_policy.py index 5d8b104540c..cf43c0f2b41 100755 --- a/tests/testflows/rbac/tests/syntax/show_create_row_policy.py +++ b/tests/testflows/rbac/tests/syntax/show_create_row_policy.py @@ -29,19 +29,19 @@ def feature(self, node="clickhouse1"): with Given("I have a table"): node.query(f"CREATE TABLE default.foo (x UInt64, y String) Engine=Memory") - with Scenario("I show create row policy", flags=TE, requirements=[ + with Scenario("I show create row policy", requirements=[ RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy("1.0")]): with cleanup("policy0"): with When("I run show create row policy command"): node.query("SHOW CREATE ROW POLICY policy0 ON default.foo") - with Scenario("I show create row policy on a table", flags=TE, requirements=[ + with Scenario("I show create row policy on a table", requirements=[ RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy_On("1.0")]): with cleanup("policy0"): with When("I run show create row policy command"): node.query("SHOW CREATE ROW POLICY policy0 ON default.foo") - with Scenario("I show create row policy using short syntax on a table", flags=TE, requirements=[ + with Scenario("I show create row policy using short syntax on a table", requirements=[ RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy_On("1.0")]): with cleanup("policy1",on="foo"): with When("I run show create row policy command"): diff --git a/tests/testflows/rbac/tests/syntax/show_create_settings_profile.py b/tests/testflows/rbac/tests/syntax/show_create_settings_profile.py index 6f715463539..4af4e37951a 100755 --- a/tests/testflows/rbac/tests/syntax/show_create_settings_profile.py +++ b/tests/testflows/rbac/tests/syntax/show_create_settings_profile.py @@ -25,13 +25,13 @@ def feature(self, node="clickhouse1"): with Finally("I drop the settings profile"): node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}") - with Scenario("I show create settings profile", flags=TE, requirements=[ + with Scenario("I show create settings profile", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_ShowCreateSettingsProfile("1.0")]): with cleanup("profile0"): with When("I run show create settings profile command"): node.query("SHOW CREATE SETTINGS PROFILE profile0") - with Scenario("I show create settings profile short form", flags=TE, requirements=[ + with Scenario("I show create settings profile short form", requirements=[ RQ_SRS_006_RBAC_SettingsProfile_ShowCreateSettingsProfile("1.0")]): with cleanup("profile1"): with When("I run show create settings profile command"): diff --git a/tests/testflows/rbac/tests/syntax/show_create_user.py b/tests/testflows/rbac/tests/syntax/show_create_user.py index 804b7e06959..963e0d5d193 100755 --- a/tests/testflows/rbac/tests/syntax/show_create_user.py +++ b/tests/testflows/rbac/tests/syntax/show_create_user.py @@ -25,13 +25,13 @@ def feature(self, node="clickhouse1"): with Finally("I drop the user"): node.query(f"DROP USER IF EXISTS {user}") - with Scenario("I run show create on user with no options", flags=TE, requirements=[ + with Scenario("I run show create on user with no options", requirements=[ RQ_SRS_006_RBAC_User_ShowCreateUser_For("1.0")]): with setup("user0"): with When("I run show create user command"): node.query("SHOW CREATE USER user0") - with Scenario("I run show create on current user", flags=TE, requirements=[ + with Scenario("I run show create on current user", requirements=[ RQ_SRS_006_RBAC_User_ShowCreateUser("1.0")]): with When("I show create the current user"): node.query("SHOW CREATE USER CURRENT_USER") \ No newline at end of file diff --git a/tests/testflows/rbac/tests/syntax/show_grants.py b/tests/testflows/rbac/tests/syntax/show_grants.py index f6c797a6d76..18165ba98a5 100755 --- a/tests/testflows/rbac/tests/syntax/show_grants.py +++ b/tests/testflows/rbac/tests/syntax/show_grants.py @@ -25,13 +25,13 @@ def feature(self, node="clickhouse1"): with Finally("I drop the user"): node.query(f"DROP USER IF EXISTS {user}") - with Scenario("I show grants for user", flags=TE, requirements=[ + with Scenario("I show grants for user", requirements=[ RQ_SRS_006_RBAC_Show_Grants_For("1.0")]): with setup("user0"): with When("I run show grants command"): node.query("SHOW GRANTS FOR user0") - with Scenario("I show grants for current user", flags=TE, requirements=[ + with Scenario("I show grants for current user", requirements=[ RQ_SRS_006_RBAC_Show_Grants("1.0")]): with When("I show grants"): node.query("SHOW GRANTS") \ No newline at end of file diff --git a/tests/testflows/rbac/tests/syntax/show_quotas.py b/tests/testflows/rbac/tests/syntax/show_quotas.py index 4003207354d..5fbae718a29 100755 --- a/tests/testflows/rbac/tests/syntax/show_quotas.py +++ b/tests/testflows/rbac/tests/syntax/show_quotas.py @@ -25,25 +25,25 @@ def feature(self, node="clickhouse1"): with Finally("I drop the quota"): node.query(f"DROP QUOTA IF EXISTS {quota}") - with Scenario("I show quotas", flags=TE, requirements=[ + with Scenario("I show quotas", requirements=[ RQ_SRS_006_RBAC_Quota_ShowQuotas("1.0")]): with cleanup("quota0"), cleanup("quota1"): with When("I run show quota command"): node.query("SHOW QUOTAS") - with Scenario("I show quotas into outfile", flags=TE, requirements=[ + with Scenario("I show quotas into outfile", requirements=[ RQ_SRS_006_RBAC_Quota_ShowQuotas_IntoOutfile("1.0")]): with cleanup("quota0"), cleanup("quota1"): with When("I run show quota command"): node.query("SHOW QUOTAS INTO OUTFILE 'quotas.txt'") - with Scenario("I show quotas with format", flags=TE, requirements=[ + with Scenario("I show quotas with format", requirements=[ RQ_SRS_006_RBAC_Quota_ShowQuotas_Format("1.0")]): with cleanup("quota0"), cleanup("quota1"): with When("I run show quota command"): node.query("SHOW QUOTAS FORMAT TabSeparated") - with Scenario("I show quotas with settings", flags=TE, requirements=[ + with Scenario("I show quotas with settings", requirements=[ RQ_SRS_006_RBAC_Quota_ShowQuotas("1.0")]): with cleanup("quota0"), cleanup("quota1"): with When("I run show quota command"): diff --git a/tests/testflows/rbac/tests/syntax/show_row_policies.py b/tests/testflows/rbac/tests/syntax/show_row_policies.py index 2bc1471fbe1..0dc7f7f1d1a 100755 --- a/tests/testflows/rbac/tests/syntax/show_row_policies.py +++ b/tests/testflows/rbac/tests/syntax/show_row_policies.py @@ -29,25 +29,25 @@ def feature(self, node="clickhouse1"): with Given("I have a table"): node.query(f"CREATE TABLE default.foo (x UInt64, y String) Engine=Memory") - with Scenario("I show row policies", flags=TE, requirements=[ + with Scenario("I show row policies", requirements=[ RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies("1.0")]): with cleanup("policy0"): with When("I run drop row policy command"): node.query("SHOW ROW POLICIES") - with Scenario("I show row policies using short syntax", flags=TE, requirements=[ + with Scenario("I show row policies using short syntax", requirements=[ RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies("1.0")]): with cleanup("policy1"): with When("I run drop row policy command"): node.query("SHOW POLICIES") - with Scenario("I show row policies on a database table", flags=TE, requirements=[ + with Scenario("I show row policies on a database table", requirements=[ RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_On("1.0")]): with cleanup("policy0"): with When("I run drop row policy command"): node.query("SHOW ROW POLICIES ON default.foo") - with Scenario("I show row policies on a table", flags=TE, requirements=[ + with Scenario("I show row policies on a table", requirements=[ RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_On("1.0")]): with cleanup("policy0"): with When("I run drop row policy command"): diff --git a/tests/testflows/rbac/tests/views/live_view.py b/tests/testflows/rbac/tests/views/live_view.py index a510877a95b..f0bc381bd84 100755 --- a/tests/testflows/rbac/tests/views/live_view.py +++ b/tests/testflows/rbac/tests/views/live_view.py @@ -1133,9 +1133,13 @@ def feature(self, stress=None, parallel=None, node="clickhouse1"): tasks = [] pool = Pool(3) + with allow_experimental_live_view(self.context.node): try: - for suite in loads(current_module(), Suite): - run_scenario(pool, tasks, suite) + try: + for suite in loads(current_module(), Suite): + run_scenario(pool, tasks, suite) + finally: + join(tasks) finally: - join(tasks) + pool.close() diff --git a/tests/testflows/rbac/tests/views/materialized_view.py b/tests/testflows/rbac/tests/views/materialized_view.py index fc3b393c114..b2b1d19e256 100755 --- a/tests/testflows/rbac/tests/views/materialized_view.py +++ b/tests/testflows/rbac/tests/views/materialized_view.py @@ -612,13 +612,17 @@ def create_with_populate_privilege_granted_directly_or_via_role(self, node=None) if node is None: node = self.context.node + with user(node, f"{user_name}"): + Scenario(test=create_with_populate, name="create with populate privilege granted directly")(grant_target_name=user_name, user_name=user_name) with user(node, f"{user_name}"), role(node, f"{role_name}"): + with When("I grant the role to the user"): node.query(f"GRANT {role_name} TO {user_name}") + Scenario(test=create_with_populate, name="create with populate privilege granted through a role")(grant_target_name=role_name, user_name=user_name) @@ -632,17 +636,22 @@ def create_with_populate(self, user_name, grant_target_name, node=None): if node is None: node = self.context.node + try: + with When("I grant CREATE VIEW privilege"): node.query(f"GRANT CREATE VIEW ON {view_name} TO {grant_target_name}") + with Then("I attempt to create a view as the user"): node.query(f"CREATE MATERIALIZED VIEW {view_name} ENGINE = Memory POPULATE AS SELECT 1", settings = [("user", f"{user_name}")], exitcode=exitcode, message=message) with When("I grant INSERT privilege on the view"): node.query(f"GRANT INSERT ON {view_name} TO {grant_target_name}") + with Given("I don't have a view"): node.query(f"DROP VIEW IF EXISTS {view_name}") + with Then("I attempt to create a view as the user"): node.query(f"CREATE MATERIALIZED VIEW {view_name} ENGINE = Memory POPULATE AS SELECT 1", settings = [("user", f"{user_name}")]) @@ -2262,7 +2271,10 @@ def feature(self, stress=None, parallel=None, node="clickhouse1"): pool = Pool(3) try: - for suite in loads(current_module(), Suite): - run_scenario(pool, tasks, suite) + try: + for suite in loads(current_module(), Suite): + run_scenario(pool, tasks, suite) + finally: + join(tasks) finally: - join(tasks) + pool.close() diff --git a/tests/testflows/regression.py b/tests/testflows/regression.py index 0e9a821cae0..05fec3ea985 100755 --- a/tests/testflows/regression.py +++ b/tests/testflows/regression.py @@ -18,6 +18,7 @@ def regression(self, local, clickhouse_binary_path, stress=None, parallel=None): Feature(test=load("ldap.regression", "regression"))(**args) Feature(test=load("rbac.regression", "regression"))(**args) Feature(test=load("aes_encryption.regression", "regression"))(**args) + # Feature(test=load("kerberos.regression", "regression"))(**args) if main(): regression() diff --git a/tests/testflows/runner b/tests/testflows/runner index 0acc3a25945..213ff6e50d8 100755 --- a/tests/testflows/runner +++ b/tests/testflows/runner @@ -120,3 +120,11 @@ if __name__ == "__main__": print(("Running testflows container as: '" + cmd + "'.")) # testflows return non zero error code on failed tests subprocess.call(cmd, shell=True) + + result_path = os.environ.get("CLICKHOUSE_TESTS_RESULT_PATH", None) + if result_path is not None: + move_from = os.path.join(args.clickhouse_root, 'tests/testflows') + status = os.path.join(move_from, 'check_status.tsv') + results = os.path.join(move_from, 'test_results.tsv') + subprocess.call("mv {} {}".format(status, result_path), shell=True) + subprocess.call("mv {} {}".format(results, result_path), shell=True) diff --git a/tests/ubsan_suppressions.txt b/tests/ubsan_suppressions.txt index 6a55155e330..8d10b4f73dd 100644 --- a/tests/ubsan_suppressions.txt +++ b/tests/ubsan_suppressions.txt @@ -1 +1,5 @@ -# We have no suppressions! +# https://github.com/llvm-mirror/compiler-rt/blob/master/lib/ubsan/ubsan_checks.inc + +# Some value is outside the range of representable values of type 'long' on user-provided data inside boost::geometry - ignore. +src:*/Functions/pointInPolygon.cpp +src:*/contrib/boost/boost/geometry/* diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index a27a7e9dadc..d38b34f3419 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -27,12 +27,12 @@ if (NOT DEFINED ENABLE_UTILS OR ENABLE_UTILS) add_subdirectory (zookeeper-adjust-block-numbers-to-parts) add_subdirectory (wikistat-loader) add_subdirectory (check-marks) - add_subdirectory (test-data-generator) add_subdirectory (convert-month-partitioned-parts) add_subdirectory (checksum-for-compressed-block) add_subdirectory (db-generator) add_subdirectory (wal-dump) add_subdirectory (check-mysql-binlog) + add_subdirectory (memcpy-bench) endif () if (ENABLE_CODE_QUALITY) diff --git a/utils/check-style/check-style b/utils/check-style/check-style index f62c7ca5849..f8926a9af2f 100755 --- a/utils/check-style/check-style +++ b/utils/check-style/check-style @@ -72,6 +72,10 @@ find $ROOT_PATH/{src,base,programs,utils} -name '*.xml' | # FIXME: for now only clickhouse-test pylint --rcfile=$ROOT_PATH/.pylintrc --score=n $ROOT_PATH/tests/clickhouse-test +find $ROOT_PATH -not -path $ROOT_PATH'/contrib*' \( -name '*.yaml' -or -name '*.yml' \) -type f | + grep -vP $EXCLUDE_DIRS | + xargs yamllint --config-file=$ROOT_PATH/.yamllint + # Machine translation to Russian is strictly prohibited find $ROOT_PATH/docs/ru -name '*.md' | grep -vP $EXCLUDE_DIRS | diff --git a/utils/convert-month-partitioned-parts/main.cpp b/utils/convert-month-partitioned-parts/main.cpp index bce1e08077c..0a697937eb6 100644 --- a/utils/convert-month-partitioned-parts/main.cpp +++ b/utils/convert-month-partitioned-parts/main.cpp @@ -97,6 +97,8 @@ void run(String part_path, String date_column, String dest_path) Poco::File(new_tmp_part_path_str + "checksums.txt").setWriteable(); WriteBufferFromFile checksums_out(new_tmp_part_path_str + "checksums.txt", 4096); checksums.write(checksums_out); + checksums_in.close(); + checksums_out.close(); Poco::File(new_tmp_part_path).renameTo(new_part_path.toString()); } diff --git a/utils/github/backport.py b/utils/github/backport.py index 576e3b069c2..7fddbbee241 100644 --- a/utils/github/backport.py +++ b/utils/github/backport.py @@ -62,7 +62,7 @@ class Backport: RE_NO_BACKPORT = re.compile(r'^v(\d+\.\d+)-no-backport$') RE_BACKPORTED = re.compile(r'^v(\d+\.\d+)-backported$') - # pull-requests are sorted by ancestry from the least recent. + # pull-requests are sorted by ancestry from the most recent. for pr in pull_requests: while repo.comparator(branches[-1][1]) >= repo.comparator(pr['mergeCommit']['oid']): logging.info("PR #{} is already inside {}. Dropping this branch for further PRs".format(pr['number'], branches[-1][0])) diff --git a/utils/github/local.py b/utils/github/local.py index a997721bc76..2ad8d4b8b71 100644 --- a/utils/github/local.py +++ b/utils/github/local.py @@ -6,15 +6,15 @@ import os import re -class RepositoryBase(object): +class RepositoryBase: def __init__(self, repo_path): import git self._repo = git.Repo(repo_path, search_parent_directories=(not repo_path)) - # commit comparator + # comparator of commits def cmp(x, y): - if x == y: + if str(x) == str(y): return 0 if self._repo.is_ancestor(x, y): return -1 diff --git a/utils/list-versions/version_date.tsv b/utils/list-versions/version_date.tsv index 8d05f5fff46..5edbc4bca1a 100644 --- a/utils/list-versions/version_date.tsv +++ b/utils/list-versions/version_date.tsv @@ -1,6 +1,16 @@ +v21.3.2.5-lts 2021-03-12 +v21.2.5.5-stable 2021-03-02 +v21.2.4.6-stable 2021-02-20 +v21.2.3.15-stable 2021-02-14 v21.2.2.8-stable 2021-02-07 +v21.1.6.13-stable 2021-03-02 +v21.1.5.4-stable 2021-02-20 +v21.1.4.46-stable 2021-02-14 v21.1.3.32-stable 2021-02-03 v21.1.2.15-stable 2021-01-18 +v20.12.8.5-stable 2021-03-02 +v20.12.7.3-stable 2021-02-20 +v20.12.6.29-stable 2021-02-14 v20.12.5.18-stable 2021-02-03 v20.12.5.14-stable 2020-12-28 v20.12.4.5-stable 2020-12-24 @@ -24,6 +34,8 @@ v20.9.5.5-stable 2020-11-13 v20.9.4.76-stable 2020-10-29 v20.9.3.45-stable 2020-10-09 v20.9.2.20-stable 2020-09-22 +v20.8.14.4-lts 2021-03-03 +v20.8.13.15-lts 2021-02-20 v20.8.12.2-lts 2021-01-16 v20.8.11.17-lts 2020-12-25 v20.8.10.13-lts 2020-12-24 diff --git a/utils/memcpy-bench/CMakeLists.txt b/utils/memcpy-bench/CMakeLists.txt new file mode 100644 index 00000000000..54dd0398912 --- /dev/null +++ b/utils/memcpy-bench/CMakeLists.txt @@ -0,0 +1,5 @@ +enable_language(ASM) +add_executable (memcpy-bench memcpy-bench.cpp memcpy_jart.S) +#target_compile_options(memcpy-bench PRIVATE -mavx) +target_link_libraries(memcpy-bench PRIVATE dbms) + diff --git a/utils/memcpy-bench/FastMemcpy.h b/utils/memcpy-bench/FastMemcpy.h new file mode 100644 index 00000000000..9c37524443a --- /dev/null +++ b/utils/memcpy-bench/FastMemcpy.h @@ -0,0 +1,770 @@ +#pragma once + +//===================================================================== +// +// FastMemcpy.c - skywind3000@163.com, 2015 +// +// feature: +// 50% speed up in avg. vs standard memcpy (tested in vc2012/gcc5.1) +// +//===================================================================== + +#include +#include +#include + + +//--------------------------------------------------------------------- +// force inline for compilers +//--------------------------------------------------------------------- +#ifndef INLINE +#ifdef __GNUC__ +#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) + #define INLINE __inline__ __attribute__((always_inline)) +#else + #define INLINE __inline__ +#endif +#elif defined(_MSC_VER) + #define INLINE __forceinline +#elif (defined(__BORLANDC__) || defined(__WATCOMC__)) + #define INLINE __inline +#else + #define INLINE +#endif +#endif + +typedef __attribute__((__aligned__(1))) uint16_t uint16_unaligned_t; +typedef __attribute__((__aligned__(1))) uint32_t uint32_unaligned_t; +typedef __attribute__((__aligned__(1))) uint64_t uint64_unaligned_t; + +//--------------------------------------------------------------------- +// fast copy for different sizes +//--------------------------------------------------------------------- +static INLINE void memcpy_sse2_16(void * __restrict dst, const void * __restrict src) +{ + __m128i m0 = _mm_loadu_si128((reinterpret_cast(src)) + 0); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 0, m0); +} + +static INLINE void memcpy_sse2_32(void * __restrict dst, const void * __restrict src) +{ + __m128i m0 = _mm_loadu_si128((reinterpret_cast(src)) + 0); + __m128i m1 = _mm_loadu_si128((reinterpret_cast(src)) + 1); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 0, m0); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 1, m1); +} + +static INLINE void memcpy_sse2_64(void * __restrict dst, const void * __restrict src) +{ + __m128i m0 = _mm_loadu_si128((reinterpret_cast(src)) + 0); + __m128i m1 = _mm_loadu_si128((reinterpret_cast(src)) + 1); + __m128i m2 = _mm_loadu_si128((reinterpret_cast(src)) + 2); + __m128i m3 = _mm_loadu_si128((reinterpret_cast(src)) + 3); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 0, m0); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 1, m1); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 2, m2); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 3, m3); +} + +static INLINE void memcpy_sse2_128(void * __restrict dst, const void * __restrict src) +{ + __m128i m0 = _mm_loadu_si128((reinterpret_cast(src)) + 0); + __m128i m1 = _mm_loadu_si128((reinterpret_cast(src)) + 1); + __m128i m2 = _mm_loadu_si128((reinterpret_cast(src)) + 2); + __m128i m3 = _mm_loadu_si128((reinterpret_cast(src)) + 3); + __m128i m4 = _mm_loadu_si128((reinterpret_cast(src)) + 4); + __m128i m5 = _mm_loadu_si128((reinterpret_cast(src)) + 5); + __m128i m6 = _mm_loadu_si128((reinterpret_cast(src)) + 6); + __m128i m7 = _mm_loadu_si128((reinterpret_cast(src)) + 7); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 0, m0); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 1, m1); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 2, m2); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 3, m3); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 4, m4); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 5, m5); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 6, m6); + _mm_storeu_si128((reinterpret_cast<__m128i*>(dst)) + 7, m7); +} + + +//--------------------------------------------------------------------- +// tiny memory copy with jump table optimized +//--------------------------------------------------------------------- +/// Attribute is used to avoid an error with undefined behaviour sanitizer +/// ../contrib/FastMemcpy/FastMemcpy.h:91:56: runtime error: applying zero offset to null pointer +/// Found by 01307_orc_output_format.sh, cause - ORCBlockInputFormat and external ORC library. +__attribute__((__no_sanitize__("undefined"))) static INLINE void *memcpy_tiny(void * __restrict dst, const void * __restrict src, size_t size) +{ + unsigned char *dd = ((unsigned char*)dst) + size; + const unsigned char *ss = ((const unsigned char*)src) + size; + + switch (size) + { + case 64: + memcpy_sse2_64(dd - 64, ss - 64); + [[fallthrough]]; + case 0: + break; + + case 65: + memcpy_sse2_64(dd - 65, ss - 65); + [[fallthrough]]; + case 1: + dd[-1] = ss[-1]; + break; + + case 66: + memcpy_sse2_64(dd - 66, ss - 66); + [[fallthrough]]; + case 2: + *((uint16_unaligned_t*)(dd - 2)) = *((const uint16_unaligned_t*)(ss - 2)); + break; + + case 67: + memcpy_sse2_64(dd - 67, ss - 67); + [[fallthrough]]; + case 3: + *((uint16_unaligned_t*)(dd - 3)) = *((const uint16_unaligned_t*)(ss - 3)); + dd[-1] = ss[-1]; + break; + + case 68: + memcpy_sse2_64(dd - 68, ss - 68); + [[fallthrough]]; + case 4: + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 69: + memcpy_sse2_64(dd - 69, ss - 69); + [[fallthrough]]; + case 5: + *((uint32_unaligned_t*)(dd - 5)) = *((const uint32_unaligned_t*)(ss - 5)); + dd[-1] = ss[-1]; + break; + + case 70: + memcpy_sse2_64(dd - 70, ss - 70); + [[fallthrough]]; + case 6: + *((uint32_unaligned_t*)(dd - 6)) = *((const uint32_unaligned_t*)(ss - 6)); + *((uint16_unaligned_t*)(dd - 2)) = *((const uint16_unaligned_t*)(ss - 2)); + break; + + case 71: + memcpy_sse2_64(dd - 71, ss - 71); + [[fallthrough]]; + case 7: + *((uint32_unaligned_t*)(dd - 7)) = *((const uint32_unaligned_t*)(ss - 7)); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 72: + memcpy_sse2_64(dd - 72, ss - 72); + [[fallthrough]]; + case 8: + *((uint64_unaligned_t*)(dd - 8)) = *((const uint64_unaligned_t*)(ss - 8)); + break; + + case 73: + memcpy_sse2_64(dd - 73, ss - 73); + [[fallthrough]]; + case 9: + *((uint64_unaligned_t*)(dd - 9)) = *((const uint64_unaligned_t*)(ss - 9)); + dd[-1] = ss[-1]; + break; + + case 74: + memcpy_sse2_64(dd - 74, ss - 74); + [[fallthrough]]; + case 10: + *((uint64_unaligned_t*)(dd - 10)) = *((const uint64_unaligned_t*)(ss - 10)); + *((uint16_unaligned_t*)(dd - 2)) = *((const uint16_unaligned_t*)(ss - 2)); + break; + + case 75: + memcpy_sse2_64(dd - 75, ss - 75); + [[fallthrough]]; + case 11: + *((uint64_unaligned_t*)(dd - 11)) = *((const uint64_unaligned_t*)(ss - 11)); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 76: + memcpy_sse2_64(dd - 76, ss - 76); + [[fallthrough]]; + case 12: + *((uint64_unaligned_t*)(dd - 12)) = *((const uint64_unaligned_t*)(ss - 12)); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 77: + memcpy_sse2_64(dd - 77, ss - 77); + [[fallthrough]]; + case 13: + *((uint64_unaligned_t*)(dd - 13)) = *((const uint64_unaligned_t*)(ss - 13)); + *((uint32_unaligned_t*)(dd - 5)) = *((const uint32_unaligned_t*)(ss - 5)); + dd[-1] = ss[-1]; + break; + + case 78: + memcpy_sse2_64(dd - 78, ss - 78); + [[fallthrough]]; + case 14: + *((uint64_unaligned_t*)(dd - 14)) = *((const uint64_unaligned_t*)(ss - 14)); + *((uint64_unaligned_t*)(dd - 8)) = *((const uint64_unaligned_t*)(ss - 8)); + break; + + case 79: + memcpy_sse2_64(dd - 79, ss - 79); + [[fallthrough]]; + case 15: + *((uint64_unaligned_t*)(dd - 15)) = *((const uint64_unaligned_t*)(ss - 15)); + *((uint64_unaligned_t*)(dd - 8)) = *((const uint64_unaligned_t*)(ss - 8)); + break; + + case 80: + memcpy_sse2_64(dd - 80, ss - 80); + [[fallthrough]]; + case 16: + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 81: + memcpy_sse2_64(dd - 81, ss - 81); + [[fallthrough]]; + case 17: + memcpy_sse2_16(dd - 17, ss - 17); + dd[-1] = ss[-1]; + break; + + case 82: + memcpy_sse2_64(dd - 82, ss - 82); + [[fallthrough]]; + case 18: + memcpy_sse2_16(dd - 18, ss - 18); + *((uint16_unaligned_t*)(dd - 2)) = *((const uint16_unaligned_t*)(ss - 2)); + break; + + case 83: + memcpy_sse2_64(dd - 83, ss - 83); + [[fallthrough]]; + case 19: + memcpy_sse2_16(dd - 19, ss - 19); + *((uint16_unaligned_t*)(dd - 3)) = *((const uint16_unaligned_t*)(ss - 3)); + dd[-1] = ss[-1]; + break; + + case 84: + memcpy_sse2_64(dd - 84, ss - 84); + [[fallthrough]]; + case 20: + memcpy_sse2_16(dd - 20, ss - 20); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 85: + memcpy_sse2_64(dd - 85, ss - 85); + [[fallthrough]]; + case 21: + memcpy_sse2_16(dd - 21, ss - 21); + *((uint32_unaligned_t*)(dd - 5)) = *((const uint32_unaligned_t*)(ss - 5)); + dd[-1] = ss[-1]; + break; + + case 86: + memcpy_sse2_64(dd - 86, ss - 86); + [[fallthrough]]; + case 22: + memcpy_sse2_16(dd - 22, ss - 22); + *((uint32_unaligned_t*)(dd - 6)) = *((const uint32_unaligned_t*)(ss - 6)); + *((uint16_unaligned_t*)(dd - 2)) = *((const uint16_unaligned_t*)(ss - 2)); + break; + + case 87: + memcpy_sse2_64(dd - 87, ss - 87); + [[fallthrough]]; + case 23: + memcpy_sse2_16(dd - 23, ss - 23); + *((uint32_unaligned_t*)(dd - 7)) = *((const uint32_unaligned_t*)(ss - 7)); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 88: + memcpy_sse2_64(dd - 88, ss - 88); + [[fallthrough]]; + case 24: + memcpy_sse2_16(dd - 24, ss - 24); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 89: + memcpy_sse2_64(dd - 89, ss - 89); + [[fallthrough]]; + case 25: + memcpy_sse2_16(dd - 25, ss - 25); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 90: + memcpy_sse2_64(dd - 90, ss - 90); + [[fallthrough]]; + case 26: + memcpy_sse2_16(dd - 26, ss - 26); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 91: + memcpy_sse2_64(dd - 91, ss - 91); + [[fallthrough]]; + case 27: + memcpy_sse2_16(dd - 27, ss - 27); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 92: + memcpy_sse2_64(dd - 92, ss - 92); + [[fallthrough]]; + case 28: + memcpy_sse2_16(dd - 28, ss - 28); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 93: + memcpy_sse2_64(dd - 93, ss - 93); + [[fallthrough]]; + case 29: + memcpy_sse2_16(dd - 29, ss - 29); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 94: + memcpy_sse2_64(dd - 94, ss - 94); + [[fallthrough]]; + case 30: + memcpy_sse2_16(dd - 30, ss - 30); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 95: + memcpy_sse2_64(dd - 95, ss - 95); + [[fallthrough]]; + case 31: + memcpy_sse2_16(dd - 31, ss - 31); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 96: + memcpy_sse2_64(dd - 96, ss - 96); + [[fallthrough]]; + case 32: + memcpy_sse2_32(dd - 32, ss - 32); + break; + + case 97: + memcpy_sse2_64(dd - 97, ss - 97); + [[fallthrough]]; + case 33: + memcpy_sse2_32(dd - 33, ss - 33); + dd[-1] = ss[-1]; + break; + + case 98: + memcpy_sse2_64(dd - 98, ss - 98); + [[fallthrough]]; + case 34: + memcpy_sse2_32(dd - 34, ss - 34); + *((uint16_unaligned_t*)(dd - 2)) = *((const uint16_unaligned_t*)(ss - 2)); + break; + + case 99: + memcpy_sse2_64(dd - 99, ss - 99); + [[fallthrough]]; + case 35: + memcpy_sse2_32(dd - 35, ss - 35); + *((uint16_unaligned_t*)(dd - 3)) = *((const uint16_unaligned_t*)(ss - 3)); + dd[-1] = ss[-1]; + break; + + case 100: + memcpy_sse2_64(dd - 100, ss - 100); + [[fallthrough]]; + case 36: + memcpy_sse2_32(dd - 36, ss - 36); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 101: + memcpy_sse2_64(dd - 101, ss - 101); + [[fallthrough]]; + case 37: + memcpy_sse2_32(dd - 37, ss - 37); + *((uint32_unaligned_t*)(dd - 5)) = *((const uint32_unaligned_t*)(ss - 5)); + dd[-1] = ss[-1]; + break; + + case 102: + memcpy_sse2_64(dd - 102, ss - 102); + [[fallthrough]]; + case 38: + memcpy_sse2_32(dd - 38, ss - 38); + *((uint32_unaligned_t*)(dd - 6)) = *((const uint32_unaligned_t*)(ss - 6)); + *((uint16_unaligned_t*)(dd - 2)) = *((const uint16_unaligned_t*)(ss - 2)); + break; + + case 103: + memcpy_sse2_64(dd - 103, ss - 103); + [[fallthrough]]; + case 39: + memcpy_sse2_32(dd - 39, ss - 39); + *((uint32_unaligned_t*)(dd - 7)) = *((const uint32_unaligned_t*)(ss - 7)); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 104: + memcpy_sse2_64(dd - 104, ss - 104); + [[fallthrough]]; + case 40: + memcpy_sse2_32(dd - 40, ss - 40); + *((uint64_unaligned_t*)(dd - 8)) = *((const uint64_unaligned_t*)(ss - 8)); + break; + + case 105: + memcpy_sse2_64(dd - 105, ss - 105); + [[fallthrough]]; + case 41: + memcpy_sse2_32(dd - 41, ss - 41); + *((uint64_unaligned_t*)(dd - 9)) = *((const uint64_unaligned_t*)(ss - 9)); + dd[-1] = ss[-1]; + break; + + case 106: + memcpy_sse2_64(dd - 106, ss - 106); + [[fallthrough]]; + case 42: + memcpy_sse2_32(dd - 42, ss - 42); + *((uint64_unaligned_t*)(dd - 10)) = *((const uint64_unaligned_t*)(ss - 10)); + *((uint16_unaligned_t*)(dd - 2)) = *((const uint16_unaligned_t*)(ss - 2)); + break; + + case 107: + memcpy_sse2_64(dd - 107, ss - 107); + [[fallthrough]]; + case 43: + memcpy_sse2_32(dd - 43, ss - 43); + *((uint64_unaligned_t*)(dd - 11)) = *((const uint64_unaligned_t*)(ss - 11)); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 108: + memcpy_sse2_64(dd - 108, ss - 108); + [[fallthrough]]; + case 44: + memcpy_sse2_32(dd - 44, ss - 44); + *((uint64_unaligned_t*)(dd - 12)) = *((const uint64_unaligned_t*)(ss - 12)); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 109: + memcpy_sse2_64(dd - 109, ss - 109); + [[fallthrough]]; + case 45: + memcpy_sse2_32(dd - 45, ss - 45); + *((uint64_unaligned_t*)(dd - 13)) = *((const uint64_unaligned_t*)(ss - 13)); + *((uint32_unaligned_t*)(dd - 5)) = *((const uint32_unaligned_t*)(ss - 5)); + dd[-1] = ss[-1]; + break; + + case 110: + memcpy_sse2_64(dd - 110, ss - 110); + [[fallthrough]]; + case 46: + memcpy_sse2_32(dd - 46, ss - 46); + *((uint64_unaligned_t*)(dd - 14)) = *((const uint64_unaligned_t*)(ss - 14)); + *((uint64_unaligned_t*)(dd - 8)) = *((const uint64_unaligned_t*)(ss - 8)); + break; + + case 111: + memcpy_sse2_64(dd - 111, ss - 111); + [[fallthrough]]; + case 47: + memcpy_sse2_32(dd - 47, ss - 47); + *((uint64_unaligned_t*)(dd - 15)) = *((const uint64_unaligned_t*)(ss - 15)); + *((uint64_unaligned_t*)(dd - 8)) = *((const uint64_unaligned_t*)(ss - 8)); + break; + + case 112: + memcpy_sse2_64(dd - 112, ss - 112); + [[fallthrough]]; + case 48: + memcpy_sse2_32(dd - 48, ss - 48); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 113: + memcpy_sse2_64(dd - 113, ss - 113); + [[fallthrough]]; + case 49: + memcpy_sse2_32(dd - 49, ss - 49); + memcpy_sse2_16(dd - 17, ss - 17); + dd[-1] = ss[-1]; + break; + + case 114: + memcpy_sse2_64(dd - 114, ss - 114); + [[fallthrough]]; + case 50: + memcpy_sse2_32(dd - 50, ss - 50); + memcpy_sse2_16(dd - 18, ss - 18); + *((uint16_unaligned_t*)(dd - 2)) = *((const uint16_unaligned_t*)(ss - 2)); + break; + + case 115: + memcpy_sse2_64(dd - 115, ss - 115); + [[fallthrough]]; + case 51: + memcpy_sse2_32(dd - 51, ss - 51); + memcpy_sse2_16(dd - 19, ss - 19); + *((uint16_unaligned_t*)(dd - 3)) = *((const uint16_unaligned_t*)(ss - 3)); + dd[-1] = ss[-1]; + break; + + case 116: + memcpy_sse2_64(dd - 116, ss - 116); + [[fallthrough]]; + case 52: + memcpy_sse2_32(dd - 52, ss - 52); + memcpy_sse2_16(dd - 20, ss - 20); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 117: + memcpy_sse2_64(dd - 117, ss - 117); + [[fallthrough]]; + case 53: + memcpy_sse2_32(dd - 53, ss - 53); + memcpy_sse2_16(dd - 21, ss - 21); + *((uint32_unaligned_t*)(dd - 5)) = *((const uint32_unaligned_t*)(ss - 5)); + dd[-1] = ss[-1]; + break; + + case 118: + memcpy_sse2_64(dd - 118, ss - 118); + [[fallthrough]]; + case 54: + memcpy_sse2_32(dd - 54, ss - 54); + memcpy_sse2_16(dd - 22, ss - 22); + *((uint32_unaligned_t*)(dd - 6)) = *((const uint32_unaligned_t*)(ss - 6)); + *((uint16_unaligned_t*)(dd - 2)) = *((const uint16_unaligned_t*)(ss - 2)); + break; + + case 119: + memcpy_sse2_64(dd - 119, ss - 119); + [[fallthrough]]; + case 55: + memcpy_sse2_32(dd - 55, ss - 55); + memcpy_sse2_16(dd - 23, ss - 23); + *((uint32_unaligned_t*)(dd - 7)) = *((const uint32_unaligned_t*)(ss - 7)); + *((uint32_unaligned_t*)(dd - 4)) = *((const uint32_unaligned_t*)(ss - 4)); + break; + + case 120: + memcpy_sse2_64(dd - 120, ss - 120); + [[fallthrough]]; + case 56: + memcpy_sse2_32(dd - 56, ss - 56); + memcpy_sse2_16(dd - 24, ss - 24); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 121: + memcpy_sse2_64(dd - 121, ss - 121); + [[fallthrough]]; + case 57: + memcpy_sse2_32(dd - 57, ss - 57); + memcpy_sse2_16(dd - 25, ss - 25); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 122: + memcpy_sse2_64(dd - 122, ss - 122); + [[fallthrough]]; + case 58: + memcpy_sse2_32(dd - 58, ss - 58); + memcpy_sse2_16(dd - 26, ss - 26); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 123: + memcpy_sse2_64(dd - 123, ss - 123); + [[fallthrough]]; + case 59: + memcpy_sse2_32(dd - 59, ss - 59); + memcpy_sse2_16(dd - 27, ss - 27); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 124: + memcpy_sse2_64(dd - 124, ss - 124); + [[fallthrough]]; + case 60: + memcpy_sse2_32(dd - 60, ss - 60); + memcpy_sse2_16(dd - 28, ss - 28); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 125: + memcpy_sse2_64(dd - 125, ss - 125); + [[fallthrough]]; + case 61: + memcpy_sse2_32(dd - 61, ss - 61); + memcpy_sse2_16(dd - 29, ss - 29); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 126: + memcpy_sse2_64(dd - 126, ss - 126); + [[fallthrough]]; + case 62: + memcpy_sse2_32(dd - 62, ss - 62); + memcpy_sse2_16(dd - 30, ss - 30); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 127: + memcpy_sse2_64(dd - 127, ss - 127); + [[fallthrough]]; + case 63: + memcpy_sse2_32(dd - 63, ss - 63); + memcpy_sse2_16(dd - 31, ss - 31); + memcpy_sse2_16(dd - 16, ss - 16); + break; + + case 128: + memcpy_sse2_128(dd - 128, ss - 128); + break; + } + + return dst; +} + + +//--------------------------------------------------------------------- +// main routine +//--------------------------------------------------------------------- +void* memcpy_fast_sse(void * __restrict destination, const void * __restrict source, size_t size) +{ + unsigned char *dst = (unsigned char*)destination; + const unsigned char *src = (const unsigned char*)source; + static size_t cachesize = 0x200000; // L2-cache size + size_t padding; + + // small memory copy + if (size <= 128) +{ + return memcpy_tiny(dst, src, size); + } + + // align destination to 16 bytes boundary + padding = (16 - (((size_t)dst) & 15)) & 15; + + if (padding > 0) + { + __m128i head = _mm_loadu_si128(reinterpret_cast(src)); + _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), head); + dst += padding; + src += padding; + size -= padding; + } + + // medium size copy + if (size <= cachesize) + { + __m128i c0, c1, c2, c3, c4, c5, c6, c7; + + for (; size >= 128; size -= 128) + { + c0 = _mm_loadu_si128((reinterpret_cast(src)) + 0); + c1 = _mm_loadu_si128((reinterpret_cast(src)) + 1); + c2 = _mm_loadu_si128((reinterpret_cast(src)) + 2); + c3 = _mm_loadu_si128((reinterpret_cast(src)) + 3); + c4 = _mm_loadu_si128((reinterpret_cast(src)) + 4); + c5 = _mm_loadu_si128((reinterpret_cast(src)) + 5); + c6 = _mm_loadu_si128((reinterpret_cast(src)) + 6); + c7 = _mm_loadu_si128((reinterpret_cast(src)) + 7); + _mm_prefetch((const char*)(src + 256), _MM_HINT_NTA); + src += 128; + _mm_store_si128(((reinterpret_cast<__m128i*>(dst)) + 0), c0); + _mm_store_si128(((reinterpret_cast<__m128i*>(dst)) + 1), c1); + _mm_store_si128(((reinterpret_cast<__m128i*>(dst)) + 2), c2); + _mm_store_si128(((reinterpret_cast<__m128i*>(dst)) + 3), c3); + _mm_store_si128(((reinterpret_cast<__m128i*>(dst)) + 4), c4); + _mm_store_si128(((reinterpret_cast<__m128i*>(dst)) + 5), c5); + _mm_store_si128(((reinterpret_cast<__m128i*>(dst)) + 6), c6); + _mm_store_si128(((reinterpret_cast<__m128i*>(dst)) + 7), c7); + dst += 128; + } + } + else + { // big memory copy + __m128i c0, c1, c2, c3, c4, c5, c6, c7; + + _mm_prefetch((const char*)(src), _MM_HINT_NTA); + + if ((((size_t)src) & 15) == 0) + { // source aligned + for (; size >= 128; size -= 128) + { + c0 = _mm_load_si128((reinterpret_cast(src)) + 0); + c1 = _mm_load_si128((reinterpret_cast(src)) + 1); + c2 = _mm_load_si128((reinterpret_cast(src)) + 2); + c3 = _mm_load_si128((reinterpret_cast(src)) + 3); + c4 = _mm_load_si128((reinterpret_cast(src)) + 4); + c5 = _mm_load_si128((reinterpret_cast(src)) + 5); + c6 = _mm_load_si128((reinterpret_cast(src)) + 6); + c7 = _mm_load_si128((reinterpret_cast(src)) + 7); + _mm_prefetch((const char*)(src + 256), _MM_HINT_NTA); + src += 128; + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 0), c0); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 1), c1); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 2), c2); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 3), c3); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 4), c4); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 5), c5); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 6), c6); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 7), c7); + dst += 128; + } + } + else + { // source unaligned + for (; size >= 128; size -= 128) + { + c0 = _mm_loadu_si128((reinterpret_cast(src)) + 0); + c1 = _mm_loadu_si128((reinterpret_cast(src)) + 1); + c2 = _mm_loadu_si128((reinterpret_cast(src)) + 2); + c3 = _mm_loadu_si128((reinterpret_cast(src)) + 3); + c4 = _mm_loadu_si128((reinterpret_cast(src)) + 4); + c5 = _mm_loadu_si128((reinterpret_cast(src)) + 5); + c6 = _mm_loadu_si128((reinterpret_cast(src)) + 6); + c7 = _mm_loadu_si128((reinterpret_cast(src)) + 7); + _mm_prefetch((const char*)(src + 256), _MM_HINT_NTA); + src += 128; + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 0), c0); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 1), c1); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 2), c2); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 3), c3); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 4), c4); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 5), c5); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 6), c6); + _mm_stream_si128(((reinterpret_cast<__m128i*>(dst)) + 7), c7); + dst += 128; + } + } + _mm_sfence(); + } + + memcpy_tiny(dst, src, size); + + return destination; +} diff --git a/utils/memcpy-bench/FastMemcpy_Avx.h b/utils/memcpy-bench/FastMemcpy_Avx.h new file mode 100644 index 00000000000..ee7d4e19536 --- /dev/null +++ b/utils/memcpy-bench/FastMemcpy_Avx.h @@ -0,0 +1,496 @@ +#pragma once + +//===================================================================== +// +// FastMemcpy.c - skywind3000@163.com, 2015 +// +// feature: +// 50% speed up in avg. vs standard memcpy (tested in vc2012/gcc5.1) +// +//===================================================================== + +#include +#include +#include + + +//--------------------------------------------------------------------- +// force inline for compilers +//--------------------------------------------------------------------- +#ifndef INLINE +#ifdef __GNUC__ +#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) + #define INLINE __inline__ __attribute__((always_inline)) +#else + #define INLINE __inline__ +#endif +#elif defined(_MSC_VER) + #define INLINE __forceinline +#elif (defined(__BORLANDC__) || defined(__WATCOMC__)) + #define INLINE __inline +#else + #define INLINE +#endif +#endif + + +//--------------------------------------------------------------------- +// fast copy for different sizes +//--------------------------------------------------------------------- +static INLINE void memcpy_avx_16(void * __restrict dst, const void * __restrict src) +{ +#if 1 + __m128i m0 = _mm_loadu_si128(((const __m128i*)src) + 0); + _mm_storeu_si128(((__m128i*)dst) + 0, m0); +#else + *((uint64_t*)((char*)dst + 0)) = *((uint64_t*)((const char*)src + 0)); + *((uint64_t*)((char*)dst + 8)) = *((uint64_t*)((const char*)src + 8)); +#endif +} + +static INLINE void memcpy_avx_32(void *dst, const void *src) +{ + __m256i m0 = _mm256_loadu_si256((reinterpret_cast(src)) + 0); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 0, m0); +} + +static INLINE void memcpy_avx_64(void *dst, const void *src) +{ + __m256i m0 = _mm256_loadu_si256((reinterpret_cast(src)) + 0); + __m256i m1 = _mm256_loadu_si256((reinterpret_cast(src)) + 1); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 0, m0); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 1, m1); +} + +static INLINE void memcpy_avx_128(void *dst, const void *src) +{ + __m256i m0 = _mm256_loadu_si256((reinterpret_cast(src)) + 0); + __m256i m1 = _mm256_loadu_si256((reinterpret_cast(src)) + 1); + __m256i m2 = _mm256_loadu_si256((reinterpret_cast(src)) + 2); + __m256i m3 = _mm256_loadu_si256((reinterpret_cast(src)) + 3); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 0, m0); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 1, m1); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 2, m2); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 3, m3); +} + +static INLINE void memcpy_avx_256(void *dst, const void *src) +{ + __m256i m0 = _mm256_loadu_si256((reinterpret_cast(src)) + 0); + __m256i m1 = _mm256_loadu_si256((reinterpret_cast(src)) + 1); + __m256i m2 = _mm256_loadu_si256((reinterpret_cast(src)) + 2); + __m256i m3 = _mm256_loadu_si256((reinterpret_cast(src)) + 3); + __m256i m4 = _mm256_loadu_si256((reinterpret_cast(src)) + 4); + __m256i m5 = _mm256_loadu_si256((reinterpret_cast(src)) + 5); + __m256i m6 = _mm256_loadu_si256((reinterpret_cast(src)) + 6); + __m256i m7 = _mm256_loadu_si256((reinterpret_cast(src)) + 7); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 0, m0); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 1, m1); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 2, m2); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 3, m3); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 4, m4); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 5, m5); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 6, m6); + _mm256_storeu_si256((reinterpret_cast<__m256i*>(dst)) + 7, m7); +} + + +//--------------------------------------------------------------------- +// tiny memory copy with jump table optimized +//--------------------------------------------------------------------- +static INLINE void *memcpy_tiny_avx(void * __restrict dst, const void * __restrict src, size_t size) +{ + unsigned char *dd = reinterpret_cast(dst) + size; + const unsigned char *ss = reinterpret_cast(src) + size; + + switch (size) + { + case 128: memcpy_avx_128(dd - 128, ss - 128); [[fallthrough]]; + case 0: break; + case 129: memcpy_avx_128(dd - 129, ss - 129); [[fallthrough]]; + case 1: dd[-1] = ss[-1]; break; + case 130: memcpy_avx_128(dd - 130, ss - 130); [[fallthrough]]; + case 2: *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; + case 131: memcpy_avx_128(dd - 131, ss - 131); [[fallthrough]]; + case 3: *((uint16_t*)(dd - 3)) = *((uint16_t*)(ss - 3)); dd[-1] = ss[-1]; break; + case 132: memcpy_avx_128(dd - 132, ss - 132); [[fallthrough]]; + case 4: *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; + case 133: memcpy_avx_128(dd - 133, ss - 133); [[fallthrough]]; + case 5: *((uint32_t*)(dd - 5)) = *((uint32_t*)(ss - 5)); dd[-1] = ss[-1]; break; + case 134: memcpy_avx_128(dd - 134, ss - 134); [[fallthrough]]; + case 6: *((uint32_t*)(dd - 6)) = *((uint32_t*)(ss - 6)); *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; + case 135: memcpy_avx_128(dd - 135, ss - 135); [[fallthrough]]; + case 7: *((uint32_t*)(dd - 7)) = *((uint32_t*)(ss - 7)); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; + case 136: memcpy_avx_128(dd - 136, ss - 136); [[fallthrough]]; + case 8: *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 137: memcpy_avx_128(dd - 137, ss - 137); [[fallthrough]]; + case 9: *((uint64_t*)(dd - 9)) = *((uint64_t*)(ss - 9)); dd[-1] = ss[-1]; break; + case 138: memcpy_avx_128(dd - 138, ss - 138); [[fallthrough]]; + case 10: *((uint64_t*)(dd - 10)) = *((uint64_t*)(ss - 10)); *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; + case 139: memcpy_avx_128(dd - 139, ss - 139); [[fallthrough]]; + case 11: *((uint64_t*)(dd - 11)) = *((uint64_t*)(ss - 11)); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; + case 140: memcpy_avx_128(dd - 140, ss - 140); [[fallthrough]]; + case 12: *((uint64_t*)(dd - 12)) = *((uint64_t*)(ss - 12)); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; + case 141: memcpy_avx_128(dd - 141, ss - 141); [[fallthrough]]; + case 13: *((uint64_t*)(dd - 13)) = *((uint64_t*)(ss - 13)); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 142: memcpy_avx_128(dd - 142, ss - 142); [[fallthrough]]; + case 14: *((uint64_t*)(dd - 14)) = *((uint64_t*)(ss - 14)); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 143: memcpy_avx_128(dd - 143, ss - 143); [[fallthrough]]; + case 15: *((uint64_t*)(dd - 15)) = *((uint64_t*)(ss - 15)); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 144: memcpy_avx_128(dd - 144, ss - 144); [[fallthrough]]; + case 16: memcpy_avx_16(dd - 16, ss - 16); break; + case 145: memcpy_avx_128(dd - 145, ss - 145); [[fallthrough]]; + case 17: memcpy_avx_16(dd - 17, ss - 17); dd[-1] = ss[-1]; break; + case 146: memcpy_avx_128(dd - 146, ss - 146); [[fallthrough]]; + case 18: memcpy_avx_16(dd - 18, ss - 18); *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; + case 147: memcpy_avx_128(dd - 147, ss - 147); [[fallthrough]]; + case 19: memcpy_avx_16(dd - 19, ss - 19); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; + case 148: memcpy_avx_128(dd - 148, ss - 148); [[fallthrough]]; + case 20: memcpy_avx_16(dd - 20, ss - 20); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; + case 149: memcpy_avx_128(dd - 149, ss - 149); [[fallthrough]]; + case 21: memcpy_avx_16(dd - 21, ss - 21); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 150: memcpy_avx_128(dd - 150, ss - 150); [[fallthrough]]; + case 22: memcpy_avx_16(dd - 22, ss - 22); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 151: memcpy_avx_128(dd - 151, ss - 151); [[fallthrough]]; + case 23: memcpy_avx_16(dd - 23, ss - 23); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 152: memcpy_avx_128(dd - 152, ss - 152); [[fallthrough]]; + case 24: memcpy_avx_16(dd - 24, ss - 24); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 153: memcpy_avx_128(dd - 153, ss - 153); [[fallthrough]]; + case 25: memcpy_avx_16(dd - 25, ss - 25); memcpy_avx_16(dd - 16, ss - 16); break; + case 154: memcpy_avx_128(dd - 154, ss - 154); [[fallthrough]]; + case 26: memcpy_avx_16(dd - 26, ss - 26); memcpy_avx_16(dd - 16, ss - 16); break; + case 155: memcpy_avx_128(dd - 155, ss - 155); [[fallthrough]]; + case 27: memcpy_avx_16(dd - 27, ss - 27); memcpy_avx_16(dd - 16, ss - 16); break; + case 156: memcpy_avx_128(dd - 156, ss - 156); [[fallthrough]]; + case 28: memcpy_avx_16(dd - 28, ss - 28); memcpy_avx_16(dd - 16, ss - 16); break; + case 157: memcpy_avx_128(dd - 157, ss - 157); [[fallthrough]]; + case 29: memcpy_avx_16(dd - 29, ss - 29); memcpy_avx_16(dd - 16, ss - 16); break; + case 158: memcpy_avx_128(dd - 158, ss - 158); [[fallthrough]]; + case 30: memcpy_avx_16(dd - 30, ss - 30); memcpy_avx_16(dd - 16, ss - 16); break; + case 159: memcpy_avx_128(dd - 159, ss - 159); [[fallthrough]]; + case 31: memcpy_avx_16(dd - 31, ss - 31); memcpy_avx_16(dd - 16, ss - 16); break; + case 160: memcpy_avx_128(dd - 160, ss - 160); [[fallthrough]]; + case 32: memcpy_avx_32(dd - 32, ss - 32); break; + case 161: memcpy_avx_128(dd - 161, ss - 161); [[fallthrough]]; + case 33: memcpy_avx_32(dd - 33, ss - 33); dd[-1] = ss[-1]; break; + case 162: memcpy_avx_128(dd - 162, ss - 162); [[fallthrough]]; + case 34: memcpy_avx_32(dd - 34, ss - 34); *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; + case 163: memcpy_avx_128(dd - 163, ss - 163); [[fallthrough]]; + case 35: memcpy_avx_32(dd - 35, ss - 35); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; + case 164: memcpy_avx_128(dd - 164, ss - 164); [[fallthrough]]; + case 36: memcpy_avx_32(dd - 36, ss - 36); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; + case 165: memcpy_avx_128(dd - 165, ss - 165); [[fallthrough]]; + case 37: memcpy_avx_32(dd - 37, ss - 37); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 166: memcpy_avx_128(dd - 166, ss - 166); [[fallthrough]]; + case 38: memcpy_avx_32(dd - 38, ss - 38); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 167: memcpy_avx_128(dd - 167, ss - 167); [[fallthrough]]; + case 39: memcpy_avx_32(dd - 39, ss - 39); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 168: memcpy_avx_128(dd - 168, ss - 168); [[fallthrough]]; + case 40: memcpy_avx_32(dd - 40, ss - 40); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 169: memcpy_avx_128(dd - 169, ss - 169); [[fallthrough]]; + case 41: memcpy_avx_32(dd - 41, ss - 41); memcpy_avx_16(dd - 16, ss - 16); break; + case 170: memcpy_avx_128(dd - 170, ss - 170); [[fallthrough]]; + case 42: memcpy_avx_32(dd - 42, ss - 42); memcpy_avx_16(dd - 16, ss - 16); break; + case 171: memcpy_avx_128(dd - 171, ss - 171); [[fallthrough]]; + case 43: memcpy_avx_32(dd - 43, ss - 43); memcpy_avx_16(dd - 16, ss - 16); break; + case 172: memcpy_avx_128(dd - 172, ss - 172); [[fallthrough]]; + case 44: memcpy_avx_32(dd - 44, ss - 44); memcpy_avx_16(dd - 16, ss - 16); break; + case 173: memcpy_avx_128(dd - 173, ss - 173); [[fallthrough]]; + case 45: memcpy_avx_32(dd - 45, ss - 45); memcpy_avx_16(dd - 16, ss - 16); break; + case 174: memcpy_avx_128(dd - 174, ss - 174); [[fallthrough]]; + case 46: memcpy_avx_32(dd - 46, ss - 46); memcpy_avx_16(dd - 16, ss - 16); break; + case 175: memcpy_avx_128(dd - 175, ss - 175); [[fallthrough]]; + case 47: memcpy_avx_32(dd - 47, ss - 47); memcpy_avx_16(dd - 16, ss - 16); break; + case 176: memcpy_avx_128(dd - 176, ss - 176); [[fallthrough]]; + case 48: memcpy_avx_32(dd - 48, ss - 48); memcpy_avx_16(dd - 16, ss - 16); break; + case 177: memcpy_avx_128(dd - 177, ss - 177); [[fallthrough]]; + case 49: memcpy_avx_32(dd - 49, ss - 49); memcpy_avx_32(dd - 32, ss - 32); break; + case 178: memcpy_avx_128(dd - 178, ss - 178); [[fallthrough]]; + case 50: memcpy_avx_32(dd - 50, ss - 50); memcpy_avx_32(dd - 32, ss - 32); break; + case 179: memcpy_avx_128(dd - 179, ss - 179); [[fallthrough]]; + case 51: memcpy_avx_32(dd - 51, ss - 51); memcpy_avx_32(dd - 32, ss - 32); break; + case 180: memcpy_avx_128(dd - 180, ss - 180); [[fallthrough]]; + case 52: memcpy_avx_32(dd - 52, ss - 52); memcpy_avx_32(dd - 32, ss - 32); break; + case 181: memcpy_avx_128(dd - 181, ss - 181); [[fallthrough]]; + case 53: memcpy_avx_32(dd - 53, ss - 53); memcpy_avx_32(dd - 32, ss - 32); break; + case 182: memcpy_avx_128(dd - 182, ss - 182); [[fallthrough]]; + case 54: memcpy_avx_32(dd - 54, ss - 54); memcpy_avx_32(dd - 32, ss - 32); break; + case 183: memcpy_avx_128(dd - 183, ss - 183); [[fallthrough]]; + case 55: memcpy_avx_32(dd - 55, ss - 55); memcpy_avx_32(dd - 32, ss - 32); break; + case 184: memcpy_avx_128(dd - 184, ss - 184); [[fallthrough]]; + case 56: memcpy_avx_32(dd - 56, ss - 56); memcpy_avx_32(dd - 32, ss - 32); break; + case 185: memcpy_avx_128(dd - 185, ss - 185); [[fallthrough]]; + case 57: memcpy_avx_32(dd - 57, ss - 57); memcpy_avx_32(dd - 32, ss - 32); break; + case 186: memcpy_avx_128(dd - 186, ss - 186); [[fallthrough]]; + case 58: memcpy_avx_32(dd - 58, ss - 58); memcpy_avx_32(dd - 32, ss - 32); break; + case 187: memcpy_avx_128(dd - 187, ss - 187); [[fallthrough]]; + case 59: memcpy_avx_32(dd - 59, ss - 59); memcpy_avx_32(dd - 32, ss - 32); break; + case 188: memcpy_avx_128(dd - 188, ss - 188); [[fallthrough]]; + case 60: memcpy_avx_32(dd - 60, ss - 60); memcpy_avx_32(dd - 32, ss - 32); break; + case 189: memcpy_avx_128(dd - 189, ss - 189); [[fallthrough]]; + case 61: memcpy_avx_32(dd - 61, ss - 61); memcpy_avx_32(dd - 32, ss - 32); break; + case 190: memcpy_avx_128(dd - 190, ss - 190); [[fallthrough]]; + case 62: memcpy_avx_32(dd - 62, ss - 62); memcpy_avx_32(dd - 32, ss - 32); break; + case 191: memcpy_avx_128(dd - 191, ss - 191); [[fallthrough]]; + case 63: memcpy_avx_32(dd - 63, ss - 63); memcpy_avx_32(dd - 32, ss - 32); break; + case 192: memcpy_avx_128(dd - 192, ss - 192); [[fallthrough]]; + case 64: memcpy_avx_64(dd - 64, ss - 64); break; + case 193: memcpy_avx_128(dd - 193, ss - 193); [[fallthrough]]; + case 65: memcpy_avx_64(dd - 65, ss - 65); dd[-1] = ss[-1]; break; + case 194: memcpy_avx_128(dd - 194, ss - 194); [[fallthrough]]; + case 66: memcpy_avx_64(dd - 66, ss - 66); *((uint16_t*)(dd - 2)) = *((uint16_t*)(ss - 2)); break; + case 195: memcpy_avx_128(dd - 195, ss - 195); [[fallthrough]]; + case 67: memcpy_avx_64(dd - 67, ss - 67); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; + case 196: memcpy_avx_128(dd - 196, ss - 196); [[fallthrough]]; + case 68: memcpy_avx_64(dd - 68, ss - 68); *((uint32_t*)(dd - 4)) = *((uint32_t*)(ss - 4)); break; + case 197: memcpy_avx_128(dd - 197, ss - 197); [[fallthrough]]; + case 69: memcpy_avx_64(dd - 69, ss - 69); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 198: memcpy_avx_128(dd - 198, ss - 198); [[fallthrough]]; + case 70: memcpy_avx_64(dd - 70, ss - 70); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 199: memcpy_avx_128(dd - 199, ss - 199); [[fallthrough]]; + case 71: memcpy_avx_64(dd - 71, ss - 71); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 200: memcpy_avx_128(dd - 200, ss - 200); [[fallthrough]]; + case 72: memcpy_avx_64(dd - 72, ss - 72); *((uint64_t*)(dd - 8)) = *((uint64_t*)(ss - 8)); break; + case 201: memcpy_avx_128(dd - 201, ss - 201); [[fallthrough]]; + case 73: memcpy_avx_64(dd - 73, ss - 73); memcpy_avx_16(dd - 16, ss - 16); break; + case 202: memcpy_avx_128(dd - 202, ss - 202); [[fallthrough]]; + case 74: memcpy_avx_64(dd - 74, ss - 74); memcpy_avx_16(dd - 16, ss - 16); break; + case 203: memcpy_avx_128(dd - 203, ss - 203); [[fallthrough]]; + case 75: memcpy_avx_64(dd - 75, ss - 75); memcpy_avx_16(dd - 16, ss - 16); break; + case 204: memcpy_avx_128(dd - 204, ss - 204); [[fallthrough]]; + case 76: memcpy_avx_64(dd - 76, ss - 76); memcpy_avx_16(dd - 16, ss - 16); break; + case 205: memcpy_avx_128(dd - 205, ss - 205); [[fallthrough]]; + case 77: memcpy_avx_64(dd - 77, ss - 77); memcpy_avx_16(dd - 16, ss - 16); break; + case 206: memcpy_avx_128(dd - 206, ss - 206); [[fallthrough]]; + case 78: memcpy_avx_64(dd - 78, ss - 78); memcpy_avx_16(dd - 16, ss - 16); break; + case 207: memcpy_avx_128(dd - 207, ss - 207); [[fallthrough]]; + case 79: memcpy_avx_64(dd - 79, ss - 79); memcpy_avx_16(dd - 16, ss - 16); break; + case 208: memcpy_avx_128(dd - 208, ss - 208); [[fallthrough]]; + case 80: memcpy_avx_64(dd - 80, ss - 80); memcpy_avx_16(dd - 16, ss - 16); break; + case 209: memcpy_avx_128(dd - 209, ss - 209); [[fallthrough]]; + case 81: memcpy_avx_64(dd - 81, ss - 81); memcpy_avx_32(dd - 32, ss - 32); break; + case 210: memcpy_avx_128(dd - 210, ss - 210); [[fallthrough]]; + case 82: memcpy_avx_64(dd - 82, ss - 82); memcpy_avx_32(dd - 32, ss - 32); break; + case 211: memcpy_avx_128(dd - 211, ss - 211); [[fallthrough]]; + case 83: memcpy_avx_64(dd - 83, ss - 83); memcpy_avx_32(dd - 32, ss - 32); break; + case 212: memcpy_avx_128(dd - 212, ss - 212); [[fallthrough]]; + case 84: memcpy_avx_64(dd - 84, ss - 84); memcpy_avx_32(dd - 32, ss - 32); break; + case 213: memcpy_avx_128(dd - 213, ss - 213); [[fallthrough]]; + case 85: memcpy_avx_64(dd - 85, ss - 85); memcpy_avx_32(dd - 32, ss - 32); break; + case 214: memcpy_avx_128(dd - 214, ss - 214); [[fallthrough]]; + case 86: memcpy_avx_64(dd - 86, ss - 86); memcpy_avx_32(dd - 32, ss - 32); break; + case 215: memcpy_avx_128(dd - 215, ss - 215); [[fallthrough]]; + case 87: memcpy_avx_64(dd - 87, ss - 87); memcpy_avx_32(dd - 32, ss - 32); break; + case 216: memcpy_avx_128(dd - 216, ss - 216); [[fallthrough]]; + case 88: memcpy_avx_64(dd - 88, ss - 88); memcpy_avx_32(dd - 32, ss - 32); break; + case 217: memcpy_avx_128(dd - 217, ss - 217); [[fallthrough]]; + case 89: memcpy_avx_64(dd - 89, ss - 89); memcpy_avx_32(dd - 32, ss - 32); break; + case 218: memcpy_avx_128(dd - 218, ss - 218); [[fallthrough]]; + case 90: memcpy_avx_64(dd - 90, ss - 90); memcpy_avx_32(dd - 32, ss - 32); break; + case 219: memcpy_avx_128(dd - 219, ss - 219); [[fallthrough]]; + case 91: memcpy_avx_64(dd - 91, ss - 91); memcpy_avx_32(dd - 32, ss - 32); break; + case 220: memcpy_avx_128(dd - 220, ss - 220); [[fallthrough]]; + case 92: memcpy_avx_64(dd - 92, ss - 92); memcpy_avx_32(dd - 32, ss - 32); break; + case 221: memcpy_avx_128(dd - 221, ss - 221); [[fallthrough]]; + case 93: memcpy_avx_64(dd - 93, ss - 93); memcpy_avx_32(dd - 32, ss - 32); break; + case 222: memcpy_avx_128(dd - 222, ss - 222); [[fallthrough]]; + case 94: memcpy_avx_64(dd - 94, ss - 94); memcpy_avx_32(dd - 32, ss - 32); break; + case 223: memcpy_avx_128(dd - 223, ss - 223); [[fallthrough]]; + case 95: memcpy_avx_64(dd - 95, ss - 95); memcpy_avx_32(dd - 32, ss - 32); break; + case 224: memcpy_avx_128(dd - 224, ss - 224); [[fallthrough]]; + case 96: memcpy_avx_64(dd - 96, ss - 96); memcpy_avx_32(dd - 32, ss - 32); break; + case 225: memcpy_avx_128(dd - 225, ss - 225); [[fallthrough]]; + case 97: memcpy_avx_64(dd - 97, ss - 97); memcpy_avx_64(dd - 64, ss - 64); break; + case 226: memcpy_avx_128(dd - 226, ss - 226); [[fallthrough]]; + case 98: memcpy_avx_64(dd - 98, ss - 98); memcpy_avx_64(dd - 64, ss - 64); break; + case 227: memcpy_avx_128(dd - 227, ss - 227); [[fallthrough]]; + case 99: memcpy_avx_64(dd - 99, ss - 99); memcpy_avx_64(dd - 64, ss - 64); break; + case 228: memcpy_avx_128(dd - 228, ss - 228); [[fallthrough]]; + case 100: memcpy_avx_64(dd - 100, ss - 100); memcpy_avx_64(dd - 64, ss - 64); break; + case 229: memcpy_avx_128(dd - 229, ss - 229); [[fallthrough]]; + case 101: memcpy_avx_64(dd - 101, ss - 101); memcpy_avx_64(dd - 64, ss - 64); break; + case 230: memcpy_avx_128(dd - 230, ss - 230); [[fallthrough]]; + case 102: memcpy_avx_64(dd - 102, ss - 102); memcpy_avx_64(dd - 64, ss - 64); break; + case 231: memcpy_avx_128(dd - 231, ss - 231); [[fallthrough]]; + case 103: memcpy_avx_64(dd - 103, ss - 103); memcpy_avx_64(dd - 64, ss - 64); break; + case 232: memcpy_avx_128(dd - 232, ss - 232); [[fallthrough]]; + case 104: memcpy_avx_64(dd - 104, ss - 104); memcpy_avx_64(dd - 64, ss - 64); break; + case 233: memcpy_avx_128(dd - 233, ss - 233); [[fallthrough]]; + case 105: memcpy_avx_64(dd - 105, ss - 105); memcpy_avx_64(dd - 64, ss - 64); break; + case 234: memcpy_avx_128(dd - 234, ss - 234); [[fallthrough]]; + case 106: memcpy_avx_64(dd - 106, ss - 106); memcpy_avx_64(dd - 64, ss - 64); break; + case 235: memcpy_avx_128(dd - 235, ss - 235); [[fallthrough]]; + case 107: memcpy_avx_64(dd - 107, ss - 107); memcpy_avx_64(dd - 64, ss - 64); break; + case 236: memcpy_avx_128(dd - 236, ss - 236); [[fallthrough]]; + case 108: memcpy_avx_64(dd - 108, ss - 108); memcpy_avx_64(dd - 64, ss - 64); break; + case 237: memcpy_avx_128(dd - 237, ss - 237); [[fallthrough]]; + case 109: memcpy_avx_64(dd - 109, ss - 109); memcpy_avx_64(dd - 64, ss - 64); break; + case 238: memcpy_avx_128(dd - 238, ss - 238); [[fallthrough]]; + case 110: memcpy_avx_64(dd - 110, ss - 110); memcpy_avx_64(dd - 64, ss - 64); break; + case 239: memcpy_avx_128(dd - 239, ss - 239); [[fallthrough]]; + case 111: memcpy_avx_64(dd - 111, ss - 111); memcpy_avx_64(dd - 64, ss - 64); break; + case 240: memcpy_avx_128(dd - 240, ss - 240); [[fallthrough]]; + case 112: memcpy_avx_64(dd - 112, ss - 112); memcpy_avx_64(dd - 64, ss - 64); break; + case 241: memcpy_avx_128(dd - 241, ss - 241); [[fallthrough]]; + case 113: memcpy_avx_64(dd - 113, ss - 113); memcpy_avx_64(dd - 64, ss - 64); break; + case 242: memcpy_avx_128(dd - 242, ss - 242); [[fallthrough]]; + case 114: memcpy_avx_64(dd - 114, ss - 114); memcpy_avx_64(dd - 64, ss - 64); break; + case 243: memcpy_avx_128(dd - 243, ss - 243); [[fallthrough]]; + case 115: memcpy_avx_64(dd - 115, ss - 115); memcpy_avx_64(dd - 64, ss - 64); break; + case 244: memcpy_avx_128(dd - 244, ss - 244); [[fallthrough]]; + case 116: memcpy_avx_64(dd - 116, ss - 116); memcpy_avx_64(dd - 64, ss - 64); break; + case 245: memcpy_avx_128(dd - 245, ss - 245); [[fallthrough]]; + case 117: memcpy_avx_64(dd - 117, ss - 117); memcpy_avx_64(dd - 64, ss - 64); break; + case 246: memcpy_avx_128(dd - 246, ss - 246); [[fallthrough]]; + case 118: memcpy_avx_64(dd - 118, ss - 118); memcpy_avx_64(dd - 64, ss - 64); break; + case 247: memcpy_avx_128(dd - 247, ss - 247); [[fallthrough]]; + case 119: memcpy_avx_64(dd - 119, ss - 119); memcpy_avx_64(dd - 64, ss - 64); break; + case 248: memcpy_avx_128(dd - 248, ss - 248); [[fallthrough]]; + case 120: memcpy_avx_64(dd - 120, ss - 120); memcpy_avx_64(dd - 64, ss - 64); break; + case 249: memcpy_avx_128(dd - 249, ss - 249); [[fallthrough]]; + case 121: memcpy_avx_64(dd - 121, ss - 121); memcpy_avx_64(dd - 64, ss - 64); break; + case 250: memcpy_avx_128(dd - 250, ss - 250); [[fallthrough]]; + case 122: memcpy_avx_64(dd - 122, ss - 122); memcpy_avx_64(dd - 64, ss - 64); break; + case 251: memcpy_avx_128(dd - 251, ss - 251); [[fallthrough]]; + case 123: memcpy_avx_64(dd - 123, ss - 123); memcpy_avx_64(dd - 64, ss - 64); break; + case 252: memcpy_avx_128(dd - 252, ss - 252); [[fallthrough]]; + case 124: memcpy_avx_64(dd - 124, ss - 124); memcpy_avx_64(dd - 64, ss - 64); break; + case 253: memcpy_avx_128(dd - 253, ss - 253); [[fallthrough]]; + case 125: memcpy_avx_64(dd - 125, ss - 125); memcpy_avx_64(dd - 64, ss - 64); break; + case 254: memcpy_avx_128(dd - 254, ss - 254); [[fallthrough]]; + case 126: memcpy_avx_64(dd - 126, ss - 126); memcpy_avx_64(dd - 64, ss - 64); break; + case 255: memcpy_avx_128(dd - 255, ss - 255); [[fallthrough]]; + case 127: memcpy_avx_64(dd - 127, ss - 127); memcpy_avx_64(dd - 64, ss - 64); break; + case 256: memcpy_avx_256(dd - 256, ss - 256); break; + } + + return dst; +} + + +//--------------------------------------------------------------------- +// main routine +//--------------------------------------------------------------------- +void* memcpy_fast_avx(void * __restrict destination, const void * __restrict source, size_t size) +{ + unsigned char *dst = reinterpret_cast(destination); + const unsigned char *src = reinterpret_cast(source); + static size_t cachesize = 0x200000; // L3-cache size + size_t padding; + + // small memory copy + if (size <= 256) + { + memcpy_tiny_avx(dst, src, size); + _mm256_zeroupper(); + return destination; + } + + // align destination to 16 bytes boundary + padding = (32 - (((size_t)dst) & 31)) & 31; + +#if 0 + if (padding > 0) + { + __m256i head = _mm256_loadu_si256(reinterpret_cast(src)); + _mm256_storeu_si256((__m256i*)dst, head); + dst += padding; + src += padding; + size -= padding; + } +#else + __m256i head = _mm256_loadu_si256(reinterpret_cast(src)); + _mm256_storeu_si256((__m256i*)dst, head); + dst += padding; + src += padding; + size -= padding; +#endif + + // medium size copy + if (size <= cachesize) + { + __m256i c0, c1, c2, c3, c4, c5, c6, c7; + + for (; size >= 256; size -= 256) + { + c0 = _mm256_loadu_si256((reinterpret_cast(src)) + 0); + c1 = _mm256_loadu_si256((reinterpret_cast(src)) + 1); + c2 = _mm256_loadu_si256((reinterpret_cast(src)) + 2); + c3 = _mm256_loadu_si256((reinterpret_cast(src)) + 3); + c4 = _mm256_loadu_si256((reinterpret_cast(src)) + 4); + c5 = _mm256_loadu_si256((reinterpret_cast(src)) + 5); + c6 = _mm256_loadu_si256((reinterpret_cast(src)) + 6); + c7 = _mm256_loadu_si256((reinterpret_cast(src)) + 7); + src += 256; + _mm256_storeu_si256(((reinterpret_cast<__m256i*>(dst)) + 0), c0); + _mm256_storeu_si256(((reinterpret_cast<__m256i*>(dst)) + 1), c1); + _mm256_storeu_si256(((reinterpret_cast<__m256i*>(dst)) + 2), c2); + _mm256_storeu_si256(((reinterpret_cast<__m256i*>(dst)) + 3), c3); + _mm256_storeu_si256(((reinterpret_cast<__m256i*>(dst)) + 4), c4); + _mm256_storeu_si256(((reinterpret_cast<__m256i*>(dst)) + 5), c5); + _mm256_storeu_si256(((reinterpret_cast<__m256i*>(dst)) + 6), c6); + _mm256_storeu_si256(((reinterpret_cast<__m256i*>(dst)) + 7), c7); + dst += 256; + } + } + else + { // big memory copy + __m256i c0, c1, c2, c3, c4, c5, c6, c7; + /* __m256i c0, c1, c2, c3, c4, c5, c6, c7; */ + + if ((((size_t)src) & 31) == 0) + { // source aligned + for (; size >= 256; size -= 256) + { + c0 = _mm256_load_si256((reinterpret_cast(src)) + 0); + c1 = _mm256_load_si256((reinterpret_cast(src)) + 1); + c2 = _mm256_load_si256((reinterpret_cast(src)) + 2); + c3 = _mm256_load_si256((reinterpret_cast(src)) + 3); + c4 = _mm256_load_si256((reinterpret_cast(src)) + 4); + c5 = _mm256_load_si256((reinterpret_cast(src)) + 5); + c6 = _mm256_load_si256((reinterpret_cast(src)) + 6); + c7 = _mm256_load_si256((reinterpret_cast(src)) + 7); + src += 256; + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 0), c0); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 1), c1); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 2), c2); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 3), c3); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 4), c4); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 5), c5); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 6), c6); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 7), c7); + dst += 256; + } + } + else + { // source unaligned + for (; size >= 256; size -= 256) + { + c0 = _mm256_loadu_si256((reinterpret_cast(src)) + 0); + c1 = _mm256_loadu_si256((reinterpret_cast(src)) + 1); + c2 = _mm256_loadu_si256((reinterpret_cast(src)) + 2); + c3 = _mm256_loadu_si256((reinterpret_cast(src)) + 3); + c4 = _mm256_loadu_si256((reinterpret_cast(src)) + 4); + c5 = _mm256_loadu_si256((reinterpret_cast(src)) + 5); + c6 = _mm256_loadu_si256((reinterpret_cast(src)) + 6); + c7 = _mm256_loadu_si256((reinterpret_cast(src)) + 7); + src += 256; + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 0), c0); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 1), c1); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 2), c2); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 3), c3); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 4), c4); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 5), c5); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 6), c6); + _mm256_stream_si256(((reinterpret_cast<__m256i*>(dst)) + 7), c7); + dst += 256; + } + } + _mm_sfence(); + } + + memcpy_tiny_avx(dst, src, size); + _mm256_zeroupper(); + + return destination; +} diff --git a/utils/memcpy-bench/memcpy-bench.cpp b/utils/memcpy-bench/memcpy-bench.cpp new file mode 100644 index 00000000000..2df72cb5ccb --- /dev/null +++ b/utils/memcpy-bench/memcpy-bench.cpp @@ -0,0 +1,620 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wcast-align" +#pragma GCC diagnostic ignored "-Wcast-qual" +#include "FastMemcpy.h" +//#include "FastMemcpy_Avx.h" + +#include +#include + + +template +void NO_INLINE loop(uint8_t * dst, uint8_t * src, size_t size, F && chunk_size_distribution, MemcpyImpl && impl) +{ + while (size) + { + size_t bytes_to_copy = std::min(size, chunk_size_distribution()); + + impl(dst, src, bytes_to_copy); + + dst += bytes_to_copy; + src += bytes_to_copy; + size -= bytes_to_copy; + } +} + + +using RNG = pcg32_fast; + +template +size_t generatorUniform(RNG & rng) { return rng() % N; }; + + +template +void test(uint8_t * dst, uint8_t * src, size_t size, size_t iterations, size_t num_threads, F && generator, MemcpyImpl && impl) +{ + Stopwatch watch; + + std::vector threads; + threads.reserve(num_threads); + + for (size_t thread_num = 0; thread_num < num_threads; ++thread_num) + { + size_t begin = size * thread_num / num_threads; + size_t end = size * (thread_num + 1) / num_threads; + + threads.emplace_back([begin, end, iterations, &src, &dst, &generator, &impl] + { + for (size_t iteration = 0; iteration < iterations; ++iteration) + { + loop( + iteration % 2 ? &src[begin] : &dst[begin], + iteration % 2 ? &dst[begin] : &src[begin], + end - begin, + [rng = RNG(), &generator]() mutable { return generator(rng); }, + std::forward(impl)); + } + }); + } + + for (auto & thread : threads) + thread.join(); + + double elapsed_ns = watch.elapsed(); + + /// Validation + size_t sum = 0; + for (size_t i = 0; i < size; ++i) + sum += dst[i]; + + std::cerr << std::fixed << std::setprecision(3) + << "Processed in " << (elapsed_ns / 1e9) << "sec, " << (size * iterations * 1.0 / elapsed_ns) << " GB/sec (sum = " << sum << ")\n"; +} + + +using memcpy_type = void * (*)(const void * __restrict, void * __restrict, size_t); + + +static void * memcpy_erms(void * dst, const void * src, size_t size) +{ + asm volatile ( + "rep movsb" + : "=D"(dst), "=S"(src), "=c"(size) + : "0"(dst), "1"(src), "2"(size) + : "memory"); + return dst; +} + +extern "C" void * memcpy_jart(void * dst, const void * src, size_t size); +extern "C" void MemCpy(void * dst, const void * src, size_t size); + + +static void * memcpySSE2(void * __restrict destination, const void * __restrict source, size_t size) +{ + unsigned char *dst = reinterpret_cast(destination); + const unsigned char *src = reinterpret_cast(source); + size_t padding; + + // small memory copy + if (size <= 16) + return memcpy_tiny(dst, src, size); + + // align destination to 16 bytes boundary + padding = (16 - (reinterpret_cast(dst) & 15)) & 15; + + if (padding > 0) + { + __m128i head = _mm_loadu_si128(reinterpret_cast(src)); + _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), head); + dst += padding; + src += padding; + size -= padding; + } + + // medium size copy + __m128i c0; + + for (; size >= 16; size -= 16) + { + c0 = _mm_loadu_si128(reinterpret_cast(src)); + src += 16; + _mm_store_si128((reinterpret_cast<__m128i*>(dst)), c0); + dst += 16; + } + + memcpy_tiny(dst, src, size); + return destination; +} + +static void * memcpySSE2Unrolled2(void * __restrict destination, const void * __restrict source, size_t size) +{ + unsigned char *dst = reinterpret_cast(destination); + const unsigned char *src = reinterpret_cast(source); + size_t padding; + + // small memory copy + if (size <= 32) + return memcpy_tiny(dst, src, size); + + // align destination to 16 bytes boundary + padding = (16 - (reinterpret_cast(dst) & 15)) & 15; + + if (padding > 0) + { + __m128i head = _mm_loadu_si128(reinterpret_cast(src)); + _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), head); + dst += padding; + src += padding; + size -= padding; + } + + // medium size copy + __m128i c0, c1; + + for (; size >= 32; size -= 32) + { + c0 = _mm_loadu_si128(reinterpret_cast(src) + 0); + c1 = _mm_loadu_si128(reinterpret_cast(src) + 1); + src += 32; + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 0), c0); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 1), c1); + dst += 32; + } + + memcpy_tiny(dst, src, size); + return destination; +} + +static void * memcpySSE2Unrolled4(void * __restrict destination, const void * __restrict source, size_t size) +{ + unsigned char *dst = reinterpret_cast(destination); + const unsigned char *src = reinterpret_cast(source); + size_t padding; + + // small memory copy + if (size <= 64) + return memcpy_tiny(dst, src, size); + + // align destination to 16 bytes boundary + padding = (16 - (reinterpret_cast(dst) & 15)) & 15; + + if (padding > 0) + { + __m128i head = _mm_loadu_si128(reinterpret_cast(src)); + _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), head); + dst += padding; + src += padding; + size -= padding; + } + + // medium size copy + __m128i c0, c1, c2, c3; + + for (; size >= 64; size -= 64) + { + c0 = _mm_loadu_si128(reinterpret_cast(src) + 0); + c1 = _mm_loadu_si128(reinterpret_cast(src) + 1); + c2 = _mm_loadu_si128(reinterpret_cast(src) + 2); + c3 = _mm_loadu_si128(reinterpret_cast(src) + 3); + src += 64; + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 0), c0); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 1), c1); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 2), c2); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 3), c3); + dst += 64; + } + + memcpy_tiny(dst, src, size); + return destination; +} + + +static void * memcpySSE2Unrolled8(void * __restrict destination, const void * __restrict source, size_t size) +{ + unsigned char *dst = reinterpret_cast(destination); + const unsigned char *src = reinterpret_cast(source); + size_t padding; + + // small memory copy + if (size <= 128) + return memcpy_tiny(dst, src, size); + + // align destination to 16 bytes boundary + padding = (16 - (reinterpret_cast(dst) & 15)) & 15; + + if (padding > 0) + { + __m128i head = _mm_loadu_si128(reinterpret_cast(src)); + _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), head); + dst += padding; + src += padding; + size -= padding; + } + + // medium size copy + __m128i c0, c1, c2, c3, c4, c5, c6, c7; + + for (; size >= 128; size -= 128) + { + c0 = _mm_loadu_si128(reinterpret_cast(src) + 0); + c1 = _mm_loadu_si128(reinterpret_cast(src) + 1); + c2 = _mm_loadu_si128(reinterpret_cast(src) + 2); + c3 = _mm_loadu_si128(reinterpret_cast(src) + 3); + c4 = _mm_loadu_si128(reinterpret_cast(src) + 4); + c5 = _mm_loadu_si128(reinterpret_cast(src) + 5); + c6 = _mm_loadu_si128(reinterpret_cast(src) + 6); + c7 = _mm_loadu_si128(reinterpret_cast(src) + 7); + src += 128; + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 0), c0); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 1), c1); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 2), c2); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 3), c3); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 4), c4); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 5), c5); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 6), c6); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 7), c7); + dst += 128; + } + + memcpy_tiny(dst, src, size); + return destination; +} + + +//static __attribute__((__always_inline__, __target__("sse2"))) +__attribute__((__always_inline__)) +void memcpy_my_medium_sse(uint8_t * __restrict & dst, const uint8_t * __restrict & src, size_t & size) +{ + /// Align destination to 16 bytes boundary. + size_t padding = (16 - (reinterpret_cast(dst) & 15)) & 15; + + if (padding > 0) + { + __m128i head = _mm_loadu_si128(reinterpret_cast(src)); + _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), head); + dst += padding; + src += padding; + size -= padding; + } + + /// Aligned unrolled copy. + __m128i c0, c1, c2, c3, c4, c5, c6, c7; + + while (size >= 128) + { + c0 = _mm_loadu_si128(reinterpret_cast(src) + 0); + c1 = _mm_loadu_si128(reinterpret_cast(src) + 1); + c2 = _mm_loadu_si128(reinterpret_cast(src) + 2); + c3 = _mm_loadu_si128(reinterpret_cast(src) + 3); + c4 = _mm_loadu_si128(reinterpret_cast(src) + 4); + c5 = _mm_loadu_si128(reinterpret_cast(src) + 5); + c6 = _mm_loadu_si128(reinterpret_cast(src) + 6); + c7 = _mm_loadu_si128(reinterpret_cast(src) + 7); + src += 128; + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 0), c0); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 1), c1); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 2), c2); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 3), c3); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 4), c4); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 5), c5); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 6), c6); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 7), c7); + dst += 128; + + size -= 128; + } +} + +__attribute__((__target__("avx"))) +void memcpy_my_medium_avx(uint8_t * __restrict & __restrict dst, const uint8_t * __restrict & __restrict src, size_t & __restrict size) +{ + size_t padding = (32 - (reinterpret_cast(dst) & 31)) & 31; + + if (padding > 0) + { + __m256i head = _mm256_loadu_si256(reinterpret_cast(src)); + _mm256_storeu_si256((__m256i*)dst, head); + dst += padding; + src += padding; + size -= padding; + } + + __m256i c0, c1, c2, c3, c4, c5, c6, c7; + + while (size >= 256) + { + c0 = _mm256_loadu_si256((reinterpret_cast(src)) + 0); + c1 = _mm256_loadu_si256((reinterpret_cast(src)) + 1); + c2 = _mm256_loadu_si256((reinterpret_cast(src)) + 2); + c3 = _mm256_loadu_si256((reinterpret_cast(src)) + 3); + c4 = _mm256_loadu_si256((reinterpret_cast(src)) + 4); + c5 = _mm256_loadu_si256((reinterpret_cast(src)) + 5); + c6 = _mm256_loadu_si256((reinterpret_cast(src)) + 6); + c7 = _mm256_loadu_si256((reinterpret_cast(src)) + 7); + src += 256; + _mm256_store_si256(((reinterpret_cast<__m256i*>(dst)) + 0), c0); + _mm256_store_si256(((reinterpret_cast<__m256i*>(dst)) + 1), c1); + _mm256_store_si256(((reinterpret_cast<__m256i*>(dst)) + 2), c2); + _mm256_store_si256(((reinterpret_cast<__m256i*>(dst)) + 3), c3); + _mm256_store_si256(((reinterpret_cast<__m256i*>(dst)) + 4), c4); + _mm256_store_si256(((reinterpret_cast<__m256i*>(dst)) + 5), c5); + _mm256_store_si256(((reinterpret_cast<__m256i*>(dst)) + 6), c6); + _mm256_store_si256(((reinterpret_cast<__m256i*>(dst)) + 7), c7); + dst += 256; + + size -= 256; + } +} + +bool have_avx = true; + +static uint8_t * memcpy_my(uint8_t * __restrict dst, const uint8_t * __restrict src, size_t size) +{ + uint8_t * ret = dst; + +tail: + if (size <= 16) + { + if (size >= 8) + { + __builtin_memcpy(dst + size - 8, src + size - 8, 8); + __builtin_memcpy(dst, src, 8); + } + else if (size >= 4) + { + __builtin_memcpy(dst + size - 4, src + size - 4, 4); + __builtin_memcpy(dst, src, 4); + } + else if (size >= 2) + { + __builtin_memcpy(dst + size - 2, src + size - 2, 2); + __builtin_memcpy(dst, src, 2); + } + else if (size >= 1) + { + *dst = *src; + } + } + else if (have_avx) + { + if (size <= 32) + { + __builtin_memcpy(dst, src, 8); + __builtin_memcpy(dst + 8, src + 8, 8); + + dst += 16; + src += 16; + size -= 16; + + goto tail; + } + + if (size <= 256) + { + __asm__( + "vmovups -0x20(%[s],%[size],1), %%ymm0\n" + "vmovups %%ymm0, -0x20(%[d],%[size],1)\n" + : [d]"+r"(dst), [s]"+r"(src) + : [size]"r"(size) + : "ymm0", "memory"); + + while (size > 32) + { + __asm__( + "vmovups (%[s]), %%ymm0\n" + "vmovups %%ymm0, (%[d])\n" + : [d]"+r"(dst), [s]"+r"(src) + : + : "ymm0", "memory"); + + dst += 32; + src += 32; + size -= 32; + } + } + else + { + size_t padding = (32 - (reinterpret_cast(dst) & 31)) & 31; + + if (padding > 0) + { + __asm__( + "vmovups (%[s]), %%ymm0\n" + "vmovups %%ymm0, (%[d])\n" + : [d]"+r"(dst), [s]"+r"(src) + : + : "ymm0", "memory"); + + dst += padding; + src += padding; + size -= padding; + } + + while (size >= 256) + { + __asm__( + "vmovups (%[s]), %%ymm0\n" + "vmovups 0x20(%[s]), %%ymm1\n" + "vmovups 0x40(%[s]), %%ymm2\n" + "vmovups 0x60(%[s]), %%ymm3\n" + "vmovups 0x80(%[s]), %%ymm4\n" + "vmovups 0xa0(%[s]), %%ymm5\n" + "vmovups 0xc0(%[s]), %%ymm6\n" + "vmovups 0xe0(%[s]), %%ymm7\n" + "add $0x100,%[s]\n" + "vmovaps %%ymm0, (%[d])\n" + "vmovaps %%ymm1, 0x20(%[d])\n" + "vmovaps %%ymm2, 0x40(%[d])\n" + "vmovaps %%ymm3, 0x60(%[d])\n" + "vmovaps %%ymm4, 0x80(%[d])\n" + "vmovaps %%ymm5, 0xa0(%[d])\n" + "vmovaps %%ymm6, 0xc0(%[d])\n" + "vmovaps %%ymm7, 0xe0(%[d])\n" + "add $0x100, %[d]\n" + : [d]"+r"(dst), [s]"+r"(src) + : + : "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "memory"); + + size -= 256; + } + + goto tail; + } + } + else + { + if (size <= 128) + { + _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + size - 16), _mm_loadu_si128(reinterpret_cast(src + size - 16))); + + while (size > 16) + { + _mm_storeu_si128(reinterpret_cast<__m128i *>(dst), _mm_loadu_si128(reinterpret_cast(src))); + dst += 16; + src += 16; + size -= 16; + } + } + else + { + /// Align destination to 16 bytes boundary. + size_t padding = (16 - (reinterpret_cast(dst) & 15)) & 15; + + if (padding > 0) + { + __m128i head = _mm_loadu_si128(reinterpret_cast(src)); + _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), head); + dst += padding; + src += padding; + size -= padding; + } + + /// Aligned unrolled copy. + __m128i c0, c1, c2, c3, c4, c5, c6, c7; + + while (size >= 128) + { + c0 = _mm_loadu_si128(reinterpret_cast(src) + 0); + c1 = _mm_loadu_si128(reinterpret_cast(src) + 1); + c2 = _mm_loadu_si128(reinterpret_cast(src) + 2); + c3 = _mm_loadu_si128(reinterpret_cast(src) + 3); + c4 = _mm_loadu_si128(reinterpret_cast(src) + 4); + c5 = _mm_loadu_si128(reinterpret_cast(src) + 5); + c6 = _mm_loadu_si128(reinterpret_cast(src) + 6); + c7 = _mm_loadu_si128(reinterpret_cast(src) + 7); + src += 128; + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 0), c0); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 1), c1); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 2), c2); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 3), c3); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 4), c4); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 5), c5); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 6), c6); + _mm_store_si128((reinterpret_cast<__m128i*>(dst) + 7), c7); + dst += 128; + + size -= 128; + } + + goto tail; + } + } + + return ret; +} + + +template +void dispatchMemcpyVariants(size_t memcpy_variant, uint8_t * dst, uint8_t * src, size_t size, size_t iterations, size_t num_threads, F && generator) +{ + memcpy_type memcpy_libc = reinterpret_cast(dlsym(RTLD_NEXT, "memcpy")); + + if (memcpy_variant == 1) + test(dst, src, size, iterations, num_threads, std::forward(generator), memcpy); + if (memcpy_variant == 2) + test(dst, src, size, iterations, num_threads, std::forward(generator), memcpy_libc); + if (memcpy_variant == 3) + test(dst, src, size, iterations, num_threads, std::forward(generator), memcpy_erms); + if (memcpy_variant == 4) + test(dst, src, size, iterations, num_threads, std::forward(generator), MemCpy); + if (memcpy_variant == 5) + test(dst, src, size, iterations, num_threads, std::forward(generator), memcpySSE2); + if (memcpy_variant == 6) + test(dst, src, size, iterations, num_threads, std::forward(generator), memcpySSE2Unrolled2); + if (memcpy_variant == 7) + test(dst, src, size, iterations, num_threads, std::forward(generator), memcpySSE2Unrolled4); + if (memcpy_variant == 8) + test(dst, src, size, iterations, num_threads, std::forward(generator), memcpySSE2Unrolled8); +// if (memcpy_variant == 9) +// test(dst, src, size, iterations, num_threads, std::forward(generator), memcpy_fast_avx); + if (memcpy_variant == 10) + test(dst, src, size, iterations, num_threads, std::forward(generator), memcpy_my); +} + +void dispatchVariants(size_t memcpy_variant, size_t generator_variant, uint8_t * dst, uint8_t * src, size_t size, size_t iterations, size_t num_threads) +{ + if (generator_variant == 1) + dispatchMemcpyVariants(memcpy_variant, dst, src, size, iterations, num_threads, generatorUniform<16>); + if (generator_variant == 2) + dispatchMemcpyVariants(memcpy_variant, dst, src, size, iterations, num_threads, generatorUniform<256>); + if (generator_variant == 3) + dispatchMemcpyVariants(memcpy_variant, dst, src, size, iterations, num_threads, generatorUniform<4096>); + if (generator_variant == 4) + dispatchMemcpyVariants(memcpy_variant, dst, src, size, iterations, num_threads, generatorUniform<65536>); + if (generator_variant == 5) + dispatchMemcpyVariants(memcpy_variant, dst, src, size, iterations, num_threads, generatorUniform<1048576>); +} + + +int main(int argc, char ** argv) +{ + size_t size = 1000000000; + if (argc >= 2) + size = std::stoull(argv[1]); + + size_t iterations = 10; + if (argc >= 3) + iterations = std::stoull(argv[2]); + + size_t num_threads = 1; + if (argc >= 4) + num_threads = std::stoull(argv[3]); + + size_t memcpy_variant = 1; + if (argc >= 5) + memcpy_variant = std::stoull(argv[4]); + + size_t generator_variant = 1; + if (argc >= 6) + generator_variant = std::stoull(argv[5]); + + std::unique_ptr src(new uint8_t[size]); + std::unique_ptr dst(new uint8_t[size]); + + /// Fill src with some pattern for validation. + for (size_t i = 0; i < size; ++i) + src[i] = i; + + /// Fill dst to avoid page faults. + memset(dst.get(), 0, size); + + dispatchVariants(memcpy_variant, generator_variant, dst.get(), src.get(), size, iterations, num_threads); + + return 0; +} diff --git a/utils/memcpy-bench/memcpy_jart.S b/utils/memcpy-bench/memcpy_jart.S new file mode 100644 index 00000000000..50430d0abe0 --- /dev/null +++ b/utils/memcpy-bench/memcpy_jart.S @@ -0,0 +1,138 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ + +// Copies memory. +// +// DEST and SRC must not overlap, unless DEST≤SRC. +// +// @param rdi is dest +// @param rsi is src +// @param rdx is number of bytes +// @return original rdi copied to rax +// @mode long +// @asyncsignalsafe +memcpy_jart: mov %rdi,%rax +// 𝑠𝑙𝑖𝑑𝑒 + .align 16 + .type memcpy_jart,@function + .size memcpy_jart,.-memcpy_jart + .globl memcpy_jart + +// Copies memory w/ minimal impact ABI. +// +// @param rdi is dest +// @param rsi is src +// @param rdx is number of bytes +// @clob flags,rcx,xmm3,xmm4 +// @mode long +MemCpy: mov $.Lmemcpytab.size,%ecx + cmp %rcx,%rdx + cmovb %rdx,%rcx + jmp *memcpytab(,%rcx,8) +.Lanchorpoint: +.L16r: cmp $1024,%rdx + jae .Lerms +.L16: movdqu -16(%rsi,%rdx),%xmm4 + mov $16,%rcx +0: add $16,%rcx + movdqu -32(%rsi,%rcx),%xmm3 + movdqu %xmm3,-32(%rdi,%rcx) + cmp %rcx,%rdx + ja 0b + movdqu %xmm4,-16(%rdi,%rdx) + pxor %xmm4,%xmm4 + pxor %xmm3,%xmm3 + jmp .L0 +.L8: push %rbx + mov (%rsi),%rcx + mov -8(%rsi,%rdx),%rbx + mov %rcx,(%rdi) + mov %rbx,-8(%rdi,%rdx) +1: pop %rbx +.L0: ret +.L4: push %rbx + mov (%rsi),%ecx + mov -4(%rsi,%rdx),%ebx + mov %ecx,(%rdi) + mov %ebx,-4(%rdi,%rdx) + jmp 1b +.L3: push %rbx + mov (%rsi),%cx + mov -2(%rsi,%rdx),%bx + mov %cx,(%rdi) + mov %bx,-2(%rdi,%rdx) + jmp 1b +.L2: mov (%rsi),%cx + mov %cx,(%rdi) + jmp .L0 +.L1: mov (%rsi),%cl + mov %cl,(%rdi) + jmp .L0 +.Lerms: cmp $1024*1024,%rdx + ja .Lnts + push %rdi + push %rsi + mov %rdx,%rcx + rep movsb + pop %rsi + pop %rdi + jmp .L0 +.Lnts: movdqu (%rsi),%xmm3 + movdqu %xmm3,(%rdi) + lea 16(%rdi),%rcx + and $-16,%rcx + sub %rdi,%rcx + add %rcx,%rdi + add %rcx,%rsi + sub %rcx,%rdx + mov $16,%rcx +0: add $16,%rcx + movdqu -32(%rsi,%rcx),%xmm3 + movntdq %xmm3,-32(%rdi,%rcx) + cmp %rcx,%rdx + ja 0b + sfence + movdqu -16(%rsi,%rdx),%xmm3 + movdqu %xmm3,-16(%rdi,%rdx) + pxor %xmm3,%xmm3 + jmp .L0 + .type MemCpy,@function + .size MemCpy,.-MemCpy + .globl MemCpy + + .section .rodata + .align 8 +memcpytab: + .quad .L0 + .quad .L1 + .quad .L2 + .quad .L3 + .rept 4 + .quad .L4 + .endr + .rept 8 + .quad .L8 + .endr + .rept 16 + .quad .L16 + .endr + .equ .Lmemcpytab.size,(.-memcpytab)/8 + .quad .L16r # SSE + ERMS + NTS + .type memcpytab,@object + .previous diff --git a/utils/simple-backport/changelog.sh b/utils/simple-backport/changelog.sh index d3d9714cb04..ca2dcfffff0 100755 --- a/utils/simple-backport/changelog.sh +++ b/utils/simple-backport/changelog.sh @@ -39,7 +39,7 @@ function github_download() local file=${2} if ! [ -f "$file" ] then - if ! curl -H "Authorization: token $GITHUB_TOKEN" \ + if ! curl -u "$GITHUB_USER:$GITHUB_TOKEN" \ -sSf "$url" \ > "$file" then diff --git a/utils/test-data-generator/CMakeLists.txt b/utils/test-data-generator/CMakeLists.txt deleted file mode 100644 index 80d7d4301e7..00000000000 --- a/utils/test-data-generator/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Disable clang-tidy for protobuf generated files -set (CMAKE_CXX_CLANG_TIDY "") - -if (USE_PROTOBUF) - protobuf_generate_cpp(ProtobufDelimitedMessagesSerializer_Srcs ProtobufDelimitedMessagesSerializer_Hdrs ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/queries/0_stateless/00825_protobuf_format.proto) - protobuf_generate_cpp(ProtobufDelimitedMessagesSerializer_Srcs2 ProtobufDelimitedMessagesSerializer_Hdrs2 ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/queries/0_stateless/00825_protobuf_format_syntax2.proto) - add_executable (ProtobufDelimitedMessagesSerializer ProtobufDelimitedMessagesSerializer.cpp ${ProtobufDelimitedMessagesSerializer_Srcs} ${ProtobufDelimitedMessagesSerializer_Hdrs} ${ProtobufDelimitedMessagesSerializer_Srcs2} ${ProtobufDelimitedMessagesSerializer_Hdrs2}) - target_include_directories (ProtobufDelimitedMessagesSerializer SYSTEM BEFORE PRIVATE ${Protobuf_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) - target_link_libraries (ProtobufDelimitedMessagesSerializer PRIVATE ${Protobuf_LIBRARY} boost::program_options) - get_filename_component(ProtobufDelimitedMessagesSerializer_OutputDir "${CMAKE_CURRENT_LIST_DIR}/../../tests/queries/0_stateless" REALPATH) - target_compile_definitions(ProtobufDelimitedMessagesSerializer PRIVATE OUTPUT_DIR="${ProtobufDelimitedMessagesSerializer_OutputDir}") - - # Protoc generates substandard code. - check_cxx_compiler_flag("-Wsuggest-destructor-override" HAS_SUGGEST_DESTRUCTOR_OVERRIDE) - if (HAS_SUGGEST_OVERRIDE) - target_compile_options(ProtobufDelimitedMessagesSerializer PRIVATE -Wno-suggest-destructor-override) - endif() -endif () diff --git a/utils/test-data-generator/ProtobufDelimitedMessagesSerializer.cpp b/utils/test-data-generator/ProtobufDelimitedMessagesSerializer.cpp deleted file mode 100644 index ad465913313..00000000000 --- a/utils/test-data-generator/ProtobufDelimitedMessagesSerializer.cpp +++ /dev/null @@ -1,728 +0,0 @@ -// Generator of protobuf delimited messages used in the protobuf IO tests -// tests/queries/0_stateless/00825_protobuf_format* - -#include -#include -#include -#include -#include "00825_protobuf_format.pb.h" -#include "00825_protobuf_format_syntax2.pb.h" - - -void writeInsertDataQueryForInputTest(std::stringstream & delimited_messages, const std::string & table_name, const std::string & format_schema, std::ostream & out) // STYLE_CHECK_ALLOW_STD_STRING_STREAM -{ - out << "echo -ne '"; - std::string bytes = delimited_messages.str(); - delimited_messages.str(""); - for (const char c : bytes) - { - char buf[5]; - sprintf(buf, "\\x%02x", static_cast(c)); - out << buf; - } - out << "' | $CLICKHOUSE_CLIENT --query=\"INSERT INTO " << table_name << " FORMAT Protobuf" - " SETTINGS format_schema = '$CURDIR/" - << format_schema << "'\"" << std::endl; -} - -void writeInsertDataQueriesForInputTest(std::ostream & out) -{ - std::stringstream ss; // STYLE_CHECK_ALLOW_STD_STRING_STREAM - { - Person person; - person.set_uuid("a7522158-3d41-4b77-ad69-6c598ee55c49"); - person.set_name("Ivan"); - person.set_surname("Petrov"); - person.set_gender(Gender::male); - person.set_birthdate(4015); // 1980-12-29 - person.set_photo("png"); - person.set_phonenumber("+74951234567"); - person.set_isonline(true); - person.set_visittime(1546703100); // 2019-01-05 18:45:00 - person.set_age(38); - person.set_zodiacsign(ZodiacSign::capricorn); - person.add_songs("Yesterday"); - person.add_songs("Flowers"); - person.add_color(255); - person.add_color(0); - person.add_color(0); - person.set_hometown("Moscow"); - person.add_location(55.753215); - person.add_location(37.622504); - person.set_pi(3.14); - person.set_lotterywin(214.10); - person.set_someratio(0.1); - person.set_temperature(5.8); - person.set_randombignumber(17060000000); - auto* mu = person.add_measureunits(); - mu->set_unit("meter"); - mu->set_coef(1); - mu = person.add_measureunits(); - mu->set_unit("centimeter"); - mu->set_coef(0.01); - mu = person.add_measureunits(); - mu->set_unit("kilometer"); - mu->set_coef(1000); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->set_d(500); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->add_e(501); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->add_e(502); - google::protobuf::util::SerializeDelimitedToOstream(person, &ss); - } - - { - Person person; - person.set_uuid("c694ad8a-f714-4ea3-907d-fd54fb25d9b5"); - person.set_name("Natalia"); - person.set_surname("Sokolova"); - person.set_gender(Gender::female); - person.set_birthdate(8102); // 1992-03-08 - person.set_photo("jpg"); - person.set_isonline(false); - person.set_age(26); - person.set_zodiacsign(ZodiacSign::pisces); - person.add_color(100); - person.add_color(200); - person.add_color(50); - person.set_hometown("Plymouth"); - person.add_location(50.403724); - person.add_location(-4.142123); - person.set_pi(3.14159); - person.set_someratio(0.007); - person.set_temperature(5.4); - person.set_randombignumber(-20000000000000); - google::protobuf::util::SerializeDelimitedToOstream(person, &ss); - } - - { - Person person; - person.set_uuid("a7da1aa6-f425-4789-8947-b034786ed374"); - person.set_name("Vasily"); - person.set_surname("Sidorov"); - person.set_gender(Gender::male); - person.set_birthdate(9339); // 1995-07-28 - person.set_photo("bmp"); - person.set_phonenumber("+442012345678"); - person.set_isonline(true); - person.set_visittime(1546117200); // 2018-12-30 00:00:00 - person.set_age(23); - person.set_zodiacsign(ZodiacSign::leo); - person.add_songs("Sunny"); - person.add_color(250); - person.add_color(244); - person.add_color(10); - person.set_hometown("Murmansk"); - person.add_location(68.970682); - person.add_location(33.074981); - person.set_pi(3.14159265358979); - person.set_lotterywin(100000000000); - person.set_someratio(800); - person.set_temperature(-3.2); - person.set_randombignumber(154400000); - auto* mu = person.add_measureunits(); - mu->set_unit("pound"); - mu->set_coef(16); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->set_d(503); - google::protobuf::util::SerializeDelimitedToOstream(person, &ss); - } - - writeInsertDataQueryForInputTest(ss, "in_persons_00825", "00825_protobuf_format:Person", out); - - { - AltPerson person; - person.add_location(42); - person.add_location(-88); - person.set_pi(3.141); - person.set_uuid("20fcd95a-332d-41db-a9ec-161f644d059c"); - person.set_name("Frida"); - person.set_gender(AltPerson::female); - person.set_zodiacsign(1122); // sagittarius - person.set_birthdate(3267); // 1978-12-12 - person.set_age("40"); - person.set_isonline(OnlineStatus::offline); - person.set_someratio(0.5); - person.set_visittime(1363005000); // 2013-03-11 16:30:00 - person.set_randombignumber(8010000009); - person.add_color(110); - person.add_color(210); - person.add_color(74); - person.set_lotterywin(311); - person.set_surname("Ermakova"); - person.set_phonenumber(3124555929); - person.set_temperature(10); - person.add_measureunits_unit("KB"); - person.add_measureunits_coef(1024); - person.add_measureunits_unit("MB"); - person.add_measureunits_coef(1048576); - person.set_nestiness_a_b_c_d(700); - person.add_nestiness_a_b_c_e(701); - google::protobuf::util::SerializeDelimitedToOstream(person, &ss); - } - - { - AltPerson person; - person.add_location(26); - person.add_location(-80); - person.set_pi(3.1416); - person.set_uuid("7cfa6856-a54a-4786-b8e5-745159d52278"); - person.set_name("Isolde"); - person.set_gender(AltPerson::female); - person.set_zodiacsign(120); // aquarius - person.set_birthdate(6248); // 1987-02-09 - person.set_age("32"); - person.set_isonline(OnlineStatus::online); - person.set_someratio(4.5); - person.set_randombignumber(-11111111111111); - person.add_color(255); - person.add_color(0); - person.add_color(255); - person.set_surname("Lavrova"); - person.set_temperature(25); - person.set_newfieldstr("abc"); - person.set_newfieldbool(true); - person.add_newfieldint(44); - person.add_measureunits_unit("Byte"); - person.add_measureunits_coef(8); - person.add_measureunits_unit("Bit"); - person.add_measureunits_coef(1); - person.mutable_newmessage()->set_z(91); - person.set_nestiness_a_b_c_d(702); - google::protobuf::util::SerializeDelimitedToOstream(person, &ss); - } - - writeInsertDataQueryForInputTest(ss, "in_persons_00825", "00825_protobuf_format:AltPerson", out); - - { - StrPerson person; - person.set_uuid("aa0e5a06-cab2-4034-a6a2-48e82b91664e"); - person.set_name("Leonid"); - person.set_surname("Kirillov"); - person.set_gender("male"); - person.set_birthdate("1983-06-24"); - person.set_phonenumber("+74950275864"); - person.set_isonline("1"); - person.set_visittime("2019-02-04 09:45:00"); - person.set_age("35"); - person.set_zodiacsign("cancer"); - person.add_songs("7 rings"); - person.add_songs("Eastside"); - person.add_songs("Last Hurrah"); - person.add_color("0"); - person.add_color("0"); - person.add_color("255"); - person.set_hometown("San Diego"); - person.add_location("32.823943"); - person.add_location("-117.081327"); - person.set_pi("3.1415927"); - person.set_lotterywin("15000000"); - person.set_someratio("186.75"); - person.set_temperature("-2.1"); - person.set_randombignumber("20659829331"); - person.mutable_measureunits()->add_unit("minute"); - person.mutable_measureunits()->add_coef("60"); - person.mutable_measureunits()->add_unit("hour"); - person.mutable_measureunits()->add_coef("3600"); - person.mutable_nestiness_a()->mutable_b_c()->add_e("1800"); - google::protobuf::util::SerializeDelimitedToOstream(person, &ss); - } - - writeInsertDataQueryForInputTest(ss, "in_persons_00825", "00825_protobuf_format:StrPerson", out); - - { - Syntax2Person person; - person.set_uuid("3faee064-c4f7-4d34-b6f3-8d81c2b6a15d"); - person.set_name("Nick"); - person.set_surname("Kolesnikov"); - person.set_gender(Syntax2Person::male); - person.set_birthdate(10586); // 1998-12-26 - person.set_photo("bmp"); - person.set_phonenumber("412-687-5007"); - person.set_isonline(true); - person.set_visittime(1542596399); // 2018-11-19 05:59:59 - person.set_age(20); - person.set_zodiacsign(Syntax2Person::capricorn); - person.add_songs("Havana"); - person.add_color(128); - person.add_color(0); - person.add_color(128); - person.set_hometown("Pittsburgh"); - person.add_location(40.517193); - person.add_location(-79.949452); - person.set_pi(3.1415926535898); - person.set_lotterywin(50000000000); - person.set_someratio(780); - person.set_temperature(18.3); - person.set_randombignumber(195500007); - person.mutable_measureunits()->add_unit("ounce"); - person.mutable_measureunits()->add_coef(28.35); - person.mutable_measureunits()->add_unit("carat"); - person.mutable_measureunits()->add_coef(0.2); - person.mutable_measureunits()->add_unit("gram"); - person.mutable_measureunits()->add_coef(1); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->set_d(9494); - google::protobuf::util::SerializeDelimitedToOstream(person, &ss); - } - - writeInsertDataQueryForInputTest(ss, "in_persons_00825", "00825_protobuf_format_syntax2:Syntax2Person", out); - - { - NumberAndSquare ns; - ns.set_number(2); - ns.set_square(4); - google::protobuf::util::SerializeDelimitedToOstream(ns, &ss); - } - - { - NumberAndSquare ns; - ns.set_number(0); - ns.set_square(0); - google::protobuf::util::SerializeDelimitedToOstream(ns, &ss); - } - - { - NumberAndSquare ns; - ns.set_number(3); - ns.set_square(9); - google::protobuf::util::SerializeDelimitedToOstream(ns, &ss); - } - - writeInsertDataQueryForInputTest(ss, "in_squares_00825", "00825_protobuf_format:NumberAndSquare", out); -} - - -void writeReferenceForOutputTest(std::ostream & out) -{ - { - Person person; - person.set_uuid("a7522158-3d41-4b77-ad69-6c598ee55c49"); - person.set_name("Ivan"); - person.set_surname("Petrov"); - person.set_gender(Gender::male); - person.set_birthdate(4015); // 1980-12-29 - person.set_photo("png"); - person.set_phonenumber(std::string("+74951234567\0", 13)); // Converted from FixedString(13) - person.set_isonline(true); - person.set_visittime(1546703100); // 2019-01-05 18:45:00 - person.set_age(38); - person.set_zodiacsign(ZodiacSign::capricorn); - person.add_songs("Yesterday"); - person.add_songs("Flowers"); - person.add_color(255); - person.add_color(0); - person.add_color(0); - person.set_hometown("Moscow"); - person.add_location(55.753215); - person.add_location(37.622504); - person.set_pi(3.14); - person.set_lotterywin(214.10); - person.set_someratio(0.1); - person.set_temperature(5.8); - person.set_randombignumber(17060000000); - auto* mu = person.add_measureunits(); - mu->set_unit("meter"); - mu->set_coef(1); - mu = person.add_measureunits(); - mu->set_unit("centimeter"); - mu->set_coef(0.01); - mu = person.add_measureunits(); - mu->set_unit("kilometer"); - mu->set_coef(1000); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->set_d(500); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->add_e(501); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->add_e(502); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - { - Person person; - person.set_uuid("c694ad8a-f714-4ea3-907d-fd54fb25d9b5"); - person.set_name("Natalia"); - person.set_surname("Sokolova"); - person.set_gender(Gender::female); - person.set_birthdate(8102); // 1992-03-08 - person.set_photo("jpg"); - person.set_isonline(false); - person.set_age(26); - person.set_zodiacsign(ZodiacSign::pisces); - person.add_color(100); - person.add_color(200); - person.add_color(50); - person.set_hometown("Plymouth"); - person.add_location(50.403724); - person.add_location(-4.142123); - person.set_pi(3.14159); - person.set_someratio(0.007); - person.set_temperature(5.4); - person.set_randombignumber(-20000000000000); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - { - Person person; - person.set_uuid("a7da1aa6-f425-4789-8947-b034786ed374"); - person.set_name("Vasily"); - person.set_surname("Sidorov"); - person.set_gender(Gender::male); - person.set_birthdate(9339); // 1995-07-28 - person.set_photo("bmp"); - person.set_phonenumber("+442012345678"); - person.set_isonline(true); - person.set_visittime(1546117200); // 2018-12-30 00:00:00 - person.set_age(23); - person.set_zodiacsign(ZodiacSign::leo); - person.add_songs("Sunny"); - person.add_color(250); - person.add_color(244); - person.add_color(10); - person.set_hometown("Murmansk"); - person.add_location(68.970682); - person.add_location(33.074981); - person.set_pi(3.14159265358979); - person.set_lotterywin(100000000000); - person.set_someratio(800); - person.set_temperature(-3.2); - person.set_randombignumber(154400000); - auto* mu = person.add_measureunits(); - mu->set_unit("pound"); - mu->set_coef(16); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->set_d(503); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - out << "ALTERNATIVE->" << std::endl; - - { - AltPerson person; - person.add_location(55); - person.add_location(37); - person.set_pi(3.14); - person.set_uuid("a7522158-3d41-4b77-ad69-6c598ee55c49"); - person.set_name("Ivan"); - person.set_gender(AltPerson::male); - person.set_zodiacsign(1222); // capricorn - person.set_birthdate(4015); // 1980-12-29 - person.set_age("38"); - person.set_isonline(OnlineStatus::online); - person.set_someratio(0.100000001490116119384765625); // 0.1 converted from float to double - person.set_visittime(1546703100); // 2019-01-05 18:45:00 - person.set_randombignumber(17060000000); - person.add_color(255); - person.add_color(0); - person.add_color(0); - person.set_lotterywin(214); - person.set_surname("Petrov"); - person.set_phonenumber(+74951234567); - person.set_temperature(5); - person.add_measureunits_unit("meter"); - person.add_measureunits_coef(1); - person.add_measureunits_unit("centimeter"); - person.add_measureunits_coef(0.01); - person.add_measureunits_unit("kilometer"); - person.add_measureunits_coef(1000); - person.set_nestiness_a_b_c_d(500); - person.add_nestiness_a_b_c_e(501); - person.add_nestiness_a_b_c_e(502); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - { - AltPerson person; - person.add_location(50); - person.add_location(-4); - person.set_pi(3.14159); - person.set_uuid("c694ad8a-f714-4ea3-907d-fd54fb25d9b5"); - person.set_name("Natalia"); - person.set_gender(AltPerson::female); - person.set_zodiacsign(219); // pisces - person.set_birthdate(8102); // 1992-03-08 - person.set_age("26"); - person.set_isonline(OnlineStatus::offline); - person.set_someratio(0.007000000216066837310791015625); // 0.007 converted from float to double - person.set_randombignumber(-20000000000000); - person.add_color(100); - person.add_color(200); - person.add_color(50); - person.set_surname("Sokolova"); - person.set_temperature(5); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - { - AltPerson person; - person.add_location(68); - person.add_location(33); - person.set_pi(3.1415926535897); - person.set_uuid("a7da1aa6-f425-4789-8947-b034786ed374"); - person.set_name("Vasily"); - person.set_gender(AltPerson::male); - person.set_zodiacsign(723); // leo - person.set_birthdate(9339); // 1995-07-28 - person.set_age("23"); - person.set_isonline(OnlineStatus::online); - person.set_someratio(800); - person.set_visittime(1546117200); // 2018-12-30 00:00:00 - person.set_randombignumber(154400000); - person.add_color(250); - person.add_color(244); - person.add_color(10); - person.set_lotterywin(100000000000); - person.set_surname("Sidorov"); - person.set_phonenumber(+442012345678); - person.set_temperature(-3); - person.add_measureunits_unit("pound"); - person.add_measureunits_coef(16); - person.set_nestiness_a_b_c_d(503); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - out << "STRINGS->" << std::endl; - - { - StrPerson person; - person.set_uuid("a7522158-3d41-4b77-ad69-6c598ee55c49"); - person.set_name("Ivan"); - person.set_surname("Petrov"); - person.set_gender("male"); - person.set_birthdate("1980-12-29"); - person.set_phonenumber(std::string("+74951234567\0", 13)); // Converted from FixedString(13) - person.set_isonline("1"); - person.set_visittime("2019-01-05 18:45:00"); - person.set_age("38"); - person.set_zodiacsign("capricorn"); - person.add_songs("Yesterday"); - person.add_songs("Flowers"); - person.add_color("255"); - person.add_color("0"); - person.add_color("0"); - person.set_hometown("Moscow"); - person.add_location("55.753215"); - person.add_location("37.622504"); - person.set_pi("3.14"); - person.set_lotterywin("214.10"); - person.set_someratio("0.1"); - person.set_temperature("5.8"); - person.set_randombignumber("17060000000"); - person.mutable_measureunits()->add_unit("meter"); - person.mutable_measureunits()->add_coef("1"); - person.mutable_measureunits()->add_unit("centimeter"); - person.mutable_measureunits()->add_coef("0.01"); - person.mutable_measureunits()->add_unit("kilometer"); - person.mutable_measureunits()->add_coef("1000"); - person.mutable_nestiness_a()->mutable_b_c()->set_d("500"); - person.mutable_nestiness_a()->mutable_b_c()->add_e("501"); - person.mutable_nestiness_a()->mutable_b_c()->add_e("502"); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - { - StrPerson person; - person.set_uuid("c694ad8a-f714-4ea3-907d-fd54fb25d9b5"); - person.set_name("Natalia"); - person.set_surname("Sokolova"); - person.set_gender("female"); - person.set_birthdate("1992-03-08"); - person.set_isonline("0"); - person.set_age("26"); - person.set_zodiacsign("pisces"); - person.add_color("100"); - person.add_color("200"); - person.add_color("50"); - person.set_hometown("Plymouth"); - person.add_location("50.403724"); - person.add_location("-4.142123"); - person.set_pi("3.14159"); - person.set_someratio("0.007"); - person.set_temperature("5.4"); - person.set_randombignumber("-20000000000000"); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - { - StrPerson person; - person.set_uuid("a7da1aa6-f425-4789-8947-b034786ed374"); - person.set_name("Vasily"); - person.set_surname("Sidorov"); - person.set_gender("male"); - person.set_birthdate("1995-07-28"); - person.set_phonenumber("+442012345678"); - person.set_isonline("1"); - person.set_visittime("2018-12-30 00:00:00"); - person.set_age("23"); - person.set_zodiacsign("leo"); - person.add_songs("Sunny"); - person.add_color("250"); - person.add_color("244"); - person.add_color("10"); - person.set_hometown("Murmansk"); - person.add_location("68.970682"); - person.add_location("33.074981"); - person.set_pi("3.14159265358979"); - person.set_lotterywin("100000000000.00"); - person.set_someratio("800"); - person.set_temperature("-3.2"); - person.set_randombignumber("154400000"); - person.mutable_measureunits()->add_unit("pound"); - person.mutable_measureunits()->add_coef("16"); - person.mutable_nestiness_a()->mutable_b_c()->set_d("503"); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - out << "SYNTAX2->" << std::endl; - - { - Syntax2Person person; - person.set_uuid("a7522158-3d41-4b77-ad69-6c598ee55c49"); - person.set_name("Ivan"); - person.set_surname("Petrov"); - person.set_gender(Syntax2Person::male); - person.set_birthdate(4015); // 1980-12-29 - person.set_photo("png"); - person.set_phonenumber(std::string("+74951234567\0", 13)); // Converted from FixedString(13) - person.set_isonline(true); - person.set_visittime(1546703100); // 2019-01-05 18:45:00 - person.set_age(38); - person.set_zodiacsign(Syntax2Person::capricorn); - person.add_songs("Yesterday"); - person.add_songs("Flowers"); - person.add_color(255); - person.add_color(0); - person.add_color(0); - person.set_hometown("Moscow"); - person.add_location(55.753215); - person.add_location(37.622504); - person.set_pi(3.14); - person.set_lotterywin(214.10); - person.set_someratio(0.1); - person.set_temperature(5.8); - person.set_randombignumber(17060000000); - person.mutable_measureunits()->add_unit("meter"); - person.mutable_measureunits()->add_coef(1); - person.mutable_measureunits()->add_unit("centimeter"); - person.mutable_measureunits()->add_coef(0.01); - person.mutable_measureunits()->add_unit("kilometer"); - person.mutable_measureunits()->add_coef(1000); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->set_d(500); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->add_e(501); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->add_e(502); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - { - Syntax2Person person; - person.set_uuid("c694ad8a-f714-4ea3-907d-fd54fb25d9b5"); - person.set_name("Natalia"); - person.set_surname("Sokolova"); - person.set_gender(Syntax2Person::female); - person.set_birthdate(8102); // 1992-03-08 - person.set_photo("jpg"); - person.set_isonline(false); - person.set_age(26); - person.set_zodiacsign(Syntax2Person::pisces); - person.add_color(100); - person.add_color(200); - person.add_color(50); - person.set_hometown("Plymouth"); - person.add_location(50.403724); - person.add_location(-4.142123); - person.set_pi(3.14159); - person.set_someratio(0.007); - person.set_temperature(5.4); - person.set_randombignumber(-20000000000000); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - { - Syntax2Person person; - person.set_uuid("a7da1aa6-f425-4789-8947-b034786ed374"); - person.set_name("Vasily"); - person.set_surname("Sidorov"); - person.set_gender(Syntax2Person::male); - person.set_birthdate(9339); // 1995-07-28 - person.set_photo("bmp"); - person.set_phonenumber("+442012345678"); - person.set_isonline(true); - person.set_visittime(1546117200); // 2018-12-30 00:00:00 - person.set_age(23); - person.set_zodiacsign(Syntax2Person::leo); - person.add_songs("Sunny"); - person.add_color(250); - person.add_color(244); - person.add_color(10); - person.set_hometown("Murmansk"); - person.add_location(68.970682); - person.add_location(33.074981); - person.set_pi(3.14159265358979); - person.set_lotterywin(100000000000); - person.set_someratio(800); - person.set_temperature(-3.2); - person.set_randombignumber(154400000); - person.mutable_measureunits()->add_unit("pound"); - person.mutable_measureunits()->add_coef(16); - person.mutable_nestiness()->mutable_a()->mutable_b()->mutable_c()->set_d(503); - google::protobuf::util::SerializeDelimitedToOstream(person, &out); - } - - out << "SQUARES->" << std::endl; - - { - NumberAndSquare ns; - ns.set_number(0); - ns.set_square(0); - google::protobuf::util::SerializeDelimitedToOstream(ns, &out); - } - - { - NumberAndSquare ns; - ns.set_number(2); - ns.set_square(4); - google::protobuf::util::SerializeDelimitedToOstream(ns, &out); - } - - { - NumberAndSquare ns; - ns.set_number(3); - ns.set_square(9); - google::protobuf::util::SerializeDelimitedToOstream(ns, &out); - } -} - - -void parseCommandLine(int argc, char ** argv, std::string & output_dir) -{ - namespace po = boost::program_options; - po::options_description desc; - output_dir = OUTPUT_DIR; - desc.add_options() - ("help,h", "Show help") - ("directory,d", po::value(&output_dir), - "Set the output directory. By default it's " OUTPUT_DIR); - po::parsed_options parsed = po::command_line_parser(argc, argv).options(desc).run(); - po::variables_map vm; - po::store(parsed, vm); - po::notify(vm); - if (!output_dir.empty()) - return; - - // Show help. - std::cout << "This utility generates delimited messages for tests checking protobuf IO support." << std::endl; - std::cout << desc; - std::cout << "Example:" << std::endl; - std::cout << argv[0] << " -g OUTPUT_REFERENCE" << std::endl; - std::exit(0); -} - -void writeFile(const std::string & filepath, void (*fn)(std::ostream &)) -{ - std::cout << "Writing '" << filepath << "' ... "; - std::fstream out(filepath, std::fstream::out | std::fstream::trunc); - fn(out); - std::cout << "done." << std::endl; -} - -int main(int argc, char ** argv) -{ - std::string output_dir; - parseCommandLine(argc, argv, output_dir); - writeFile(output_dir + "/00825_protobuf_format_input.insh", writeInsertDataQueriesForInputTest); - writeFile(output_dir + "/00825_protobuf_format_output.reference", writeReferenceForOutputTest); - return 0; -} diff --git a/utils/zookeeper-test/main.cpp b/utils/zookeeper-test/main.cpp index 8f8aac00866..102c30e59a1 100644 --- a/utils/zookeeper-test/main.cpp +++ b/utils/zookeeper-test/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,8 @@ void testCreateList(zkutil::ZooKeeper & zk) throw std::runtime_error("Children of /data/lst doesn't equal to three"); for (size_t i = 0; i < children.size(); ++i) { + std::cerr << "children:" << children[i] << std::endl; + std::cerr << "children size:" << children[i].size() << std::endl; if (children[i] != "d" + std::to_string(i + 1)) throw std::runtime_error(fmt::format("Incorrect children #{} got {}, expected {}", i, children[i], "d" + std::to_string(i + 1))); } @@ -127,18 +130,22 @@ void testCreateListWatchEvent(zkutil::ZooKeeper & zk) void testMultiRequest(zkutil::ZooKeeper & zk) { + std::cerr << "Testing multi request\n"; Coordination::Requests requests; requests.push_back(zkutil::makeCreateRequest("/data/multirequest", "aaa", zkutil::CreateMode::Persistent)); requests.push_back(zkutil::makeSetRequest("/data/multirequest", "bbb", -1)); zk.multi(requests); + std::cerr << "Multi executed\n"; try { requests.clear(); + std::cerr << "Testing bad multi\n"; requests.push_back(zkutil::makeCreateRequest("/data/multirequest", "qweqwe", zkutil::CreateMode::Persistent)); requests.push_back(zkutil::makeSetRequest("/data/multirequest", "bbb", -1)); requests.push_back(zkutil::makeSetRequest("/data/multirequest", "ccc", -1)); zk.multi(requests); + std::cerr << "Bad multi executed\n"; std::terminate(); } catch (...) @@ -147,6 +154,7 @@ void testMultiRequest(zkutil::ZooKeeper & zk) } checkEq(zk, "/data/multirequest", "bbb"); + std::cerr << "Multi request finished\n"; } std::mutex elements_mutex; @@ -207,6 +215,82 @@ void createPathAndSetWatch(zkutil::ZooKeeper & zk, const String & path_prefix, s } +std::string random_string(size_t length) +{ + auto randchar = []() -> char + { + const char charset[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + const size_t max_index = (sizeof(charset) - 1); + return charset[rand() % max_index]; + }; + std::string str(length, 0); + std::generate_n(str.begin(), length, randchar); + return str; +} + +std::string currentDateTime() +{ + time_t now = time(nullptr); + tm tstruct; + char buf[80]; + tstruct = *localtime(&now); + // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime + // for more information about date/time format + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tstruct); + + return buf; +} + + +void createOnPrefix(const std::string & zkhost, const String & path_prefix, size_t datasize, size_t total) +{ + zkutil::ZooKeeper zk(zkhost); + std::vector> holder_futures; + using namespace std::chrono; + try + { + for (size_t i = 0; i < total; ++i) + { + std::cerr << currentDateTime() << "] Request:" << i << std::endl; + std::string path = path_prefix + "/element" + std::to_string(i); + holder_futures.push_back(zk.asyncCreate(path, random_string(datasize), zkutil::CreateMode::Persistent)); + } + + for (size_t i = 0; i < holder_futures.size(); ++i) + holder_futures[i].get(); + } + catch (...) + { + ::exit(-1); + } +} + + +void createConcurrent(zkutil::ZooKeeper & testzk, const std::string & zkhost, size_t threads, size_t requests, size_t blobsize) +{ + std::vector> asyncs; + for (size_t i = 0; i < threads; ++i) + { + std::string path_prefix = "/data/create_test" + std::to_string(i); + testzk.createIfNotExists(path_prefix, ""); + auto callback = [&zkhost, path_prefix, requests, blobsize] () + { + createOnPrefix(zkhost, path_prefix, blobsize, requests); + }; + asyncs.push_back(std::async(std::launch::async, callback)); + } + + size_t i = 0; + for (auto & async : asyncs) + { + async.wait(); + i++; + } +} + void tryConcurrentWatches(zkutil::ZooKeeper & zk) { std::string path_prefix = "/concurrent_watches"; @@ -239,6 +323,7 @@ void tryConcurrentWatches(zkutil::ZooKeeper & zk) std::cerr << "WatchesTriggered:" << watches_triggered << std::endl; } + int main(int argc, char *argv[]) { if (argc != 2) @@ -254,15 +339,24 @@ int main(int argc, char *argv[]) try { + std::cerr << "Removing\n"; zk.tryRemoveRecursive("/data"); - testCreateGetExistsNode(zk); - testCreateSetNode(zk); - testCreateList(zk); - testCreateSetVersionRequest(zk); - testMultiRequest(zk); - testCreateSetWatchEvent(zk); - testCreateListWatchEvent(zk); - tryConcurrentWatches(zk); + std::cerr << "Creating\n"; + zk.createIfNotExists("/data", ""); + std::cerr << "Created\n"; + + Stopwatch watch; + createConcurrent(zk, argv[1], 1, 1005000, 10); + std::cerr << "Finished in: " << watch.elapsedMilliseconds() << "ms" << std::endl; + + //testCreateGetExistsNode(zk); + //testCreateSetNode(zk); + //testCreateList(zk); + //testCreateSetVersionRequest(zk); + //testMultiRequest(zk); + //testCreateSetWatchEvent(zk); + //testCreateListWatchEvent(zk); + //tryConcurrentWatches(zk); } catch (...) { diff --git a/website/README.md b/website/README.md index c2702c82157..c4383bea24c 100644 --- a/website/README.md +++ b/website/README.md @@ -16,3 +16,9 @@ virtualenv build # Open the web browser and go to http://localhost:8080/ ``` + +# How to quickly test the blog + +``` +./build.py --skip-multi-page --skip-single-page --skip-amp --skip-pdf --skip-git-log --skip-docs --skip-test-templates --livereload 8080 +``` diff --git a/website/benchmark/hardware/index.html b/website/benchmark/hardware/index.html index 6e6664af55a..92da6328f0f 100644 --- a/website/benchmark/hardware/index.html +++ b/website/benchmark/hardware/index.html @@ -73,7 +73,8 @@ Results for Digital Ocean are from Zimin Aleksey.
Results for 2x EPYC 7642 w/ 512 GB RAM (192 Cores) + 12X 1TB SSD (RAID6) are from Yiğit Konur and Metehan Çetinkaya of seo.do.
Results for Raspberry Pi and Digital Ocean CPU-optimized are from Fritz Wijaya.
Results for Digitalocean (Storage-intesinve VMs) + (CPU/GP) are from Yiğit Konur and Metehan Çetinkaya of seo.do.
-Results for 2x AMD EPYC 7F72 3.2 Ghz (Total 96 Cores, IBM Cloud's Bare Metal Service) from Yiğit Konur and Metehan Çetinkaya of seo.do. +Results for 2x AMD EPYC 7F72 3.2 Ghz (Total 96 Cores, IBM Cloud's Bare Metal Service) from Yiğit Konur and Metehan Çetinkaya of seo.do.
+Results for 2x AMD EPYC 7742 (128 physical cores, 1 TB DDR4-3200 RAM) from Yedige Davletgaliyev and Nikita Zhavoronkov of blockchair.com.

diff --git a/website/benchmark/hardware/results/amd_epyc_7742.json b/website/benchmark/hardware/results/amd_epyc_7742.json new file mode 100644 index 00000000000..61b76d9e37b --- /dev/null +++ b/website/benchmark/hardware/results/amd_epyc_7742.json @@ -0,0 +1,54 @@ +[ + { + "system": "AMD EPYC 7742", + "system_full": "AMD EPYC 7742, 256 cores, 1 TiB Samsung 16x64GB DDR4-3200 ECC, 2 * Samsung PM1725b 12.8TB (RAID 0)", + "time": "2021-02-23 00:00:00", + "kind": "server", + "result": + [ +[0.001, 0.001, 0.001], +[0.075, 0.080, 0.015], +[0.030, 0.029, 0.025], +[0.052, 0.027, 0.028], +[0.141, 0.104, 0.105], +[0.180, 0.127, 0.129], +[0.023, 0.018, 0.017], +[0.018, 0.016, 0.016], +[0.135, 0.097, 0.096], +[0.146, 0.109, 0.108], +[0.106, 0.070, 0.069], +[0.105, 0.068, 0.070], +[0.180, 0.137, 0.136], +[0.216, 0.171, 0.175], +[0.193, 0.160, 0.156], +[0.148, 0.123, 0.132], +[0.364, 0.317, 0.317], +[0.276, 0.245, 0.240], +[0.636, 0.562, 0.615], +[0.070, 0.018, 0.015], +[0.576, 0.131, 0.125], +[0.595, 0.124, 0.121], +[0.861, 0.596, 0.610], +[1.172, 0.262, 0.276], +[0.152, 0.054, 0.050], +[0.114, 0.046, 0.046], +[0.149, 0.052, 0.051], +[0.536, 0.288, 0.306], +[0.587, 0.207, 0.217], +[0.436, 0.419, 0.406], +[0.178, 0.110, 0.113], +[0.337, 0.165, 0.162], +[1.072, 0.855, 0.882], +[0.908, 0.600, 0.612], +[0.904, 0.604, 0.629], +[0.223, 0.207, 0.216], +[0.151, 0.143, 0.172], +[0.063, 0.061, 0.060], +[0.059, 0.053, 0.054], +[0.321, 0.318, 0.321], +[0.026, 0.021, 0.020], +[0.018, 0.015, 0.016], +[0.005, 0.005, 0.004] + ] + } +] diff --git a/website/benchmark/hardware/results/amd_ryzen_9_3950x.json b/website/benchmark/hardware/results/amd_ryzen_9_3950x.json index 0a3fc4ba288..8760a235521 100644 --- a/website/benchmark/hardware/results/amd_ryzen_9_3950x.json +++ b/website/benchmark/hardware/results/amd_ryzen_9_3950x.json @@ -50,5 +50,57 @@ [0.024, 0.015, 0.021], [0.007, 0.013, 0.006] ] + }, + { + "system": "AMD Ryzen 9", + "system_full": "AMD Ryzen 9 3950X 16-Core Processor, 64 GiB RAM, Samsung evo 970 plus 1TB", + "time": "2021-03-08 00:00:00", + "kind": "desktop", + "result": + [ +[0.002, 0.002, 0.002], +[0.013, 0.011, 0.010], +[0.030, 0.023, 0.023], +[0.071, 0.033, 0.031], +[0.090, 0.068, 0.066], +[0.165, 0.137, 0.137], +[0.015, 0.014, 0.015], +[0.013, 0.012, 0.012], +[0.317, 0.268, 0.261], +[0.337, 0.303, 0.301], +[0.108, 0.089, 0.091], +[0.127, 0.110, 0.114], +[0.714, 0.690, 0.643], +[0.888, 0.835, 0.809], +[0.748, 0.727, 0.704], +[0.666, 0.653, 0.652], +[1.868, 1.821, 1.826], +[1.007, 0.958, 0.957], +[4.466, 4.371, 4.377], +[0.074, 0.027, 0.027], +[0.748, 0.326, 0.307], +[0.844, 0.427, 0.408], +[2.040, 1.545, 1.552], +[1.392, 0.609, 0.560], +[0.237, 0.155, 0.142], +[0.140, 0.112, 0.114], +[0.233, 0.151, 0.146], +[0.790, 0.567, 0.545], +[0.981, 0.751, 0.752], +[3.532, 3.522, 3.516], +[0.505, 0.478, 0.456], +[1.078, 0.959, 0.959], +[5.653, 5.600, 5.570], +[3.572, 3.399, 3.405], +[3.619, 3.445, 3.429], +[1.176, 1.174, 1.165], +[0.140, 0.127, 0.124], +[0.054, 0.052, 0.052], +[0.052, 0.049, 0.048], +[0.275, 0.265, 0.265], +[0.025, 0.024, 0.025], +[0.020, 0.021, 0.019], +[0.006, 0.005, 0.005] + ] } ] diff --git a/website/blog/en/2021/fuzzing-clickhouse.md b/website/blog/en/2021/fuzzing-clickhouse.md new file mode 100644 index 00000000000..b6852dcce15 --- /dev/null +++ b/website/blog/en/2021/fuzzing-clickhouse.md @@ -0,0 +1,61 @@ +--- +title: 'Fuzzing ClickHouse' +image: 'https://blog-images.clickhouse.tech/en/2021/fuzzing-clickhouse/some-checks-were-not-successful.png' +date: '2021-03-11' +author: '[Alexander Kuzmenkov](https://github.com/akuzm)' +tags: ['fuzzing', 'testing'] +--- + +Testing is a major problem in software development: there is never enough of it. It becomes especially true for a database management system, whose task is to interpret a query language that works on the persistent state managed by the system in a distributed fashion. Each of these three functions is hard enough to test even in isolation, and it gets much worse when you combine them. As ClickHouse developers, we know this from experience. Despite a large amount of automated testing of all kinds we routinely perform as part of our continuous integration system, new bugs and regressions are creeping in. We are always looking for the ways to improve our test coverage, and this article will describe our recent development in this area — the AST-based query fuzzer. + +## How to Test a SQL DBMS + +A natural form of testing for a SQL DBMS is to create a SQL script describing the test case, and record its reference result. To test, we run the script and check that the result matches the reference. This is used in many SQL DBMS, and it is the default kind of a test you are expected to write for any ClickHouse feature or fix. Currently we have [73k lines of SQL tests alone](https://github.com/ClickHouse/ClickHouse/tree/master/tests/queries/0_stateless), that reach the [code coverage of 76%](https://clickhouse-test-reports.s3.yandex.net/0/47d684a5c35410201d4dd4f63f3287bf25cdabb7/coverage_report/test_output/index.html). + +This form of testing, where a developer writes a few simplified examples of how the feature can and cannot be used, is sometimes called "example-based testing". Sadly, the bugs often appear in various corner cases and intersections of features, and it is not practical to enumerate all of these cases by hand. There is a technique for automating this process, called "property-based testing". It lets you write more general tests of the form "for all values matching these specs, the result of some operation on them should match this other spec". For example, such a test can check that if you add two positive numbers, the result is greater than both of them. But you don't specify which numbers exactly, only these properties. Then, the property testing system randomly generates some examples with particular numbers that match the specification, and checks that the result also matches its specification. + +Property-based testing is said to be very efficient, but requires some developer effort and expertise to write the tests in a special way. There is another well-known testing technique that is in some sense a corner case of property-based testing, and that doesn't require much developer time. It is called fuzzing. When you are fuzzing your program, you feed it random inputs generated according to some grammar, and the property you are checking is that your program terminates correctly (no segfaults or assertions or other kinds of program errors). Most often, the grammar of input for fuzzing is simple — say, bit flips and additions, or maybe some dictionary. The space of possible inputs is huge, so to find interesting paths in it, fuzzing software records the code paths taken by the program under test for a particular input, and focuses on the inputs that lead to new code paths that were not seen before. It also employs some techniques for finding interesting constant values, and so on. In general, fuzzing allows you to find many interesting corner cases in your program automatically, without much developer involvement. + +Generating valid SQL queries with bit flips would take a long time, so there are systems that generate queries based on the SQL grammar, such as [SQLSmith](https://github.com/anse1/sqlsmith). They are succesfully used for finding bugs in databases. It would be interesting to use such a system for ClickHouse, but it requires some up-front effort to support the ClickHouse SQL grammar and functions, which may be different from the standard. Also, such systems don't use any feedback, so while they are much better than systems with primitive grammar, they still might have a hard time finding interesting examples. But we already have a big corpus of human-written interesting SQL queries — it's in our regression tests. Maybe we can use them as a base for fuzzing? We tried to do this, and it turned out to be surprisingly simple and efficient. + +## AST-based Query Fuzzer + +Consider some SQL query from a regression test. After parsing, it is easy to mutate the resulting AST (abstract syntax tree, an internal representation of the parsed query) before execution to introduce random changes into the query. For strings and arrays, we make random modifications such as inserting a random character or doubling the string. For numbers, there are well-known Bad Numbers such as 0, 1, powers of two and nearby, integer limits, `NaN`. `NaN`s proved to be especially efficient in finding bugs, because you can often have some alternative branches in your numeric code, but for a `NaN`, both branches hold (or not) simultaneously, so this leads to nasty effects. + +Another interesting thing we can do is change the arguments of functions, or the list of expressions in `SELECT`, `ORDER BY` and so on. Naturally, all the interesting arguments can be taken from other test queries. Same goes for changing the tables used in the queries. When the fuzzer runs in CI, it runs queries from all the SQL tests in random order, mixing into them some parts of queries it has seen previously. This process can eventually cover all the possible permutations of our features. + +The core implementation of the fuzzer is relatively small, consisting of about 700 lines of C++ code. A prototype was made in a couple of days, but naturally it took significantly longer to polish it and to start routinely using it in CI. It is very productive and let us find more than 200 bugs already (see the label [fuzz](https://github.com/ClickHouse/ClickHouse/labels/fuzz) on GitHub), some of which are serious logic errors or even memory errors. When we only started, we could segfault the server or make it enter a never-ending loop with simplest read-only queries such as `SELECT arrayReverseFill(x -> (x < 10), [])` or `SELECT geoDistance(0., 0., -inf, 1.)`. Of course I couldn't resist bringing down our [public playground](https://gh-api.clickhouse.tech/play?user=play#LS0gWW91IGNhbiBxdWVyeSB0aGUgR2l0SHViIGhpc3RvcnkgZGF0YSBoZXJlLiBTZWUgaHR0cHM6Ly9naC5jbGlja2hvdXNlLnRlY2gvZXhwbG9yZXIvIGZvciB0aGUgZGVzY3JpcHRpb24gYW5kIGV4YW1wbGUgcXVlcmllcy4Kc2VsZWN0ICdoZWxsbyB3b3JsZCc=) with some of these queries, and was content to see that the server soon restarts correctly. These queries are actually minified by hand, normally the fuzzer would generate something barely intelligible such as: +``` +SELECT + (val + 257, + (((tuple(NULL), 10.000100135803223), tuple(-inf)), '-1', (NULL, '0.10', NULL), NULL), + (val + 9223372036854775807) = (rval * 100), + tuple(65535), tuple(NULL), NULL, NULL), + * +FROM +( + SELECT dummy AS val + FROM system.one +) AS s1 +ANY LEFT JOIN +( + SELECT toLowCardinality(toNullable(dummy)) AS rval + FROM system.one +) AS s2 ON (val + 100) = (rval * 7) +``` +In principle, we could add automated test case minification by modifying AST in the same vein with fuzzing. This is somewhat complicated by the fact that the server dies after every, excuse my pun, successfully failed query, so we didn't implement it yet. + +Not all errors the fuzzer finds are significant, some of them are pretty boring and harmless, such as a wrong error code for an out-of-bounds argument. We still try to fix all of them, because this lets us ensure that under normal operation, the fuzzer doesn't find any errors. This is similar to the approach usually taken with compiler warnings and other optional diagnostics — it's better to fix or disable every single case, so that you can be sure you have no diagnostics if everything is OK, and it's easy to notice new problems. + +After fixing the majority of pre-existing error, this fuzzer became efficient for finding errors in new features. Pull requests introducing new features normally add an SQL test, and we pay extra attention to the new tests when fuzzing, generating more permutations for them. Even if the coverage of the test is not sufficient, there is a good chance that the fuzzer will find the missing corner cases. So when we see that all the fuzzer runs in different configurations have failed for a particular pull request, this almost always means that it introduces a new bug. When developing a feature that requires new grammar, it is also helpful to add fuzzing support for it. I did this for window functions early in the development, and it helped me find several bugs. + +A major factor that makes fuzzing really efficient for us is that we have a lot of assertions and other checks of program logic in our code. For debug-only checks, we use the plain `assert` macro from ``. For checks that are needed even in release mode, we use an exception with a special code `LOGICAL_ERROR` that signifies an internal program error. We did some work to ensure that these errors are distinct from errors caused by the wrong user actions. A user error reported for a randomly generated query is normal (e.g. it references some non-existent columns), but when we see an internal program error, we know that it's definitely a bug, same as an assertion. Of course, even without assertions, you get some checks for memory errors provided by the OS (segfaults). Another way to add runtime checks to your program is to use some kind of sanitizer. We already run most of our tests under clang's Address, Memory, UndefinedBehavior and Thread sanitizers. Using them in conjunction with this fuzzer also proved to be very efficient. + +To see for yourself how the fuzzer works, you only need the normal ClickHouse client. Start `clickhouse-client --query-fuzzer-runs=100`, enter any query, and enjoy the client going crazy and running a hundred of random queries instead. All queries from the current session become a source for expressions for fuzzing, so try entering several different queries to get more interesting results. Be careful not to do this in production! When you do this experiment, you'll soon notice that the fuzzer tends to generate queries that take very long to run. This is why for the CI fuzzer runs we have to configure the server to limit query execution time, memory usage and so on using the corresponding [server settings](https://clickhouse.tech/docs/en/operations/settings/query-complexity/#:~:text=In%20the%20default%20configuration%20file,query%20within%20a%20single%20server.). We had a hilarious situation after that: the fuzzer figured out how to remove the limits by generating a `SET max_execution_time = 0` query, and then generated a never-ending query and failed. Thankfully we were able to defeat its cleverness by using [settings constraints](https://clickhouse.tech/docs/en/operations/settings/constraints-on-settings/). + +## Other Fuzzers + +The AST-based fuzzer we discussed is only one of the many kinds of fuzzers we have in ClickHouse. There is a [talk](https://www.youtube.com/watch?v=GbmK84ZwSeI&t=4481s) (in Russian, [slides are here](https://presentations.clickhouse.tech/cpp_siberia_2021/)) by Alexey Milovidov that explores all the fuzzers we have. Another interesting recent development is application of pivoted query synthesis technique, implemented in [SQLancer](https://github.com/sqlancer/sqlancer), to ClickHouse. The authors are going to give [a talk about this](https://heisenbug-piter.ru/2021/spb/talks/nr1cwknssdodjkqgzsbvh/) soon, so stay tuned. + +_2021-03-11 [Alexander Kuzmenkov](https://github.com/akuzm)_ + diff --git a/website/blog/en/2021/reading-from-external-memory.md b/website/blog/en/2021/reading-from-external-memory.md new file mode 100644 index 00000000000..f431bde0625 --- /dev/null +++ b/website/blog/en/2021/reading-from-external-memory.md @@ -0,0 +1,69 @@ +--- +title: 'A journey to io_uring, AIO and modern storage devices' +image: 'https://blog-images.clickhouse.tech/en/2021/reading-from-external-memory/all-single-read.png' +date: '2021-03-09' +author: '[Ruslan Savchenko](https://github.com/savrus)' +tags: ['Linux', 'benchmark', 'experiment'] +--- + +*While main memory is considered to be rather cheap by some systems designers it is not always possible to store everything in the main memory. When data is stored in external memory one has to think carefully how to access the data. There are several kind of storage devices and more than one system call to read from them. We performed experiments to find out how different Linux system calls perform for available devices. In total HDD, SATA SSD, NVMe SSD, and Intel Optane were accessed via single-threaded and multi-threaded pread, Linux aio, and new io_uring interfaces. Full report is available in PDF format:* [link](https://arxiv.org/pdf/2102.11198). *We give one section from the report as an example.* + +# Single Random Read + +External memory devices are block devices which means data transfer between a device and a host is done in blocks rather than single bytes. Typically 512 bytes or 4 kilobytes blocks are used. These block sizes have been chosen by manufactures long time ago and may be not the best choice for modern devices. By requesing larger amount of contigious data we can emulate larger block size. Let's find out how modern devices perform with larger blocks. + +Our goal is to pick the best block size for a random read. An application (or filesystem) can pick any block size and access data with respect to this block size. We vary block size from 4 kilobytes up to 32 megabytes. For each block size we make some random reads. Among these reads we calculate average, minimum and maximum latency as well as 99,0 and 99,9 percentiles. We use system call pread(2) in this experiment. We believe that lseek(2) followed by read(2) should have the same performance since the observed storage access time is far longer than a system call. + +## Hard Disk Drive + +This figure shows results for HDD. + +![HDD single read latency](https://blog-images.clickhouse.tech/en/2021/reading-from-external-memory/hdd-single-read.png) + +The latency is almost the same for all block sizes smaller than 256 kilobytes. This happens because seek time is much larger than the data transfer time. The seek time includes arm positioning to find the right track and awaiting for platter rotation to bring data under the head. A simple consequence is that for a HDD random read one should use blocks of size at least 256 kilobytes. Even if an application use smaller blocks the drive access time would be the same. However one could still decide to use smaller blocks for better cache utilization: if the amount of data per request is small and is expected to fit in cache then storing a large block along with the requested data would actually make cache capacity smaller in terms of useful data. + +The 256 kilobyte block read takes 12 milliseconds on the average. We experienced variations from 4 milliseconds up to 25 milliseconds. This is really a huge amount of time for a computer. For example the typical process scheduling quantum is just a few milliseconds. An operating system can (and in fact does) execute other processes while our process waits for the data to arrive from the hard drive. + +## SATA SSD + +The figure below shows SATA SSD read latencies. + +![SATA SSD single read latency](https://blog-images.clickhouse.tech/en/2021/reading-from-external-memory/ssd-single-read.png) + +Note that the time at the lower part of the figure is in microseconds (we use standard shortenings ms for milliseconds and us for microseconds). Reading block of size 4 kilobytes takes 140 microseconds on the average and the time growth is linear when the block size increase. Compared to HDD reading a 4 kilobyte block from SSD is 80 times faster. For a 256 kilobyte block SSD is ten times faster than HDD. When block size is large enough (starting from 4 megabytes) SSD is only two times faster than HDD. + +## NVMe SSD + +The next figure shows results for NVMe SSD. + +![NVMe SSD single read latency](https://blog-images.clickhouse.tech/en/2021/reading-from-external-memory/nvme-single-read.png) + +The latency is better than those for SATA SSD. For a 4 kilobytes block size the average time improved only a little, but the 99 percentile is two times lower. It takes less than millisecond to read a megabyte block from NVMe SSD. For SATA SSD it took 3 milliseconds. As we see, upgrade from SATA SSD to NVMe SSD is not as dramatic as upgrade from HDD to SATA SSD. This is not surprising since both SATA and NVMe SSD are based on the same thechnology. Only interfaces differ. + +## Intel Optane + +This figure shows results for Intel Optane SSD. + +![Intel Optane single read latency](https://blog-images.clickhouse.tech/en/2021/reading-from-external-memory/optane-single-read.png) + +Minimal latency is 12 microseconds whih is 10 times lower than those of NVMe SSD. Average latency is 1000 lower than those of HDD. There is quite large variation for small block read latency: even though the average time is quite low and close to minimal latency the maximum latency and even 99 percentile are significantly worse. If somebody looks at these results and wishes to create an Intel Optane-based service with 12 microsecond latency for reads they would have to install larger number of Intel Optane drives or consider providing more realistic timings. + +When latency is so small overheads of context switching and interrupt handling become noticeable. One can use polling mode to gain some improvement. In this mode the Linux kernel monitors the completion queue instead of switching to some other job and relying on hardware interrupt with interrupt handler to notify about completion. Clearly, it is considerable to use the polling mode only when hardware response is expected to arrive fast enough. +![Intel Optane single read latency in polling mode](https://blog-images.clickhouse.tech/en/2021/reading-from-external-memory/optane-single-hipri-read.png) + +The figure above shows results for reading from Intel Optane in polling mode. The polling mode is used when an application calls preadv2(2) system call with RWF\_HIGHPRI flag. Compared to usual pread(2) the polling mode lowers the maximum latency by a factor of two for block sizes up to 256 kilobytes. + +## Summary + +To summarize our results the next figure shows single read latencies for all four storage types on a single chart. + +![Single read latency for Optane, SSD and HDD](https://blog-images.clickhouse.tech/en/2021/reading-from-external-memory/all-single-read.png) + +Starting from 4 megabytes the latency is easily predicted by linear extrapolation so we don't show larger blocks here. To show everything on a single figure we are forced to use quite an overloaded legend. We use vertical level to show the latency and we iterate the block size horizontally. For each block size we show four bars, from left to right: for Intel Optane, NVMe SSD, SATA SSD, and HDD. Storage type is represented by hatch and the latency by color. + +We see that solid state device latencies are far better than HDD. For a single read the leader is Intel Optane, however as we shall see later it has it's own drawback compared to NVMe SSD. NVMe SSD and SATA SSD look quite close to each other when the block size is small. Our observations show that the best block size for random read is 256 kilobytes for HDD, 4 kilobytes for NVMe and SATA SSD and 8 kilobytes for Intel Optane. + +So, how about testing modern IO interfaces in Linux? Continue reading the [full article](https://arxiv.org/pdf/2102.11198). + +2021-03-09 [Ruslan Savchenko](https://github.com/savrus) + diff --git a/website/css/highlight.css b/website/css/highlight.css index 55a0054b07f..7cc8a4865dd 100644 --- a/website/css/highlight.css +++ b/website/css/highlight.css @@ -11,7 +11,7 @@ .syntax .hll { background-color: #b9b6b0 } .syntax { background: #f8f9fa; color: #2f1e2e } .syntax .c { color: #8d8687 } /* Comment */ -.syntax .err { color: #ef6155 } /* Error */ +.syntax .err {} /* Error */ .syntax .k { color: #000000; font-weight: bold } /* Keyword */ .syntax .l { color: #0088ff } /* Literal */ .syntax .n { color: #2f1e2e } /* Name */