Merge branch 'master' into drop_tables

This commit is contained in:
zhongyuankai 2024-03-26 14:09:04 +08:00
commit aa3830a3db
155 changed files with 3984 additions and 2635 deletions

View File

@ -6,6 +6,7 @@ env:
PYTHONUNBUFFERED: 1
on: # yamllint disable-line rule:truthy
merge_group:
pull_request:
types:
- synchronize
@ -29,6 +30,7 @@ jobs:
fetch-depth: 0 # to get version
filter: tree:0
- name: Labels check
if: ${{ github.event_name != 'merge_group' }}
run: |
cd "$GITHUB_WORKSPACE/tests/ci"
python3 run_check.py
@ -56,16 +58,9 @@ jobs:
echo 'EOF'
} >> "$GITHUB_OUTPUT"
- name: Re-create GH statuses for skipped jobs if any
if: ${{ github.event_name != 'merge_group' }}
run: |
python3 "$GITHUB_WORKSPACE/tests/ci/ci.py" --infile ${{ runner.temp }}/ci_run_data.json --update-gh-statuses
- name: Style check early
# hack to run style check before the docker build job if possible (style-check image not changed)
if: contains(fromJson(steps.runconfig.outputs.CI_DATA).jobs_data.jobs_to_do, 'Style check early')
run: |
DOCKER_TAG=$(echo '${{ toJson(fromJson(steps.runconfig.outputs.CI_DATA).docker_data.images) }}' | tr -d '\n')
export DOCKER_TAG=$DOCKER_TAG
python3 ./tests/ci/style_check.py --no-push
python3 "$GITHUB_WORKSPACE/tests/ci/ci.py" --infile ${{ runner.temp }}/ci_run_data.json --post --job-name 'Style check'
BuildDockers:
needs: [RunConfig]
if: ${{ !failure() && !cancelled() && toJson(fromJson(needs.RunConfig.outputs.data).docker_data.missing_multi) != '[]' }}

View File

@ -1,10 +1,184 @@
### Table of Contents
**[ClickHouse release v24.3 LTS, 2024-03-26](#243)**<br/>
**[ClickHouse release v24.2, 2024-02-29](#242)**<br/>
**[ClickHouse release v24.1, 2024-01-30](#241)**<br/>
**[Changelog for 2023](https://clickhouse.com/docs/en/whats-new/changelog/2023/)**<br/>
# 2024 Changelog
### <a id="243"></a> ClickHouse release 24.3 LTS, 2024-03-26
#### Upgrade Notes
* The setting `allow_experimental_analyzer` is enabled by default and it switches the query analysis to a new implementation, which has better compatibility and feature completeness. The feature "analyzer" is considered beta instead of experimental. You can turn the old behavior by setting the `compatibility` to `24.2` or disabling the `allow_experimental_analyzer` setting. Watch the [video on YouTube](https://www.youtube.com/watch?v=zhrOYQpgvkk).
* ClickHouse allows arbitrary binary data in the String data type, which is typically UTF-8. Parquet/ORC/Arrow Strings only support UTF-8. That's why you can choose which Arrow's data type to use for the ClickHouse String data type - String or Binary. This is controlled by the settings, `output_format_parquet_string_as_string`, `output_format_orc_string_as_string`, `output_format_arrow_string_as_string`. While Binary would be more correct and compatible, using String by default will correspond to user expectations in most cases. Parquet/ORC/Arrow supports many compression methods, including lz4 and zstd. ClickHouse supports each and every compression method. Some inferior tools lack support for the faster `lz4` compression method, that's why we set `zstd` by default. This is controlled by the settings `output_format_parquet_compression_method`, `output_format_orc_compression_method`, and `output_format_arrow_compression_method`. We changed the default to `zstd` for Parquet and ORC, but not Arrow (it is emphasized for low-level usages). [#61817](https://github.com/ClickHouse/ClickHouse/pull/61817) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* In the new ClickHouse version, the functions `geoDistance`, `greatCircleDistance`, and `greatCircleAngle` will use 64-bit double precision floating point data type for internal calculations and return type if all the arguments are Float64. This closes [#58476](https://github.com/ClickHouse/ClickHouse/issues/58476). In previous versions, the function always used Float32. You can switch to the old behavior by setting `geo_distance_returns_float64_on_float64_arguments` to `false` or setting `compatibility` to `24.2` or earlier. [#61848](https://github.com/ClickHouse/ClickHouse/pull/61848) ([Alexey Milovidov](https://github.com/alexey-milovidov)). Co-authored with [Geet Patel](https://github.com/geetptl).
* The obsolete in-memory data parts have been deprecated since version 23.5 and have not been supported since version 23.10. Now the remaining code is removed. Continuation of [#55186](https://github.com/ClickHouse/ClickHouse/issues/55186) and [#45409](https://github.com/ClickHouse/ClickHouse/issues/45409). It is unlikely that you have used in-memory data parts because they were available only before version 23.5 and only when you enabled them manually by specifying the corresponding SETTINGS for a MergeTree table. To check if you have in-memory data parts, run the following query: `SELECT part_type, count() FROM system.parts GROUP BY part_type ORDER BY part_type`. To disable the usage of in-memory data parts, do `ALTER TABLE ... MODIFY SETTING min_bytes_for_compact_part = DEFAULT, min_rows_for_compact_part = DEFAULT`. Before upgrading from old ClickHouse releases, first check that you don't have in-memory data parts. If there are in-memory data parts, disable them first, then wait while there are no in-memory data parts and continue the upgrade. [#61127](https://github.com/ClickHouse/ClickHouse/pull/61127) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Changed the column name from `duration_ms` to `duration_microseconds` in the `system.zookeeper` table to reflect the reality that the duration is in the microsecond resolution. [#60774](https://github.com/ClickHouse/ClickHouse/pull/60774) ([Duc Canh Le](https://github.com/canhld94)).
* Reject incoming INSERT queries in case when query-level settings `async_insert` and `deduplicate_blocks_in_dependent_materialized_views` are enabled together. This behaviour is controlled by a setting `throw_if_deduplication_in_dependent_materialized_views_enabled_with_async_insert` and enabled by default. This is a continuation of https://github.com/ClickHouse/ClickHouse/pull/59699 needed to unblock https://github.com/ClickHouse/ClickHouse/pull/59915. [#60888](https://github.com/ClickHouse/ClickHouse/pull/60888) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)).
* Utility `clickhouse-copier` is moved to a separate repository on GitHub: https://github.com/ClickHouse/copier. It is no longer included in the bundle but is still available as a separate download. This closes: [#60734](https://github.com/ClickHouse/ClickHouse/issues/60734) This closes: [#60540](https://github.com/ClickHouse/ClickHouse/issues/60540) This closes: [#60250](https://github.com/ClickHouse/ClickHouse/issues/60250) This closes: [#52917](https://github.com/ClickHouse/ClickHouse/issues/52917) This closes: [#51140](https://github.com/ClickHouse/ClickHouse/issues/51140) This closes: [#47517](https://github.com/ClickHouse/ClickHouse/issues/47517) This closes: [#47189](https://github.com/ClickHouse/ClickHouse/issues/47189) This closes: [#46598](https://github.com/ClickHouse/ClickHouse/issues/46598) This closes: [#40257](https://github.com/ClickHouse/ClickHouse/issues/40257) This closes: [#36504](https://github.com/ClickHouse/ClickHouse/issues/36504) This closes: [#35485](https://github.com/ClickHouse/ClickHouse/issues/35485) This closes: [#33702](https://github.com/ClickHouse/ClickHouse/issues/33702) This closes: [#26702](https://github.com/ClickHouse/ClickHouse/issues/26702).
* To increase compatibility with MySQL, the compatibility alias `locate` now accepts arguments `(needle, haystack[, start_pos])` by default. The previous behavior `(haystack, needle, [, start_pos])` can be restored by setting `function_locate_has_mysql_compatible_argument_order = 0`. [#61092](https://github.com/ClickHouse/ClickHouse/pull/61092) ([Robert Schulze](https://github.com/rschu1ze)).
* Forbid `SimpleAggregateFunction` in `ORDER BY` of `MergeTree` tables (like `AggregateFunction` is forbidden, but they are forbidden because they are not comparable) by default (use `allow_suspicious_primary_key` to allow them). [#61399](https://github.com/ClickHouse/ClickHouse/pull/61399) ([Azat Khuzhin](https://github.com/azat)).
* The `Ordinary` database engine is deprecated. You will receive a warning in clickhouse-client if your server is using it. This closes [#52229](https://github.com/ClickHouse/ClickHouse/issues/52229). [#56942](https://github.com/ClickHouse/ClickHouse/pull/56942) ([shabroo](https://github.com/shabroo)).
#### New Feature
* Support reading and writing backups as `tar` (in addition to `zip`). [#59535](https://github.com/ClickHouse/ClickHouse/pull/59535) ([josh-hildred](https://github.com/josh-hildred)).
* Implemented support for S3 Express buckets. [#59965](https://github.com/ClickHouse/ClickHouse/pull/59965) ([Nikita Taranov](https://github.com/nickitat)).
* Allow to attach parts from a different disk (using copy instead of hard link). [#60112](https://github.com/ClickHouse/ClickHouse/pull/60112) ([Unalian](https://github.com/Unalian)).
* Size-capped `Memory` tables: controlled by their settings, `min_bytes_to_keep, max_bytes_to_keep, min_rows_to_keep` and `max_rows_to_keep`. [#60612](https://github.com/ClickHouse/ClickHouse/pull/60612) ([Jake Bamrah](https://github.com/JakeBamrah)).
* Separate limits on number of waiting and executing queries. Added new server setting `max_waiting_queries` that limits the number of queries waiting due to `async_load_databases`. Existing limits on number of executing queries no longer count waiting queries. [#61053](https://github.com/ClickHouse/ClickHouse/pull/61053) ([Sergei Trifonov](https://github.com/serxa)).
* Added a table `system.keywords` which contains all the keywords from parser. Mostly needed and will be used for better fuzzing and syntax highlighting. [#51808](https://github.com/ClickHouse/ClickHouse/pull/51808) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)).
* Add support for `ATTACH PARTITION ALL`. [#61107](https://github.com/ClickHouse/ClickHouse/pull/61107) ([Kirill Nikiforov](https://github.com/allmazz)).
* Add a new function, `getClientHTTPHeader`. This closes [#54665](https://github.com/ClickHouse/ClickHouse/issues/54665). Co-authored with @lingtaolf. [#61820](https://github.com/ClickHouse/ClickHouse/pull/61820) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Add `generate_series` as a table function (compatibility alias for PostgreSQL to the existing `numbers` function). This function generates table with an arithmetic progression with natural numbers. [#59390](https://github.com/ClickHouse/ClickHouse/pull/59390) ([divanik](https://github.com/divanik)).
* A mode for `topK`/`topkWeighed` support mode, which return count of values and its error. [#54508](https://github.com/ClickHouse/ClickHouse/pull/54508) ([UnamedRus](https://github.com/UnamedRus)).
* Added function `toMillisecond` which returns the millisecond component for values of type`DateTime` or `DateTime64`. [#60281](https://github.com/ClickHouse/ClickHouse/pull/60281) ([Shaun Struwig](https://github.com/Blargian)).
* Allow configuring HTTP redirect handlers for clickhouse-server. For example, you can make `/` redirect to the Play UI. [#60390](https://github.com/ClickHouse/ClickHouse/pull/60390) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
#### Performance Improvement
* Optimized function `dotProduct` to omit unnecessary and expensive memory copies. [#60928](https://github.com/ClickHouse/ClickHouse/pull/60928) ([Robert Schulze](https://github.com/rschu1ze)).
* 30x faster printing for 256-bit integers. [#61100](https://github.com/ClickHouse/ClickHouse/pull/61100) ([Raúl Marín](https://github.com/Algunenano)).
* If the table's primary key contains mostly useless columns, don't keep them in memory. This is controlled by a new setting `primary_key_ratio_of_unique_prefix_values_to_skip_suffix_columns` with the value `0.9` by default, which means: for a composite primary key, if a column changes its value for at least 0.9 of all the times, the next columns after it will be not loaded. [#60255](https://github.com/ClickHouse/ClickHouse/pull/60255) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Make all format names case insensitive, like Tsv, or TSV, or tsv, or even rowbinary. [#60420](https://github.com/ClickHouse/ClickHouse/pull/60420) ([豪肥肥](https://github.com/HowePa)). I appreciate if you will continue to write it correctly, e.g., `JSON` 😇, not `Json` 🤮, but we don't mind if you spell it as you prefer.
* Improve the performance of serialized aggregation method when involving multiple `Nullable` columns. [#55809](https://github.com/ClickHouse/ClickHouse/pull/55809) ([Amos Bird](https://github.com/amosbird)).
* Lazy build JSON's output to improve performance of ALL JOIN. [#58278](https://github.com/ClickHouse/ClickHouse/pull/58278) ([LiuNeng](https://github.com/liuneng1994)).
* Make HTTP/HTTPs connections with external services, such as AWS S3 reusable for all uses cases. Even when response is 3xx or 4xx. [#58845](https://github.com/ClickHouse/ClickHouse/pull/58845) ([Sema Checherinda](https://github.com/CheSema)).
* Improvements to aggregate functions `argMin` / `argMax` / `any` / `anyLast` / `anyHeavy`, as well as `ORDER BY {u8/u16/u32/u64/i8/i16/u32/i64) LIMIT 1` queries. [#58640](https://github.com/ClickHouse/ClickHouse/pull/58640) ([Raúl Marín](https://github.com/Algunenano)).
* Trivial optimization for column's filter. Peak memory can be reduced to 44% of the original in some cases. [#59698](https://github.com/ClickHouse/ClickHouse/pull/59698) ([李扬](https://github.com/taiyang-li)).
* Execute `multiIf` function in a columnar fashion when the result type's underlying type is a number. [#60384](https://github.com/ClickHouse/ClickHouse/pull/60384) ([李扬](https://github.com/taiyang-li)).
* Faster (almost 2x) mutexes. [#60823](https://github.com/ClickHouse/ClickHouse/pull/60823) ([Azat Khuzhin](https://github.com/azat)).
* Drain multiple connections in parallel when a distributed query is finishing. [#60845](https://github.com/ClickHouse/ClickHouse/pull/60845) ([lizhuoyu5](https://github.com/lzydmxy)).
* Optimize data movement between columns of a Nullable number or a Nullable string, which improves some micro-benchmarks. [#60846](https://github.com/ClickHouse/ClickHouse/pull/60846) ([李扬](https://github.com/taiyang-li)).
* Operations with the filesystem cache will suffer less from the lock contention. [#61066](https://github.com/ClickHouse/ClickHouse/pull/61066) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Optimize array join and other JOINs by preventing a wrong compiler's optimization. Close [#61074](https://github.com/ClickHouse/ClickHouse/issues/61074). [#61075](https://github.com/ClickHouse/ClickHouse/pull/61075) ([李扬](https://github.com/taiyang-li)).
* If a query with a syntax error contained `COLUMNS` matcher with a regular expression, the regular expression was compiled each time during the parser's backtracking, instead of being compiled once. This was a fundamental error. The compiled regexp was put to AST. But the letter A in AST means "abstract" which means it should not contain heavyweight objects. Parts of AST can be created and discarded during parsing, including a large number of backtracking. This leads to slowness on the parsing side and consequently allows DoS by a readonly user. But the main problem is that it prevents progress in fuzzers. [#61543](https://github.com/ClickHouse/ClickHouse/pull/61543) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Add a new analyzer pass to optimize the IN operator for a single value. [#61564](https://github.com/ClickHouse/ClickHouse/pull/61564) ([LiuNeng](https://github.com/liuneng1994)).
* DNSResolver shuffles set of resolved IPs which is needed to uniformly utilize multiple endpoints of AWS S3. [#60965](https://github.com/ClickHouse/ClickHouse/pull/60965) ([Sema Checherinda](https://github.com/CheSema)).
#### Experimental Feature
* Support parallel reading for Azure blob storage. This improves the performance of the experimental Azure object storage. [#61503](https://github.com/ClickHouse/ClickHouse/pull/61503) ([SmitaRKulkarni](https://github.com/SmitaRKulkarni)).
* Add asynchronous WriteBuffer for Azure blob storage similar to S3. This improves the performance of the experimental Azure object storage. [#59929](https://github.com/ClickHouse/ClickHouse/pull/59929) ([SmitaRKulkarni](https://github.com/SmitaRKulkarni)).
* Use managed identity for backups IO when using Azure Blob Storage. Add a setting to prevent ClickHouse from attempting to create a non-existent container, which requires permissions at the storage account level. [#61785](https://github.com/ClickHouse/ClickHouse/pull/61785) ([Daniel Pozo Escalona](https://github.com/danipozo)).
* Add a setting `parallel_replicas_allow_in_with_subquery = 1` which allows subqueries for IN work with parallel replicas. [#60950](https://github.com/ClickHouse/ClickHouse/pull/60950) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
* A change for the "zero-copy" replication: all zero copy locks related to a table have to be dropped when the table is dropped. The directory which contains these locks has to be removed also. [#57575](https://github.com/ClickHouse/ClickHouse/pull/57575) ([Sema Checherinda](https://github.com/CheSema)).
#### Improvement
* Use `MergeTree` as a default table engine. [#60524](https://github.com/ClickHouse/ClickHouse/pull/60524) ([Alexey Milovidov](https://github.com/alexey-milovidov))
* Enable `output_format_pretty_row_numbers` by default. It is better for usability. [#61791](https://github.com/ClickHouse/ClickHouse/pull/61791) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* In the previous version, some numbers in Pretty formats were not pretty enough. [#61794](https://github.com/ClickHouse/ClickHouse/pull/61794) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* A long value in Pretty formats won't be cut if it is the single value in the resultset, such as in the result of the `SHOW CREATE TABLE` query. [#61795](https://github.com/ClickHouse/ClickHouse/pull/61795) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Similarly to `clickhouse-local`, `clickhouse-client` will accept the `--output-format` option as a synonym to the `--format` option. This closes [#59848](https://github.com/ClickHouse/ClickHouse/issues/59848). [#61797](https://github.com/ClickHouse/ClickHouse/pull/61797) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* If stdout is a terminal and the output format is not specified, `clickhouse-client` and similar tools will use `PrettyCompact` by default, similarly to the interactive mode. `clickhouse-client` and `clickhouse-local` will handle command line arguments for input and output formats in a unified fashion. This closes [#61272](https://github.com/ClickHouse/ClickHouse/issues/61272). [#61800](https://github.com/ClickHouse/ClickHouse/pull/61800) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Underscore digit groups in Pretty formats for better readability. This is controlled by a new setting, `output_format_pretty_highlight_digit_groups`. [#61802](https://github.com/ClickHouse/ClickHouse/pull/61802) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Add ability to override initial INSERT settings via `SYSTEM FLUSH DISTRIBUTED`. [#61832](https://github.com/ClickHouse/ClickHouse/pull/61832) ([Azat Khuzhin](https://github.com/azat)).
* Enable processors profiling (time spent/in and out bytes for sorting, aggregation, ...) by default. [#61096](https://github.com/ClickHouse/ClickHouse/pull/61096) ([Azat Khuzhin](https://github.com/azat)).
* Support files without format extension in Filesystem database. [#60795](https://github.com/ClickHouse/ClickHouse/pull/60795) ([Kruglov Pavel](https://github.com/Avogar)).
* Added `none_only_active` mode for `distributed_ddl_output_mode` setting. [#60340](https://github.com/ClickHouse/ClickHouse/pull/60340) ([Alexander Tokmakov](https://github.com/tavplubix)).
* The advanced dashboard has slightly better colors for multi-line graphs. [#60391](https://github.com/ClickHouse/ClickHouse/pull/60391) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* The Advanced dashboard now has controls always visible on scrolling. This allows you to add a new chart without scrolling up. [#60692](https://github.com/ClickHouse/ClickHouse/pull/60692) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* While running the `MODIFY COLUMN` query for materialized views, check the inner table's structure to ensure every column exists. [#47427](https://github.com/ClickHouse/ClickHouse/pull/47427) ([sunny](https://github.com/sunny19930321)).
* String types and Enums can be used in the same context, such as: arrays, UNION queries, conditional expressions. This closes [#60726](https://github.com/ClickHouse/ClickHouse/issues/60726). [#60727](https://github.com/ClickHouse/ClickHouse/pull/60727) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Allow declaring Enums in the structure of external data for query processing (this is an immediate temporary table that you can provide for your query). [#57857](https://github.com/ClickHouse/ClickHouse/pull/57857) ([Duc Canh Le](https://github.com/canhld94)).
* Consider lightweight deleted rows when selecting parts to merge, so the disk size of the resulting part will be estimated better. [#58223](https://github.com/ClickHouse/ClickHouse/pull/58223) ([Zhuo Qiu](https://github.com/jewelzqiu)).
* Added comments for columns for more system tables. Continuation of https://github.com/ClickHouse/ClickHouse/pull/58356. [#59016](https://github.com/ClickHouse/ClickHouse/pull/59016) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)).
* Now we can use virtual columns in PREWHERE. It's worthwhile for non-const virtual columns like `_part_offset`. [#59033](https://github.com/ClickHouse/ClickHouse/pull/59033) ([Amos Bird](https://github.com/amosbird)). Improved overall usability of virtual columns. Now it is allowed to use virtual columns in `PREWHERE` (it's worthwhile for non-const virtual columns like `_part_offset`). Now a builtin documentation is available for virtual columns as a comment of column in `DESCRIBE` query with enabled setting `describe_include_virtual_columns`. [#60205](https://github.com/ClickHouse/ClickHouse/pull/60205) ([Anton Popov](https://github.com/CurtizJ)).
* Instead using a constant key, now object storage generates key for determining remove objects capability. [#59495](https://github.com/ClickHouse/ClickHouse/pull/59495) ([Sema Checherinda](https://github.com/CheSema)).
* Allow "local" as object storage type instead of "local_blob_storage". [#60165](https://github.com/ClickHouse/ClickHouse/pull/60165) ([Kseniia Sumarokova](https://github.com/kssenii)).
* Parallel flush of pending INSERT blocks of Distributed engine on `DETACH`/server shutdown and `SYSTEM FLUSH DISTRIBUTED` (Parallelism will work only if you have multi-disk policy for a table (like everything in the Distributed engine right now)). [#60225](https://github.com/ClickHouse/ClickHouse/pull/60225) ([Azat Khuzhin](https://github.com/azat)).
* Add a setting to force read-through cache for merges. [#60308](https://github.com/ClickHouse/ClickHouse/pull/60308) ([Kseniia Sumarokova](https://github.com/kssenii)).
* An improvement for the MySQL compatibility protocol. The issue [#57598](https://github.com/ClickHouse/ClickHouse/issues/57598) mentions a variant behaviour regarding transaction handling. An issued COMMIT/ROLLBACK when no transaction is active is reported as an error contrary to MySQL behaviour. [#60338](https://github.com/ClickHouse/ClickHouse/pull/60338) ([PapaToemmsn](https://github.com/PapaToemmsn)).
* Function `substring` now has a new alias `byteSlice`. [#60494](https://github.com/ClickHouse/ClickHouse/pull/60494) ([Robert Schulze](https://github.com/rschu1ze)).
* Renamed server setting `dns_cache_max_size` to `dns_cache_max_entries` to reduce ambiguity. [#60500](https://github.com/ClickHouse/ClickHouse/pull/60500) ([Kirill Nikiforov](https://github.com/allmazz)).
* `SHOW INDEX | INDEXES | INDICES | KEYS` no longer sorts by the primary key columns (which was unintuitive). [#60514](https://github.com/ClickHouse/ClickHouse/pull/60514) ([Robert Schulze](https://github.com/rschu1ze)).
* Keeper improvement: abort during startup if an invalid snapshot is detected to avoid data loss. [#60537](https://github.com/ClickHouse/ClickHouse/pull/60537) ([Antonio Andelic](https://github.com/antonio2368)).
* Update tzdata to 2024a. [#60768](https://github.com/ClickHouse/ClickHouse/pull/60768) ([Raúl Marín](https://github.com/Algunenano)).
* Keeper improvement: support `leadership_expiry_ms` in Keeper's settings. [#60806](https://github.com/ClickHouse/ClickHouse/pull/60806) ([Brokenice0415](https://github.com/Brokenice0415)).
* Always infer exponential numbers in JSON formats regardless of the setting `input_format_try_infer_exponent_floats`. Add setting `input_format_json_use_string_type_for_ambiguous_paths_in_named_tuples_inference_from_objects` that allows to use String type for ambiguous paths instead of an exception during named Tuples inference from JSON objects. [#60808](https://github.com/ClickHouse/ClickHouse/pull/60808) ([Kruglov Pavel](https://github.com/Avogar)).
* Add support for `START TRANSACTION` syntax typically used in MySQL syntax, resolving https://github.com/ClickHouse/ClickHouse/discussions/60865. [#60886](https://github.com/ClickHouse/ClickHouse/pull/60886) ([Zach Naimon](https://github.com/ArctypeZach)).
* Add a flag for the full-sorting merge join algorithm to treat null as biggest/smallest. So the behavior can be compitable with other SQL systems, like Apache Spark. [#60896](https://github.com/ClickHouse/ClickHouse/pull/60896) ([loudongfeng](https://github.com/loudongfeng)).
* Support detect output format by file exctension in `clickhouse-client` and `clickhouse-local`. [#61036](https://github.com/ClickHouse/ClickHouse/pull/61036) ([豪肥肥](https://github.com/HowePa)).
* Update memory limit in runtime when Linux's CGroups value changed. [#61049](https://github.com/ClickHouse/ClickHouse/pull/61049) ([Han Fei](https://github.com/hanfei1991)).
* Add the function `toUInt128OrZero`, which was missed by mistake (the mistake is related to https://github.com/ClickHouse/ClickHouse/pull/945). The compatibility aliases `FROM_UNIXTIME` and `DATE_FORMAT` (they are not ClickHouse-native and only exist for MySQL compatibility) have been made case insensitive, as expected for SQL-compatibility aliases. [#61114](https://github.com/ClickHouse/ClickHouse/pull/61114) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Improvements for the access checks, allowing to revoke of unpossessed rights in case the target user doesn't have the revoking grants either. Example: `GRANT SELECT ON *.* TO user1; REVOKE SELECT ON system.* FROM user1;`. [#61115](https://github.com/ClickHouse/ClickHouse/pull/61115) ([pufit](https://github.com/pufit)).
* Fix `has()` function with `Nullable` column (fixes [#60214](https://github.com/ClickHouse/ClickHouse/issues/60214)). [#61249](https://github.com/ClickHouse/ClickHouse/pull/61249) ([Mikhail Koviazin](https://github.com/mkmkme)).
* Now it's possible to specify the attribute `merge="true"` in config substitutions for subtrees `<include from_zk="/path" merge="true">`. In case this attribute specified, clickhouse will merge subtree with existing configuration, otherwise default behavior is append new content to configuration. [#61299](https://github.com/ClickHouse/ClickHouse/pull/61299) ([alesapin](https://github.com/alesapin)).
* Add async metrics for virtual memory mappings: `VMMaxMapCount` & `VMNumMaps`. Closes [#60662](https://github.com/ClickHouse/ClickHouse/issues/60662). [#61354](https://github.com/ClickHouse/ClickHouse/pull/61354) ([Tuan Pham Anh](https://github.com/tuanpavn)).
* Use `temporary_files_codec` setting in all places where we create temporary data, for example external memory sorting and external memory GROUP BY. Before it worked only in `partial_merge` JOIN algorithm. [#61456](https://github.com/ClickHouse/ClickHouse/pull/61456) ([Maksim Kita](https://github.com/kitaisreal)).
* Add a new setting `max_parser_backtracks` which allows to limit the complexity of query parsing. [#61502](https://github.com/ClickHouse/ClickHouse/pull/61502) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Less contention during dynamic resize of the filesystem cache. [#61524](https://github.com/ClickHouse/ClickHouse/pull/61524) ([Kseniia Sumarokova](https://github.com/kssenii)).
* Disallow sharded mode of StorageS3 queue, because it will be rewritten. [#61537](https://github.com/ClickHouse/ClickHouse/pull/61537) ([Kseniia Sumarokova](https://github.com/kssenii)).
* Fixed typo: from `use_leagcy_max_level` to `use_legacy_max_level`. [#61545](https://github.com/ClickHouse/ClickHouse/pull/61545) ([William Schoeffel](https://github.com/wiledusc)).
* Remove some duplicate entries in `system.blob_storage_log`. [#61622](https://github.com/ClickHouse/ClickHouse/pull/61622) ([YenchangChan](https://github.com/YenchangChan)).
* Added `current_user` function as a compatibility alias for MySQL. [#61770](https://github.com/ClickHouse/ClickHouse/pull/61770) ([Yarik Briukhovetskyi](https://github.com/yariks5s)).
* Fix inconsistent floating point aggregate function states in mixed x86-64 / ARM clusters [#60610](https://github.com/ClickHouse/ClickHouse/pull/60610) ([Harry Lee](https://github.com/HarryLeeIBM)).
#### Build/Testing/Packaging Improvement
* The real-time query profiler now works on AArch64. In previous versions, it worked only when a program didn't spend time inside a syscall. [#60807](https://github.com/ClickHouse/ClickHouse/pull/60807) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* ClickHouse version has been added to docker labels. Closes [#54224](https://github.com/ClickHouse/ClickHouse/issues/54224). [#60949](https://github.com/ClickHouse/ClickHouse/pull/60949) ([Nikolay Monkov](https://github.com/nikmonkov)).
* Upgrade `prqlc` to 0.11.3. [#60616](https://github.com/ClickHouse/ClickHouse/pull/60616) ([Maximilian Roos](https://github.com/max-sixty)).
* Add generic query text fuzzer in `clickhouse-local`. [#61508](https://github.com/ClickHouse/ClickHouse/pull/61508) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
#### Bug Fix (user-visible misbehavior in an official stable release)
* Fix finished_mutations_to_keep=0 for MergeTree (as docs says 0 is to keep everything) [#60031](https://github.com/ClickHouse/ClickHouse/pull/60031) ([Azat Khuzhin](https://github.com/azat)).
* Something was wrong with the FINAL optimization, here is how the author describes it: "PartsSplitter invalid ranges for the same part". [#60041](https://github.com/ClickHouse/ClickHouse/pull/60041) ([Maksim Kita](https://github.com/kitaisreal)).
* Something was wrong with Apache Hive, which is experimental and not supported. [#60262](https://github.com/ClickHouse/ClickHouse/pull/60262) ([shanfengp](https://github.com/Aed-p)).
* An improvement for experimental parallel replicas: force reanalysis if parallel replicas changed [#60362](https://github.com/ClickHouse/ClickHouse/pull/60362) ([Raúl Marín](https://github.com/Algunenano)).
* Fix usage of plain metadata type with new disks configuration option [#60396](https://github.com/ClickHouse/ClickHouse/pull/60396) ([Kseniia Sumarokova](https://github.com/kssenii)).
* Don't allow to set max_parallel_replicas to 0 as it doesn't make sense [#60430](https://github.com/ClickHouse/ClickHouse/pull/60430) ([Kruglov Pavel](https://github.com/Avogar)).
* Try to fix logical error 'Cannot capture column because it has incompatible type' in mapContainsKeyLike [#60451](https://github.com/ClickHouse/ClickHouse/pull/60451) ([Kruglov Pavel](https://github.com/Avogar)).
* Avoid calculation of scalar subqueries for CREATE TABLE. [#60464](https://github.com/ClickHouse/ClickHouse/pull/60464) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
* Fix deadlock in parallel parsing when lots of rows are skipped due to errors [#60516](https://github.com/ClickHouse/ClickHouse/pull/60516) ([Kruglov Pavel](https://github.com/Avogar)).
* Something was wrong with experimental KQL (Kusto) support: fix `max_query_size_for_kql_compound_operator`: [#60534](https://github.com/ClickHouse/ClickHouse/pull/60534) ([Yong Wang](https://github.com/kashwy)).
* Keeper fix: add timeouts when waiting for commit logs [#60544](https://github.com/ClickHouse/ClickHouse/pull/60544) ([Antonio Andelic](https://github.com/antonio2368)).
* Don't output number tips for date types [#60577](https://github.com/ClickHouse/ClickHouse/pull/60577) ([Raúl Marín](https://github.com/Algunenano)).
* Fix reading from MergeTree with non-deterministic functions in filter [#60586](https://github.com/ClickHouse/ClickHouse/pull/60586) ([Kruglov Pavel](https://github.com/Avogar)).
* Fix logical error on bad compatibility setting value type [#60596](https://github.com/ClickHouse/ClickHouse/pull/60596) ([Kruglov Pavel](https://github.com/Avogar)).
* fix(prql): Robust panic handler [#60615](https://github.com/ClickHouse/ClickHouse/pull/60615) ([Maximilian Roos](https://github.com/max-sixty)).
* Fix `intDiv` for decimal and date arguments [#60672](https://github.com/ClickHouse/ClickHouse/pull/60672) ([Yarik Briukhovetskyi](https://github.com/yariks5s)).
* Fix: expand CTE in alter modify query [#60682](https://github.com/ClickHouse/ClickHouse/pull/60682) ([Yakov Olkhovskiy](https://github.com/yakov-olkhovskiy)).
* Fix system.parts for non-Atomic/Ordinary database engine (i.e. Memory) [#60689](https://github.com/ClickHouse/ClickHouse/pull/60689) ([Azat Khuzhin](https://github.com/azat)).
* Fix "Invalid storage definition in metadata file" for parameterized views [#60708](https://github.com/ClickHouse/ClickHouse/pull/60708) ([Azat Khuzhin](https://github.com/azat)).
* Fix buffer overflow in CompressionCodecMultiple [#60731](https://github.com/ClickHouse/ClickHouse/pull/60731) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Remove nonsense from SQL/JSON [#60738](https://github.com/ClickHouse/ClickHouse/pull/60738) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Remove wrong assertion in aggregate function quantileGK [#60740](https://github.com/ClickHouse/ClickHouse/pull/60740) ([李扬](https://github.com/taiyang-li)).
* Fix insert-select + insert_deduplication_token bug by setting streams to 1 [#60745](https://github.com/ClickHouse/ClickHouse/pull/60745) ([Jordi Villar](https://github.com/jrdi)).
* Prevent setting custom metadata headers on unsupported multipart upload operations [#60748](https://github.com/ClickHouse/ClickHouse/pull/60748) ([Francisco J. Jurado Moreno](https://github.com/Beetelbrox)).
* Fix toStartOfInterval [#60763](https://github.com/ClickHouse/ClickHouse/pull/60763) ([Andrey Zvonov](https://github.com/zvonand)).
* Fix crash in arrayEnumerateRanked [#60764](https://github.com/ClickHouse/ClickHouse/pull/60764) ([Raúl Marín](https://github.com/Algunenano)).
* Fix crash when using input() in INSERT SELECT JOIN [#60765](https://github.com/ClickHouse/ClickHouse/pull/60765) ([Kruglov Pavel](https://github.com/Avogar)).
* Fix crash with different allow_experimental_analyzer value in subqueries [#60770](https://github.com/ClickHouse/ClickHouse/pull/60770) ([Dmitry Novik](https://github.com/novikd)).
* Remove recursion when reading from S3 [#60849](https://github.com/ClickHouse/ClickHouse/pull/60849) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix possible stuck on error in HashedDictionaryParallelLoader [#60926](https://github.com/ClickHouse/ClickHouse/pull/60926) ([vdimir](https://github.com/vdimir)).
* Fix async RESTORE with Replicated database [#60934](https://github.com/ClickHouse/ClickHouse/pull/60934) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix deadlock in async inserts to `Log` tables via native protocol [#61055](https://github.com/ClickHouse/ClickHouse/pull/61055) ([Anton Popov](https://github.com/CurtizJ)).
* Fix lazy execution of default argument in dictGetOrDefault for RangeHashedDictionary [#61196](https://github.com/ClickHouse/ClickHouse/pull/61196) ([Kruglov Pavel](https://github.com/Avogar)).
* Fix multiple bugs in groupArraySorted [#61203](https://github.com/ClickHouse/ClickHouse/pull/61203) ([Raúl Marín](https://github.com/Algunenano)).
* Fix Keeper reconfig for standalone binary [#61233](https://github.com/ClickHouse/ClickHouse/pull/61233) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix usage of session_token in S3 engine [#61234](https://github.com/ClickHouse/ClickHouse/pull/61234) ([Kruglov Pavel](https://github.com/Avogar)).
* Fix possible incorrect result of aggregate function `uniqExact` [#61257](https://github.com/ClickHouse/ClickHouse/pull/61257) ([Anton Popov](https://github.com/CurtizJ)).
* Fix bugs in show database [#61269](https://github.com/ClickHouse/ClickHouse/pull/61269) ([Raúl Marín](https://github.com/Algunenano)).
* Fix logical error in RabbitMQ storage with MATERIALIZED columns [#61320](https://github.com/ClickHouse/ClickHouse/pull/61320) ([vdimir](https://github.com/vdimir)).
* Fix CREATE OR REPLACE DICTIONARY [#61356](https://github.com/ClickHouse/ClickHouse/pull/61356) ([Vitaly Baranov](https://github.com/vitlibar)).
* Fix ATTACH query with external ON CLUSTER [#61365](https://github.com/ClickHouse/ClickHouse/pull/61365) ([Nikolay Degterinsky](https://github.com/evillique)).
* Fix consecutive keys optimization for nullable keys [#61393](https://github.com/ClickHouse/ClickHouse/pull/61393) ([Anton Popov](https://github.com/CurtizJ)).
* fix issue of actions dag split [#61458](https://github.com/ClickHouse/ClickHouse/pull/61458) ([Raúl Marín](https://github.com/Algunenano)).
* Fix finishing a failed RESTORE [#61466](https://github.com/ClickHouse/ClickHouse/pull/61466) ([Vitaly Baranov](https://github.com/vitlibar)).
* Disable async_insert_use_adaptive_busy_timeout correctly with compatibility settings [#61468](https://github.com/ClickHouse/ClickHouse/pull/61468) ([Raúl Marín](https://github.com/Algunenano)).
* Allow queuing in restore pool [#61475](https://github.com/ClickHouse/ClickHouse/pull/61475) ([Nikita Taranov](https://github.com/nickitat)).
* Fix an inconsistency when reading system.parts using UUID. [#61479](https://github.com/ClickHouse/ClickHouse/pull/61479) ([Dan Wu](https://github.com/wudanzy)).
* Fix ALTER QUERY MODIFY SQL SECURITY [#61480](https://github.com/ClickHouse/ClickHouse/pull/61480) ([pufit](https://github.com/pufit)).
* Fix crash in window view [#61526](https://github.com/ClickHouse/ClickHouse/pull/61526) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Fix `repeat` with non native integers [#61527](https://github.com/ClickHouse/ClickHouse/pull/61527) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix client's `-s` argument [#61530](https://github.com/ClickHouse/ClickHouse/pull/61530) ([Mikhail f. Shiryaev](https://github.com/Felixoid)).
* Fix crash in arrayPartialReverseSort [#61539](https://github.com/ClickHouse/ClickHouse/pull/61539) ([Raúl Marín](https://github.com/Algunenano)).
* Fix string search with const position [#61547](https://github.com/ClickHouse/ClickHouse/pull/61547) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix addDays cause an error when used DateTime64 [#61561](https://github.com/ClickHouse/ClickHouse/pull/61561) ([Shuai li](https://github.com/loneylee)).
* Disallow LowCardinality input type for JSONExtract [#61617](https://github.com/ClickHouse/ClickHouse/pull/61617) ([Julia Kartseva](https://github.com/jkartseva)).
* Fix `system.part_log` for async insert with deduplication [#61620](https://github.com/ClickHouse/ClickHouse/pull/61620) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix a `Non-ready set` exception for system.parts. [#61666](https://github.com/ClickHouse/ClickHouse/pull/61666) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
* Fix actual_part_name for REPLACE_RANGE (`Entry actual part isn't empty yet`) [#61675](https://github.com/ClickHouse/ClickHouse/pull/61675) ([Alexander Tokmakov](https://github.com/tavplubix)).
* Fix a sanitizer report in `multiSearchAllPositionsCaseInsensitiveUTF8` for incorrect UTF-8 [#61749](https://github.com/ClickHouse/ClickHouse/pull/61749) ([pufit](https://github.com/pufit)).
* Fix an observation that the RANGE frame is not supported for Nullable columns. [#61766](https://github.com/ClickHouse/ClickHouse/pull/61766) ([YuanLiu](https://github.com/ditgittube)).
### <a id="242"></a> ClickHouse release 24.2, 2024-02-29
#### Backward Incompatible Change

View File

@ -28,7 +28,6 @@ curl https://clickhouse.com/ | sh
* [Slack](https://clickhouse.com/slack) and [Telegram](https://telegram.me/clickhouse_en) allow chatting with ClickHouse users in real-time.
* [Blog](https://clickhouse.com/blog/) contains various ClickHouse-related articles, as well as announcements and reports about events.
* [Code Browser (github.dev)](https://github.dev/ClickHouse/ClickHouse) with syntax highlighting, powered by github.dev.
* [Static Analysis (SonarCloud)](https://sonarcloud.io/project/issues?resolved=false&id=ClickHouse_ClickHouse) proposes C++ quality improvements.
* [Contacts](https://clickhouse.com/company/contact) can help to get your questions answered if there are any.
## Monthly Release & Community Call

View File

@ -153,6 +153,26 @@ Upon successful build you get an executable file `ClickHouse/<build_dir>/program
ls -l programs/clickhouse
### Advanced Building Process {#advanced-building-process}
#### Minimal Build {#minimal-build}
If you are not interested in functionality provided by third-party libraries, you can further speed up the build using `cmake` options
```
cmake -DENABLE_LIBRARIES=OFF
```
In case of problems with any of the development options, you are on your own!
#### Rust support {#rust-support}
Rust requires internet connection, in case you don't have it, you can disable Rust support:
```
cmake -DENABLE_RUST=OFF
```
## Running the Built Executable of ClickHouse {#running-the-built-executable-of-clickhouse}
To run the server under the current user you need to navigate to `ClickHouse/programs/server/` (located outside of `build`) and run:
@ -250,10 +270,3 @@ Most probably some of the builds will fail at first times. This is due to the fa
You can use GitHub integrated code browser [here](https://github.dev/ClickHouse/ClickHouse).
Also, you can browse sources on [GitHub](https://github.com/ClickHouse/ClickHouse) as usual.
If you are not interested in functionality provided by third-party libraries, you can further speed up the build using `cmake` options
```
-DENABLE_LIBRARIES=0
```
In case of problems with any of the development options, you are on your own!

View File

@ -867,3 +867,31 @@ Default value: `Never`
Persists virtual column `_block_number` on merges.
Default value: false.
## exclude_deleted_rows_for_part_size_in_merge {#exclude_deleted_rows_for_part_size_in_merge}
If enabled, estimated actual size of data parts (i.e., excluding those rows that have been deleted through `DELETE FROM`) will be used when selecting parts to merge. Note that this behavior is only triggered for data parts affected by `DELETE FROM` executed after this setting is enabled.
Possible values:
- true, false
Default value: false
**See Also**
- [load_existing_rows_count_for_old_parts](#load_existing_rows_count_for_old_parts) setting
## load_existing_rows_count_for_old_parts {#load_existing_rows_count_for_old_parts}
If enabled along with [exclude_deleted_rows_for_part_size_in_merge](#exclude_deleted_rows_for_part_size_in_merge), deleted rows count for existing data parts will be calculated during table starting up. Note that it may slow down start up table loading.
Possible values:
- true, false
Default value: false
**See Also**
- [exclude_deleted_rows_for_part_size_in_merge](#exclude_deleted_rows_for_part_size_in_merge) setting

View File

@ -3132,3 +3132,17 @@ Result:
│ (616.2931945826209,108.8825,115.6175) │
└───────────────────────────────────────┘
```
## getClientHTTPHeader
Get the value of an HTTP header.
If there is no such header or the current request is not performed via the HTTP interface, the function returns an empty string.
Certain HTTP headers (e.g., `Authentication` and `X-ClickHouse-*`) are restricted.
The function requires the setting `allow_get_client_http_header` to be enabled.
The setting is not enabled by default for security reasons, because some headers, such as `Cookie`, could contain sensitive info.
HTTP headers are case sensitive for this function.
If the function is used in the context of a distributed query, it returns non-empty result only on the initiator node.

View File

@ -180,10 +180,16 @@ SYSTEM STOP DISTRIBUTED SENDS [db.]<distributed_table_name> [ON CLUSTER cluster_
Forces ClickHouse to send data to cluster nodes synchronously. If any nodes are unavailable, ClickHouse throws an exception and stops query execution. You can retry the query until it succeeds, which will happen when all nodes are back online.
You can also override some settings via `SETTINGS` clause, this can be useful to avoid some temporary limitations, like `max_concurrent_queries_for_all_users` or `max_memory_usage`.
``` sql
SYSTEM FLUSH DISTRIBUTED [db.]<distributed_table_name> [ON CLUSTER cluster_name]
SYSTEM FLUSH DISTRIBUTED [db.]<distributed_table_name> [ON CLUSTER cluster_name] [SETTINGS ...]
```
:::note
Each pending block is stored in disk with settings from the initial INSERT query, so that is why sometimes you may want to override settings.
:::
### START DISTRIBUTED SENDS
Enables background data distribution when inserting data into distributed tables.

View File

@ -127,7 +127,7 @@ See the [deployment](docs/en/deployment-guides/terminology.md) documentation for
#### Verify that experimental transactions are enabled
Issue a `BEGIN TRANSACTION` followed by a `ROLLBACK` to verify that experimental transactions are enabled, and that ClickHouse Keeper is enabled as it is used to track transactions.
Issue a `BEGIN TRANSACTION` or `START TRANSACTION` followed by a `ROLLBACK` to verify that experimental transactions are enabled, and that ClickHouse Keeper is enabled as it is used to track transactions.
```sql
BEGIN TRANSACTION

View File

@ -36,7 +36,7 @@ if [ "$1" = configure ] || [ -n "$not_deb_os" ]; then
fi
/bin/systemctl daemon-reload
/bin/systemctl enable --now clickhouse-server
/bin/systemctl enable clickhouse-server
else
# If you downgrading to version older than 1.1.54336 run: systemctl disable clickhouse-server
if [ -x "/etc/init.d/clickhouse-server" ]; then

View File

@ -0,0 +1,73 @@
#include <Analyzer/ColumnNode.h>
#include <Analyzer/ConstantNode.h>
#include <Analyzer/FunctionNode.h>
#include <Analyzer/InDepthQueryTreeVisitor.h>
#include <Analyzer/Passes/ConvertInToEqualPass.h>
#include <Functions/equals.h>
#include <Functions/notEquals.h>
namespace DB
{
class ConvertInToEqualPassVisitor : public InDepthQueryTreeVisitorWithContext<ConvertInToEqualPassVisitor>
{
public:
using Base = InDepthQueryTreeVisitorWithContext<ConvertInToEqualPassVisitor>;
using Base::Base;
void enterImpl(QueryTreeNodePtr & node)
{
static const std::unordered_map<String, String> MAPPING = {
{"in", "equals"},
{"notIn", "notEquals"}
};
auto * func_node = node->as<FunctionNode>();
if (!func_node
|| !MAPPING.contains(func_node->getFunctionName())
|| func_node->getArguments().getNodes().size() != 2)
return ;
auto args = func_node->getArguments().getNodes();
auto * column_node = args[0]->as<ColumnNode>();
auto * constant_node = args[1]->as<ConstantNode>();
if (!column_node || !constant_node)
return ;
// IN multiple values is not supported
if (constant_node->getValue().getType() == Field::Types::Which::Tuple
|| constant_node->getValue().getType() == Field::Types::Which::Array)
return ;
// x IN null not equivalent to x = null
if (constant_node->getValue().isNull())
return ;
auto result_func_name = MAPPING.at(func_node->getFunctionName());
auto equal = std::make_shared<FunctionNode>(result_func_name);
QueryTreeNodes arguments{column_node->clone(), constant_node->clone()};
equal->getArguments().getNodes() = std::move(arguments);
FunctionOverloadResolverPtr resolver;
bool decimal_check_overflow = getContext()->getSettingsRef().decimal_check_overflow;
if (result_func_name == "equals")
{
resolver = createInternalFunctionEqualOverloadResolver(decimal_check_overflow);
}
else
{
resolver = createInternalFunctionNotEqualOverloadResolver(decimal_check_overflow);
}
try
{
equal->resolveAsFunction(resolver);
}
catch (...)
{
// When function resolver fails, we should not replace the function node
return;
}
node = equal;
}
};
void ConvertInToEqualPass::run(QueryTreeNodePtr & query_tree_node, ContextPtr context)
{
ConvertInToEqualPassVisitor visitor(std::move(context));
visitor.visit(query_tree_node);
}
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <Analyzer/IQueryTreePass.h>
namespace DB
{
/** Optimize `in` to `equals` if possible.
* 1. convert in single value to equal
* Example: SELECT * from test where x IN (1);
* Result: SELECT * from test where x = 1;
*
* 2. convert not in single value to notEqual
* Example: SELECT * from test where x NOT IN (1);
* Result: SELECT * from test where x != 1;
*
* If value is null or tuple, do not convert.
*/
class ConvertInToEqualPass final : public IQueryTreePass
{
public:
String getName() override { return "ConvertInToEqualPass"; }
String getDescription() override { return "Convert in to equal"; }
void run(QueryTreeNodePtr & query_tree_node, ContextPtr context) override;
};
}

View File

@ -28,6 +28,7 @@
#include <Analyzer/Passes/MultiIfToIfPass.h>
#include <Analyzer/Passes/IfConstantConditionPass.h>
#include <Analyzer/Passes/IfChainToMultiIfPass.h>
#include <Analyzer/Passes/ConvertInToEqualPass.h>
#include <Analyzer/Passes/OrderByTupleEliminationPass.h>
#include <Analyzer/Passes/NormalizeCountVariantsPass.h>
#include <Analyzer/Passes/AggregateFunctionsArithmericOperationsPass.h>
@ -263,6 +264,7 @@ void addQueryTreePasses(QueryTreePassManager & manager, bool only_analyze)
manager.addPass(std::make_unique<SumIfToCountIfPass>());
manager.addPass(std::make_unique<RewriteArrayExistsToHasPass>());
manager.addPass(std::make_unique<NormalizeCountVariantsPass>());
manager.addPass(std::make_unique<ConvertInToEqualPass>());
/// should before AggregateFunctionsArithmericOperationsPass
manager.addPass(std::make_unique<AggregateFunctionOfGroupByKeysPass>());

View File

@ -276,10 +276,9 @@ std::unique_ptr<WriteBuffer> BackupWriterAzureBlobStorage::writeFile(const Strin
return std::make_unique<WriteBufferFromAzureBlobStorage>(
client,
key,
settings->max_single_part_upload_size,
settings->max_unexpected_write_error_retries,
DBMS_DEFAULT_BUFFER_SIZE,
write_settings);
write_settings,
settings);
}
void BackupWriterAzureBlobStorage::removeFile(const String & file_name)

View File

@ -2,6 +2,7 @@
#include <limits>
#include <optional>
#include <magic_enum.hpp>
#include <fmt/format.h>
#include <base/defines.h>
#include <base/scope_guard.h>
@ -201,9 +202,10 @@ void LoadTask::remove()
}
}
AsyncLoader::AsyncLoader(std::vector<PoolInitializer> pool_initializers, bool log_failures_, bool log_progress_)
AsyncLoader::AsyncLoader(std::vector<PoolInitializer> pool_initializers, bool log_failures_, bool log_progress_, bool log_events_)
: log_failures(log_failures_)
, log_progress(log_progress_)
, log_events(log_events_)
, log(getLogger("AsyncLoader"))
{
pools.reserve(pool_initializers.size());
@ -332,6 +334,8 @@ void AsyncLoader::schedule(const LoadJobSet & jobs_to_schedule)
ALLOW_ALLOCATIONS_IN_SCOPE;
scheduled_jobs.try_emplace(job);
job->scheduled(++last_job_id);
if (log_events)
LOG_DEBUG(log, "Schedule load job '{}' into {}", job->name, getPoolName(job->pool()));
});
}
@ -587,6 +591,14 @@ void AsyncLoader::finish(const LoadJobPtr & job, LoadStatus status, std::excepti
else if (status == LoadStatus::CANCELED)
job->canceled(reason);
if (log_events)
{
NOEXCEPT_SCOPE({
ALLOW_ALLOCATIONS_IN_SCOPE;
LOG_DEBUG(log, "Finish load job '{}' with status {}", job->name, magic_enum::enum_name(status));
});
}
Info & info = scheduled_jobs[job];
if (info.isReady())
{
@ -666,6 +678,14 @@ void AsyncLoader::prioritize(const LoadJobPtr & job, size_t new_pool_id, std::un
job->pool_id.store(new_pool_id);
if (log_events)
{
NOEXCEPT_SCOPE({
ALLOW_ALLOCATIONS_IN_SCOPE;
LOG_DEBUG(log, "Prioritize load job '{}': {} -> {}", job->name, old_pool.name, new_pool.name);
});
}
// Recurse into dependencies
for (const auto & dep : job->dependencies)
prioritize(dep, new_pool_id, lock);
@ -770,6 +790,9 @@ void AsyncLoader::wait(std::unique_lock<std::mutex> & job_lock, const LoadJobPtr
if (job->load_status != LoadStatus::PENDING) // Shortcut just to avoid incrementing ProfileEvents
return;
if (log_events)
LOG_DEBUG(log, "Wait load job '{}' in {}", job->name, getPoolName(job->pool_id));
if (job->on_waiters_increment)
job->on_waiters_increment(job);
@ -808,6 +831,20 @@ bool AsyncLoader::canWorkerLive(Pool & pool, std::unique_lock<std::mutex> &)
&& (!current_priority || *current_priority >= pool.priority);
}
void AsyncLoader::setCurrentPriority(std::unique_lock<std::mutex> &, std::optional<Priority> priority)
{
if (log_events && current_priority != priority)
{
NOEXCEPT_SCOPE({
ALLOW_ALLOCATIONS_IN_SCOPE;
LOG_DEBUG(log, "Change current priority: {} -> {}",
current_priority ? std::to_string(*current_priority) : "none",
priority ? std::to_string(*priority) : "none");
});
}
current_priority = priority;
}
void AsyncLoader::updateCurrentPriorityAndSpawn(std::unique_lock<std::mutex> & lock)
{
// Find current priority.
@ -818,7 +855,7 @@ void AsyncLoader::updateCurrentPriorityAndSpawn(std::unique_lock<std::mutex> & l
if (pool.isActive() && (!priority || *priority > pool.priority))
priority = pool.priority;
}
current_priority = priority;
setCurrentPriority(lock, priority);
// Spawn workers in all pools with current priority
for (Pool & pool : pools)
@ -828,12 +865,14 @@ void AsyncLoader::updateCurrentPriorityAndSpawn(std::unique_lock<std::mutex> & l
}
}
void AsyncLoader::spawn(Pool & pool, std::unique_lock<std::mutex> &)
void AsyncLoader::spawn(Pool & pool, std::unique_lock<std::mutex> & lock)
{
setCurrentPriority(lock, pool.priority); // canSpawnWorker() ensures this would not decrease current_priority
pool.workers++;
current_priority = pool.priority; // canSpawnWorker() ensures this would not decrease current_priority
NOEXCEPT_SCOPE({
ALLOW_ALLOCATIONS_IN_SCOPE;
if (log_events)
LOG_DEBUG(log, "Spawn loader worker #{} in {}", pool.workers, pool.name);
pool.thread_pool->scheduleOrThrowOnError([this, &pool] { worker(pool); });
});
}
@ -861,6 +900,13 @@ void AsyncLoader::worker(Pool & pool)
if (!canWorkerLive(pool, lock))
{
if (log_events)
{
NOEXCEPT_SCOPE({
ALLOW_ALLOCATIONS_IN_SCOPE;
LOG_DEBUG(log, "Stop worker in {}", pool.name);
});
}
if (--pool.workers == 0)
updateCurrentPriorityAndSpawn(lock); // It will spawn lower priority workers if needed
return;
@ -871,6 +917,14 @@ void AsyncLoader::worker(Pool & pool)
job = it->second;
pool.ready_queue.erase(it);
scheduled_jobs.find(job)->second.ready_seqno = 0; // This job is no longer in the ready queue
if (log_events)
{
NOEXCEPT_SCOPE({
ALLOW_ALLOCATIONS_IN_SCOPE;
LOG_DEBUG(log, "Execute load job '{}' in {}", job->name, pool.name);
});
}
}
ALLOW_ALLOCATIONS_IN_SCOPE;

View File

@ -390,7 +390,7 @@ private:
};
public:
AsyncLoader(std::vector<PoolInitializer> pool_initializers, bool log_failures_, bool log_progress_);
AsyncLoader(std::vector<PoolInitializer> pool_initializers, bool log_failures_, bool log_progress_, bool log_events_);
// WARNING: all tasks instances should be destructed before associated AsyncLoader.
~AsyncLoader();
@ -470,6 +470,7 @@ private:
void wait(std::unique_lock<std::mutex> & job_lock, const LoadJobPtr & job);
bool canSpawnWorker(Pool & pool, std::unique_lock<std::mutex> & lock);
bool canWorkerLive(Pool & pool, std::unique_lock<std::mutex> & lock);
void setCurrentPriority(std::unique_lock<std::mutex> & lock, std::optional<Priority> priority);
void updateCurrentPriorityAndSpawn(std::unique_lock<std::mutex> & lock);
void spawn(Pool & pool, std::unique_lock<std::mutex> & lock);
void worker(Pool & pool);
@ -478,6 +479,7 @@ private:
// Logging
const bool log_failures; // Worker should log all exceptions caught from job functions.
const bool log_progress; // Periodically log total progress
const bool log_events; // Log all important events: job start/end, waits, prioritizations
LoggerPtr log;
mutable std::mutex mutex; // Guards all the fields below.

View File

@ -1,22 +1,18 @@
#include "config.h"
#if USE_AWS_S3
#include <IO/WriteBufferFromS3.h>
#include "BufferAllocationPolicy.h"
#include <memory>
namespace
namespace DB
{
class FixedSizeBufferAllocationPolicy : public DB::WriteBufferFromS3::IBufferAllocationPolicy
class FixedSizeBufferAllocationPolicy : public BufferAllocationPolicy
{
const size_t buffer_size = 0;
size_t buffer_number = 0;
public:
explicit FixedSizeBufferAllocationPolicy(const DB::S3Settings::RequestSettings::PartUploadSettings & settings_)
: buffer_size(settings_.strict_upload_part_size)
explicit FixedSizeBufferAllocationPolicy(const BufferAllocationPolicy::Settings & settings_)
: buffer_size(settings_.strict_size)
{
chassert(buffer_size > 0);
}
@ -36,7 +32,7 @@ public:
};
class ExpBufferAllocationPolicy : public DB::WriteBufferFromS3::IBufferAllocationPolicy
class ExpBufferAllocationPolicy : public DB::BufferAllocationPolicy
{
const size_t first_size = 0;
const size_t second_size = 0;
@ -49,12 +45,12 @@ class ExpBufferAllocationPolicy : public DB::WriteBufferFromS3::IBufferAllocatio
size_t buffer_number = 0;
public:
explicit ExpBufferAllocationPolicy(const DB::S3Settings::RequestSettings::PartUploadSettings & settings_)
: first_size(std::max(settings_.max_single_part_upload_size, settings_.min_upload_part_size))
, second_size(settings_.min_upload_part_size)
, multiply_factor(settings_.upload_part_size_multiply_factor)
, multiply_threshold(settings_.upload_part_size_multiply_parts_count_threshold)
, max_size(settings_.max_upload_part_size)
explicit ExpBufferAllocationPolicy(const BufferAllocationPolicy::Settings & settings_)
: first_size(std::max(settings_.max_single_size, settings_.min_size))
, second_size(settings_.min_size)
, multiply_factor(settings_.multiply_factor)
, multiply_threshold(settings_.multiply_parts_count_threshold)
, max_size(settings_.max_size)
{
chassert(first_size > 0);
chassert(second_size > 0);
@ -92,16 +88,12 @@ public:
}
};
}
namespace DB
BufferAllocationPolicy::~BufferAllocationPolicy() = default;
BufferAllocationPolicyPtr BufferAllocationPolicy::create(BufferAllocationPolicy::Settings settings_)
{
WriteBufferFromS3::IBufferAllocationPolicy::~IBufferAllocationPolicy() = default;
WriteBufferFromS3::IBufferAllocationPolicyPtr WriteBufferFromS3::ChooseBufferPolicy(const S3Settings::RequestSettings::PartUploadSettings & settings_)
{
if (settings_.strict_upload_part_size > 0)
if (settings_.strict_size > 0)
return std::make_unique<FixedSizeBufferAllocationPolicy>(settings_);
else
return std::make_unique<ExpBufferAllocationPolicy>(settings_);
@ -109,4 +101,3 @@ WriteBufferFromS3::IBufferAllocationPolicyPtr WriteBufferFromS3::ChooseBufferPol
}
#endif

View File

@ -0,0 +1,39 @@
#pragma once
#include "config.h"
#include "logger_useful.h"
#include <list>
namespace DB
{
class BufferAllocationPolicy;
using BufferAllocationPolicyPtr = std::unique_ptr<BufferAllocationPolicy>;
/// Buffer number starts with 0
class BufferAllocationPolicy
{
public:
struct Settings
{
size_t strict_size = 0;
size_t min_size = 16 * 1024 * 1024;
size_t max_size = 5ULL * 1024 * 1024 * 1024;
size_t multiply_factor = 2;
size_t multiply_parts_count_threshold = 500;
size_t max_single_size = 32 * 1024 * 1024; /// Max size for a single buffer/block
};
virtual size_t getBufferNumber() const = 0;
virtual size_t getBufferSize() const = 0;
virtual void nextBuffer() = 0;
virtual ~BufferAllocationPolicy() = 0;
static BufferAllocationPolicyPtr create(Settings settings_);
};
}

View File

@ -1,8 +1,6 @@
#include "config.h"
#if USE_AWS_S3
#include <IO/WriteBufferFromS3TaskTracker.h>
#include "ThreadPoolTaskTracker.h"
namespace ProfileEvents
{
@ -12,19 +10,19 @@ namespace ProfileEvents
namespace DB
{
WriteBufferFromS3::TaskTracker::TaskTracker(ThreadPoolCallbackRunner<void> scheduler_, size_t max_tasks_inflight_, LogSeriesLimiterPtr limitedLog_)
TaskTracker::TaskTracker(ThreadPoolCallbackRunner<void> scheduler_, size_t max_tasks_inflight_, LogSeriesLimiterPtr limitedLog_)
: is_async(bool(scheduler_))
, scheduler(scheduler_ ? std::move(scheduler_) : syncRunner())
, max_tasks_inflight(max_tasks_inflight_)
, limitedLog(limitedLog_)
{}
WriteBufferFromS3::TaskTracker::~TaskTracker()
TaskTracker::~TaskTracker()
{
safeWaitAll();
}
ThreadPoolCallbackRunner<void> WriteBufferFromS3::TaskTracker::syncRunner()
ThreadPoolCallbackRunner<void> TaskTracker::syncRunner()
{
return [](Callback && callback, int64_t) mutable -> std::future<void>
{
@ -35,7 +33,7 @@ ThreadPoolCallbackRunner<void> WriteBufferFromS3::TaskTracker::syncRunner()
};
}
void WriteBufferFromS3::TaskTracker::waitAll()
void TaskTracker::waitAll()
{
/// Exceptions are propagated
for (auto & future : futures)
@ -48,7 +46,7 @@ void WriteBufferFromS3::TaskTracker::waitAll()
finished_futures.clear();
}
void WriteBufferFromS3::TaskTracker::safeWaitAll()
void TaskTracker::safeWaitAll()
{
for (auto & future : futures)
{
@ -71,7 +69,7 @@ void WriteBufferFromS3::TaskTracker::safeWaitAll()
finished_futures.clear();
}
void WriteBufferFromS3::TaskTracker::waitIfAny()
void TaskTracker::waitIfAny()
{
if (futures.empty())
return;
@ -99,7 +97,7 @@ void WriteBufferFromS3::TaskTracker::waitIfAny()
ProfileEvents::increment(ProfileEvents::WriteBufferFromS3WaitInflightLimitMicroseconds, watch.elapsedMicroseconds());
}
void WriteBufferFromS3::TaskTracker::add(Callback && func)
void TaskTracker::add(Callback && func)
{
/// All this fuzz is about 2 things. This is the most critical place of TaskTracker.
/// The first is not to fail insertion in the list `futures`.
@ -134,7 +132,7 @@ void WriteBufferFromS3::TaskTracker::add(Callback && func)
waitTilInflightShrink();
}
void WriteBufferFromS3::TaskTracker::waitTilInflightShrink()
void TaskTracker::waitTilInflightShrink()
{
if (!max_tasks_inflight)
return;
@ -166,11 +164,10 @@ void WriteBufferFromS3::TaskTracker::waitTilInflightShrink()
ProfileEvents::increment(ProfileEvents::WriteBufferFromS3WaitInflightLimitMicroseconds, watch.elapsedMicroseconds());
}
bool WriteBufferFromS3::TaskTracker::isAsync() const
bool TaskTracker::isAsync() const
{
return is_async;
}
}
#endif

View File

@ -1,20 +1,16 @@
#pragma once
#include "config.h"
#include "threadPoolCallbackRunner.h"
#include "IO/WriteBufferFromS3.h"
#if USE_AWS_S3
#include "WriteBufferFromS3.h"
#include <Common/logger_useful.h>
#include "logger_useful.h"
#include <list>
namespace DB
{
/// That class is used only in WriteBufferFromS3 for now.
/// Therefore it declared as a part of WriteBufferFromS3.
/// TaskTracker takes a Callback which is run by scheduler in some external shared ThreadPool.
/// TaskTracker brings the methods waitIfAny, waitAll/safeWaitAll
/// to help with coordination of the running tasks.
@ -22,7 +18,7 @@ namespace DB
/// Basic exception safety is provided. If exception occurred the object has to be destroyed.
/// No thread safety is provided. Use this object with no concurrency.
class WriteBufferFromS3::TaskTracker
class TaskTracker
{
public:
using Callback = std::function<void()>;
@ -68,5 +64,3 @@ private:
};
}
#endif

View File

@ -812,7 +812,7 @@ void ZooKeeper::receiveEvent()
RequestInfo request_info;
ZooKeeperResponsePtr response;
UInt64 elapsed_ms = 0;
UInt64 elapsed_microseconds = 0;
maybeInjectRecvFault();
@ -875,8 +875,8 @@ void ZooKeeper::receiveEvent()
CurrentMetrics::sub(CurrentMetrics::ZooKeeperRequest);
}
elapsed_ms = std::chrono::duration_cast<std::chrono::microseconds>(clock::now() - request_info.time).count();
ProfileEvents::increment(ProfileEvents::ZooKeeperWaitMicroseconds, elapsed_ms);
elapsed_microseconds = std::chrono::duration_cast<std::chrono::microseconds>(clock::now() - request_info.time).count();
ProfileEvents::increment(ProfileEvents::ZooKeeperWaitMicroseconds, elapsed_microseconds);
}
try
@ -935,7 +935,7 @@ void ZooKeeper::receiveEvent()
length, actual_length);
}
logOperationIfNeeded(request_info.request, response, /* finalize= */ false, elapsed_ms);
logOperationIfNeeded(request_info.request, response, /* finalize= */ false, elapsed_microseconds);
}
catch (...)
{
@ -954,7 +954,7 @@ void ZooKeeper::receiveEvent()
if (request_info.callback)
request_info.callback(*response);
logOperationIfNeeded(request_info.request, response, /* finalize= */ false, elapsed_ms);
logOperationIfNeeded(request_info.request, response, /* finalize= */ false, elapsed_microseconds);
}
catch (...)
{
@ -1048,14 +1048,14 @@ void ZooKeeper::finalize(bool error_send, bool error_receive, const String & rea
? Error::ZCONNECTIONLOSS
: Error::ZSESSIONEXPIRED;
response->xid = request_info.request->xid;
UInt64 elapsed_ms = std::chrono::duration_cast<std::chrono::microseconds>(clock::now() - request_info.time).count();
UInt64 elapsed_microseconds = std::chrono::duration_cast<std::chrono::microseconds>(clock::now() - request_info.time).count();
if (request_info.callback)
{
try
{
request_info.callback(*response);
logOperationIfNeeded(request_info.request, response, true, elapsed_ms);
logOperationIfNeeded(request_info.request, response, true, elapsed_microseconds);
}
catch (...)
{
@ -1115,8 +1115,8 @@ void ZooKeeper::finalize(bool error_send, bool error_receive, const String & rea
try
{
info.callback(*response);
UInt64 elapsed_ms = std::chrono::duration_cast<std::chrono::microseconds>(clock::now() - info.time).count();
logOperationIfNeeded(info.request, response, true, elapsed_ms);
UInt64 elapsed_microseconds = std::chrono::duration_cast<std::chrono::microseconds>(clock::now() - info.time).count();
logOperationIfNeeded(info.request, response, true, elapsed_microseconds);
}
catch (...)
{
@ -1498,7 +1498,7 @@ void ZooKeeper::setZooKeeperLog(std::shared_ptr<DB::ZooKeeperLog> zk_log_)
}
#ifdef ZOOKEEPER_LOG
void ZooKeeper::logOperationIfNeeded(const ZooKeeperRequestPtr & request, const ZooKeeperResponsePtr & response, bool finalize, UInt64 elapsed_ms)
void ZooKeeper::logOperationIfNeeded(const ZooKeeperRequestPtr & request, const ZooKeeperResponsePtr & response, bool finalize, UInt64 elapsed_microseconds)
{
auto maybe_zk_log = std::atomic_load(&zk_log);
if (!maybe_zk_log)
@ -1536,7 +1536,7 @@ void ZooKeeper::logOperationIfNeeded(const ZooKeeperRequestPtr & request, const
elem.event_time = event_time;
elem.address = socket_address;
elem.session_id = session_id;
elem.duration_ms = elapsed_ms;
elem.duration_microseconds = elapsed_microseconds;
if (request)
{
elem.thread_id = request->thread_id;

View File

@ -343,7 +343,7 @@ private:
void flushWriteBuffer();
ReadBuffer & getReadBuffer();
void logOperationIfNeeded(const ZooKeeperRequestPtr & request, const ZooKeeperResponsePtr & response = nullptr, bool finalize = false, UInt64 elapsed_ms = 0);
void logOperationIfNeeded(const ZooKeeperRequestPtr & request, const ZooKeeperResponsePtr & response = nullptr, bool finalize = false, UInt64 elapsed_microseconds = 0);
void initFeatureFlags();

View File

@ -50,7 +50,7 @@ struct AsyncLoaderTest
pcg64 rng{randomSeed()};
explicit AsyncLoaderTest(std::vector<Initializer> initializers)
: loader(getPoolInitializers(initializers), /* log_failures = */ false, /* log_progress = */ false)
: loader(getPoolInitializers(initializers), /* log_failures = */ false, /* log_progress = */ false, /* log_events = */ false)
{
loader.stop(); // All tests call `start()` manually to better control ordering
}

View File

@ -78,11 +78,17 @@ class IColumn;
M(UInt64, distributed_connections_pool_size, 1024, "Maximum number of connections with one remote server in the pool.", 0) \
M(UInt64, connections_with_failover_max_tries, 3, "The maximum number of attempts to connect to replicas.", 0) \
M(UInt64, s3_strict_upload_part_size, 0, "The exact size of part to upload during multipart upload to S3 (some implementations does not supports variable size parts).", 0) \
M(UInt64, azure_strict_upload_part_size, 0, "The exact size of part to upload during multipart upload to Azure blob storage.", 0) \
M(UInt64, s3_min_upload_part_size, 16*1024*1024, "The minimum size of part to upload during multipart upload to S3.", 0) \
M(UInt64, s3_max_upload_part_size, 5ull*1024*1024*1024, "The maximum size of part to upload during multipart upload to S3.", 0) \
M(UInt64, azure_min_upload_part_size, 16*1024*1024, "The minimum size of part to upload during multipart upload to Azure blob storage.", 0) \
M(UInt64, azure_max_upload_part_size, 5ull*1024*1024*1024, "The maximum size of part to upload during multipart upload to Azure blob storage.", 0) \
M(UInt64, s3_upload_part_size_multiply_factor, 2, "Multiply s3_min_upload_part_size by this factor each time s3_multiply_parts_count_threshold parts were uploaded from a single write to S3.", 0) \
M(UInt64, s3_upload_part_size_multiply_parts_count_threshold, 500, "Each time this number of parts was uploaded to S3, s3_min_upload_part_size is multiplied by s3_upload_part_size_multiply_factor.", 0) \
M(UInt64, s3_max_inflight_parts_for_one_file, 20, "The maximum number of a concurrent loaded parts in multipart upload request. 0 means unlimited. You ", 0) \
M(UInt64, azure_upload_part_size_multiply_factor, 2, "Multiply azure_min_upload_part_size by this factor each time azure_multiply_parts_count_threshold parts were uploaded from a single write to Azure blob storage.", 0) \
M(UInt64, azure_upload_part_size_multiply_parts_count_threshold, 500, "Each time this number of parts was uploaded to Azure blob storage, azure_min_upload_part_size is multiplied by azure_upload_part_size_multiply_factor.", 0) \
M(UInt64, s3_max_inflight_parts_for_one_file, 20, "The maximum number of a concurrent loaded parts in multipart upload request. 0 means unlimited.", 0) \
M(UInt64, azure_max_inflight_parts_for_one_file, 20, "The maximum number of a concurrent loaded parts in multipart upload request. 0 means unlimited.", 0) \
M(UInt64, s3_max_single_part_upload_size, 32*1024*1024, "The maximum size of object to upload using singlepart upload to S3.", 0) \
M(UInt64, azure_max_single_part_upload_size, 100*1024*1024, "The maximum size of object to upload using singlepart upload to Azure blob storage.", 0) \
M(UInt64, azure_max_single_part_copy_size, 256*1024*1024, "The maximum size of object to copy using single part copy to Azure blob storage.", 0) \
@ -862,6 +868,8 @@ class IColumn;
M(Bool, use_variant_as_common_type, false, "Use Variant as a result type for if/multiIf in case when there is no common type for arguments", 0) \
M(Bool, enable_order_by_all, true, "Enable sorting expression ORDER BY ALL.", 0) \
M(Bool, traverse_shadow_remote_data_paths, false, "Traverse shadow directory when query system.remote_data_paths", 0) \
M(Bool, geo_distance_returns_float64_on_float64_arguments, true, "If all four arguments to `geoDistance`, `greatCircleDistance`, `greatCircleAngle` functions are Float64, return Float64 and use double precision for internal calculations. In previous ClickHouse versions, the functions always returned Float32.", 0) \
M(Bool, allow_get_client_http_header, false, "Allow to use the function `getClientHTTPHeader` which lets to obtain a value of an the current HTTP request's header. It is not enabled by default for security reasons, because some headers, such as `Cookie`, could contain sensitive info. Note that the `X-ClickHouse-*` and `Authentication` headers are always restricted and cannot be obtained with this function.", 0) \
\
/** Experimental functions */ \
M(Bool, allow_experimental_materialized_postgresql_table, false, "Allows to use the MaterializedPostgreSQL table engine. Disabled by default, because this feature is experimental", 0) \
@ -1140,7 +1148,7 @@ class IColumn;
\
M(Bool, output_format_enable_streaming, false, "Enable streaming in output formats that support it.", 0) \
M(Bool, output_format_write_statistics, true, "Write statistics about read rows, bytes, time elapsed in suitable output formats.", 0) \
M(Bool, output_format_pretty_row_numbers, false, "Add row numbers before each row for pretty output format", 0) \
M(Bool, output_format_pretty_row_numbers, true, "Add row numbers before each row for pretty output format", 0) \
M(Bool, output_format_pretty_highlight_digit_groups, true, "If enabled and if output is a terminal, highlight every digit corresponding to the number of thousands, millions, etc. with underline.", 0) \
M(UInt64, output_format_pretty_single_large_number_tip_threshold, 1'000'000, "Print a readable number tip on the right side of the table if the block consists of a single number which exceeds this value (except 0)", 0) \
M(Bool, insert_distributed_one_random_shard, false, "If setting is enabled, inserting into distributed table will choose a random shard to write when there is no sharding key", 0) \

View File

@ -106,6 +106,8 @@ static std::map<ClickHouseVersion, SettingsChangesHistory::SettingsChanges> sett
{"keeper_retry_max_backoff_ms", 5000, 5000, "Max backoff timeout for general keeper operations"},
{"s3queue_allow_experimental_sharded_mode", false, false, "Enable experimental sharded mode of S3Queue table engine. It is experimental because it will be rewritten"},
{"merge_tree_read_split_ranges_into_intersecting_and_non_intersecting_injection_probability", 0.0, 0.0, "For testing of `PartsSplitter` - split read ranges into intersecting and non intersecting every time you read from MergeTree with the specified probability."},
{"allow_get_client_http_header", false, false, "Introduced a new function."},
{"output_format_pretty_row_numbers", false, true, "It is better for usability."},
{"output_format_pretty_max_value_width_apply_for_single_value", true, false, "Single values in Pretty formats won't be cut."},
{"output_format_parquet_string_as_string", false, true, "ClickHouse allows arbitrary binary data in the String data type, which is typically UTF-8. Parquet/ORC/Arrow Strings only support UTF-8. That's why you can choose which Arrow's data type to use for the ClickHouse String data type - String or Binary. While Binary would be more correct and compatible, using String by default will correspond to user expectations in most cases."},
{"output_format_orc_string_as_string", false, true, "ClickHouse allows arbitrary binary data in the String data type, which is typically UTF-8. Parquet/ORC/Arrow Strings only support UTF-8. That's why you can choose which Arrow's data type to use for the ClickHouse String data type - String or Binary. While Binary would be more correct and compatible, using String by default will correspond to user expectations in most cases."},
@ -113,6 +115,13 @@ static std::map<ClickHouseVersion, SettingsChangesHistory::SettingsChanges> sett
{"output_format_parquet_compression_method", "lz4", "zstd", "Parquet/ORC/Arrow support many compression methods, including lz4 and zstd. ClickHouse supports each and every compression method. Some inferior tools, such as 'duckdb', lack support for the faster `lz4` compression method, that's why we set zstd by default."},
{"output_format_orc_compression_method", "lz4", "zstd", "Parquet/ORC/Arrow support many compression methods, including lz4 and zstd. ClickHouse supports each and every compression method. Some inferior tools, such as 'duckdb', lack support for the faster `lz4` compression method, that's why we set zstd by default."},
{"output_format_pretty_highlight_digit_groups", false, true, "If enabled and if output is a terminal, highlight every digit corresponding to the number of thousands, millions, etc. with underline."},
{"geo_distance_returns_float64_on_float64_arguments", false, true, "Increase the default precision."},
{"azure_max_inflight_parts_for_one_file", 20, 20, "The maximum number of a concurrent loaded parts in multipart upload request. 0 means unlimited."},
{"azure_strict_upload_part_size", 0, 0, "The exact size of part to upload during multipart upload to Azure blob storage."},
{"azure_min_upload_part_size", 16*1024*1024, 16*1024*1024, "The minimum size of part to upload during multipart upload to Azure blob storage."},
{"azure_max_upload_part_size", 5ull*1024*1024*1024, 5ull*1024*1024*1024, "The maximum size of part to upload during multipart upload to Azure blob storage."},
{"azure_upload_part_size_multiply_factor", 2, 2, "Multiply azure_min_upload_part_size by this factor each time azure_multiply_parts_count_threshold parts were uploaded from a single write to Azure blob storage."},
{"azure_upload_part_size_multiply_parts_count_threshold", 500, 500, "Each time this number of parts was uploaded to Azure blob storage, azure_min_upload_part_size is multiplied by azure_upload_part_size_multiply_factor."},
}},
{"24.2", {{"allow_suspicious_variant_types", true, false, "Don't allow creating Variant type with suspicious variants by default"},
{"validate_experimental_and_suspicious_types_inside_nested_types", false, true, "Validate usage of experimental and suspicious types inside nested types"},

View File

@ -71,6 +71,17 @@ void applyMetadataChangesToCreateQuery(const ASTPtr & query, const StorageInMemo
query->replace(ast_create_query.refresh_strategy, metadata.refresh);
}
if (metadata.sql_security_type)
{
auto new_sql_security = std::make_shared<ASTSQLSecurity>();
new_sql_security->type = metadata.sql_security_type;
if (metadata.definer)
new_sql_security->definer = std::make_shared<ASTUserNameWithHost>(*metadata.definer);
ast_create_query.sql_security = std::move(new_sql_security);
}
/// MaterializedView, Dictionary are types of CREATE query without storage.
if (ast_create_query.storage)
{

View File

@ -8,7 +8,7 @@
#include <Common/Throttler.h>
#include <base/sleep.h>
#include <Common/ProfileEvents.h>
#include <IO/SeekableReadBuffer.h>
namespace ProfileEvents
{
@ -27,7 +27,6 @@ namespace ErrorCodes
extern const int LOGICAL_ERROR;
}
ReadBufferFromAzureBlobStorage::ReadBufferFromAzureBlobStorage(
std::shared_ptr<const Azure::Storage::Blobs::BlobContainerClient> blob_container_client_,
const String & path_,
@ -56,7 +55,6 @@ ReadBufferFromAzureBlobStorage::ReadBufferFromAzureBlobStorage(
}
}
void ReadBufferFromAzureBlobStorage::setReadUntilEnd()
{
if (read_until_position)
@ -105,7 +103,7 @@ bool ReadBufferFromAzureBlobStorage::nextImpl()
auto handle_exception = [&, this](const auto & e, size_t i)
{
LOG_INFO(log, "Exception caught during Azure Read for file {} at attempt {}/{}: {}", path, i + 1, max_single_read_retries, e.Message);
LOG_DEBUG(log, "Exception caught during Azure Read for file {} at attempt {}/{}: {}", path, i + 1, max_single_read_retries, e.Message);
if (i + 1 == max_single_read_retries)
throw;
@ -139,7 +137,6 @@ bool ReadBufferFromAzureBlobStorage::nextImpl()
return true;
}
off_t ReadBufferFromAzureBlobStorage::seek(off_t offset_, int whence)
{
if (offset_ == getPosition() && whence == SEEK_SET)
@ -193,13 +190,11 @@ off_t ReadBufferFromAzureBlobStorage::seek(off_t offset_, int whence)
return offset;
}
off_t ReadBufferFromAzureBlobStorage::getPosition()
{
return offset - available();
}
void ReadBufferFromAzureBlobStorage::initialize()
{
if (initialized)
@ -220,7 +215,7 @@ void ReadBufferFromAzureBlobStorage::initialize()
auto handle_exception = [&, this](const auto & e, size_t i)
{
LOG_INFO(log, "Exception caught during Azure Download for file {} at offset {} at attempt {}/{}: {}", path, offset, i + 1, max_single_download_retries, e.Message);
LOG_DEBUG(log, "Exception caught during Azure Download for file {} at offset {} at attempt {}/{}: {}", path, offset, i + 1, max_single_download_retries, e.Message);
if (i + 1 == max_single_download_retries)
throw;
@ -262,6 +257,47 @@ size_t ReadBufferFromAzureBlobStorage::getFileSize()
return *file_size;
}
size_t ReadBufferFromAzureBlobStorage::readBigAt(char * to, size_t n, size_t range_begin, const std::function<bool(size_t)> & /*progress_callback*/) const
{
size_t initial_n = n;
size_t sleep_time_with_backoff_milliseconds = 100;
for (size_t i = 0; i < max_single_download_retries && n > 0; ++i)
{
size_t bytes_copied = 0;
try
{
Azure::Storage::Blobs::DownloadBlobOptions download_options;
download_options.Range = {static_cast<int64_t>(range_begin), n};
auto download_response = blob_client->Download(download_options);
std::unique_ptr<Azure::Core::IO::BodyStream> body_stream = std::move(download_response.Value.BodyStream);
bytes_copied = body_stream->ReadToCount(reinterpret_cast<uint8_t *>(to), body_stream->Length());
LOG_TEST(log, "AzureBlobStorage readBigAt read bytes {}", bytes_copied);
if (read_settings.remote_throttler)
read_settings.remote_throttler->add(bytes_copied, ProfileEvents::RemoteReadThrottlerBytes, ProfileEvents::RemoteReadThrottlerSleepMicroseconds);
}
catch (const Azure::Core::RequestFailedException & e)
{
LOG_DEBUG(log, "Exception caught during Azure Download for file {} at offset {} at attempt {}/{}: {}", path, offset, i + 1, max_single_download_retries, e.Message);
if (i + 1 == max_single_download_retries)
throw;
sleepForMilliseconds(sleep_time_with_backoff_milliseconds);
sleep_time_with_backoff_milliseconds *= 2;
}
range_begin += bytes_copied;
to += bytes_copied;
n -= bytes_copied;
}
return initial_n;
}
}
#endif

View File

@ -44,6 +44,10 @@ public:
size_t getFileSize() override;
size_t readBigAt(char * to, size_t n, size_t range_begin, const std::function<bool(size_t)> & progress_callback) const override;
bool supportsReadAt() override { return true; }
private:
void initialize();

View File

@ -18,21 +18,48 @@ namespace ProfileEvents
namespace DB
{
struct WriteBufferFromAzureBlobStorage::PartData
{
Memory<> memory;
size_t data_size = 0;
std::string block_id;
};
BufferAllocationPolicyPtr createBufferAllocationPolicy(const AzureObjectStorageSettings & settings)
{
BufferAllocationPolicy::Settings allocation_settings;
allocation_settings.strict_size = settings.strict_upload_part_size;
allocation_settings.min_size = settings.min_upload_part_size;
allocation_settings.max_size = settings.max_upload_part_size;
allocation_settings.multiply_factor = settings.upload_part_size_multiply_factor;
allocation_settings.multiply_parts_count_threshold = settings.upload_part_size_multiply_parts_count_threshold;
allocation_settings.max_single_size = settings.max_single_part_upload_size;
return BufferAllocationPolicy::create(allocation_settings);
}
WriteBufferFromAzureBlobStorage::WriteBufferFromAzureBlobStorage(
std::shared_ptr<const Azure::Storage::Blobs::BlobContainerClient> blob_container_client_,
const String & blob_path_,
size_t max_single_part_upload_size_,
size_t max_unexpected_write_error_retries_,
size_t buf_size_,
const WriteSettings & write_settings_)
const WriteSettings & write_settings_,
std::shared_ptr<const AzureObjectStorageSettings> settings_,
ThreadPoolCallbackRunner<void> schedule_)
: WriteBufferFromFileBase(buf_size_, nullptr, 0)
, log(getLogger("WriteBufferFromAzureBlobStorage"))
, max_single_part_upload_size(max_single_part_upload_size_)
, max_unexpected_write_error_retries(max_unexpected_write_error_retries_)
, buffer_allocation_policy(createBufferAllocationPolicy(*settings_))
, max_single_part_upload_size(settings_->max_single_part_upload_size)
, max_unexpected_write_error_retries(settings_->max_unexpected_write_error_retries)
, blob_path(blob_path_)
, write_settings(write_settings_)
, blob_container_client(blob_container_client_)
, task_tracker(
std::make_unique<TaskTracker>(
std::move(schedule_),
settings_->max_inflight_parts_for_one_file,
limitedLog))
{
allocateBuffer();
}
@ -77,62 +104,73 @@ void WriteBufferFromAzureBlobStorage::execWithRetry(std::function<void()> func,
void WriteBufferFromAzureBlobStorage::finalizeImpl()
{
auto block_blob_client = blob_container_client->GetBlockBlobClient(blob_path);
/// If there is only one block and size is less than or equal to max_single_part_upload_size
/// then we use single part upload instead of multi part upload
if (buffer_allocation_policy->getBufferNumber() == 1)
{
size_t data_size = size_t(position() - memory.data());
if (data_size <= max_single_part_upload_size)
{
Azure::Core::IO::MemoryBodyStream memory_stream(reinterpret_cast<const uint8_t *>(memory.data()), data_size);
execWithRetry([&](){ block_blob_client.Upload(memory_stream); }, max_unexpected_write_error_retries, data_size);
LOG_TRACE(log, "Committed single block for blob `{}`", blob_path);
return;
}
}
execWithRetry([this](){ next(); }, max_unexpected_write_error_retries);
if (tmp_buffer_write_offset > 0)
uploadBlock(tmp_buffer->data(), tmp_buffer_write_offset);
task_tracker->waitAll();
auto block_blob_client = blob_container_client->GetBlockBlobClient(blob_path);
execWithRetry([&](){ block_blob_client.CommitBlockList(block_ids); }, max_unexpected_write_error_retries);
LOG_TRACE(log, "Committed {} blocks for blob `{}`", block_ids.size(), blob_path);
}
void WriteBufferFromAzureBlobStorage::uploadBlock(const char * data, size_t size)
{
auto block_blob_client = blob_container_client->GetBlockBlobClient(blob_path);
const std::string & block_id = block_ids.emplace_back(getRandomASCIIString(64));
Azure::Core::IO::MemoryBodyStream memory_stream(reinterpret_cast<const uint8_t *>(data), size);
execWithRetry([&](){ block_blob_client.StageBlock(block_id, memory_stream); }, max_unexpected_write_error_retries, size);
tmp_buffer_write_offset = 0;
LOG_TRACE(log, "Staged block (id: {}) of size {} (blob path: {}).", block_id, size, blob_path);
}
WriteBufferFromAzureBlobStorage::MemoryBufferPtr WriteBufferFromAzureBlobStorage::allocateBuffer() const
{
return std::make_unique<Memory<>>(max_single_part_upload_size);
}
void WriteBufferFromAzureBlobStorage::nextImpl()
{
size_t size_to_upload = offset();
task_tracker->waitIfAny();
writePart();
allocateBuffer();
}
if (size_to_upload == 0)
void WriteBufferFromAzureBlobStorage::allocateBuffer()
{
buffer_allocation_policy->nextBuffer();
auto size = buffer_allocation_policy->getBufferSize();
if (buffer_allocation_policy->getBufferNumber() == 1)
size = std::min(size_t(DBMS_DEFAULT_BUFFER_SIZE), size);
memory = Memory(size);
WriteBuffer::set(memory.data(), memory.size());
}
void WriteBufferFromAzureBlobStorage::writePart()
{
auto data_size = size_t(position() - memory.data());
if (data_size == 0)
return;
if (!tmp_buffer)
tmp_buffer = allocateBuffer();
const std::string & block_id = block_ids.emplace_back(getRandomASCIIString(64));
std::shared_ptr<PartData> part_data = std::make_shared<PartData>(std::move(memory), data_size, block_id);
WriteBuffer::set(nullptr, 0);
size_t uploaded_size = 0;
while (uploaded_size != size_to_upload)
auto upload_worker = [this, part_data] ()
{
size_t memory_buffer_remaining_size = max_single_part_upload_size - tmp_buffer_write_offset;
if (memory_buffer_remaining_size == 0)
uploadBlock(tmp_buffer->data(), tmp_buffer->size());
auto block_blob_client = blob_container_client->GetBlockBlobClient(blob_path);
size_t size = std::min(memory_buffer_remaining_size, size_to_upload - uploaded_size);
memcpy(tmp_buffer->data() + tmp_buffer_write_offset, working_buffer.begin() + uploaded_size, size);
uploaded_size += size;
tmp_buffer_write_offset += size;
}
Azure::Core::IO::MemoryBodyStream memory_stream(reinterpret_cast<const uint8_t *>(part_data->memory.data()), part_data->data_size);
execWithRetry([&](){ block_blob_client.StageBlock(part_data->block_id, memory_stream); }, max_unexpected_write_error_retries, part_data->data_size);
if (tmp_buffer_write_offset == max_single_part_upload_size)
uploadBlock(tmp_buffer->data(), tmp_buffer->size());
if (write_settings.remote_throttler)
write_settings.remote_throttler->add(part_data->data_size, ProfileEvents::RemoteWriteThrottlerBytes, ProfileEvents::RemoteWriteThrottlerSleepMicroseconds);
};
if (write_settings.remote_throttler)
write_settings.remote_throttler->add(size_to_upload, ProfileEvents::RemoteWriteThrottlerBytes, ProfileEvents::RemoteWriteThrottlerSleepMicroseconds);
task_tracker->add(std::move(upload_worker));
}
}

View File

@ -11,7 +11,9 @@
#include <IO/WriteSettings.h>
#include <azure/storage/blobs.hpp>
#include <azure/core/io/body_stream.hpp>
#include <Common/ThreadPoolTaskTracker.h>
#include <Common/BufferAllocationPolicy.h>
#include <Storages/StorageAzureBlob.h>
namespace Poco
{
@ -21,6 +23,8 @@ class Logger;
namespace DB
{
class TaskTracker;
class WriteBufferFromAzureBlobStorage : public WriteBufferFromFileBase
{
public:
@ -29,10 +33,10 @@ public:
WriteBufferFromAzureBlobStorage(
AzureClientPtr blob_container_client_,
const String & blob_path_,
size_t max_single_part_upload_size_,
size_t max_unexpected_write_error_retries_,
size_t buf_size_,
const WriteSettings & write_settings_);
const WriteSettings & write_settings_,
std::shared_ptr<const AzureObjectStorageSettings> settings_,
ThreadPoolCallbackRunner<void> schedule_ = {});
~WriteBufferFromAzureBlobStorage() override;
@ -42,11 +46,19 @@ public:
void sync() override { next(); }
private:
struct PartData;
void writePart();
void allocateBuffer();
void finalizeImpl() override;
void execWithRetry(std::function<void()> func, size_t num_tries, size_t cost = 0);
void uploadBlock(const char * data, size_t size);
LoggerPtr log;
LogSeriesLimiterPtr limitedLog = std::make_shared<LogSeriesLimiter>(log, 1, 5);
BufferAllocationPolicyPtr buffer_allocation_policy;
const size_t max_single_part_upload_size;
const size_t max_unexpected_write_error_retries;
@ -61,6 +73,10 @@ private:
size_t tmp_buffer_write_offset = 0;
MemoryBufferPtr allocateBuffer() const;
bool first_buffer=true;
std::unique_ptr<TaskTracker> task_tracker;
};
}

View File

@ -212,17 +212,23 @@ std::unique_ptr<BlobContainerClient> getAzureBlobContainerClient(
std::unique_ptr<AzureObjectStorageSettings> getAzureBlobStorageSettings(const Poco::Util::AbstractConfiguration & config, const String & config_prefix, ContextPtr context)
{
return std::make_unique<AzureObjectStorageSettings>(
config.getUInt64(config_prefix + ".max_single_part_upload_size", 100 * 1024 * 1024),
config.getUInt64(config_prefix + ".min_bytes_for_seek", 1024 * 1024),
config.getInt(config_prefix + ".max_single_read_retries", 3),
config.getInt(config_prefix + ".max_single_download_retries", 3),
config.getInt(config_prefix + ".list_object_keys_size", 1000),
config.getUInt64(config_prefix + ".max_upload_part_size", 5ULL * 1024 * 1024 * 1024),
config.getUInt64(config_prefix + ".max_single_part_copy_size", context->getSettings().azure_max_single_part_copy_size),
config.getBool(config_prefix + ".use_native_copy", false),
config.getUInt64(config_prefix + ".max_unexpected_write_error_retries", context->getSettings().azure_max_unexpected_write_error_retries)
);
std::unique_ptr<AzureObjectStorageSettings> settings = std::make_unique<AzureObjectStorageSettings>();
settings->max_single_part_upload_size = config.getUInt64(config_prefix + ".max_single_part_upload_size", context->getSettings().azure_max_single_part_upload_size);
settings->min_bytes_for_seek = config.getUInt64(config_prefix + ".min_bytes_for_seek", 1024 * 1024);
settings->max_single_read_retries = config.getInt(config_prefix + ".max_single_read_retries", 3);
settings->max_single_download_retries = config.getInt(config_prefix + ".max_single_download_retries", 3);
settings->list_object_keys_size = config.getInt(config_prefix + ".list_object_keys_size", 1000);
settings->min_upload_part_size = config.getUInt64(config_prefix + ".min_upload_part_size", context->getSettings().azure_min_upload_part_size);
settings->max_upload_part_size = config.getUInt64(config_prefix + ".max_upload_part_size", context->getSettings().azure_max_upload_part_size);
settings->max_single_part_copy_size = config.getUInt64(config_prefix + ".max_single_part_copy_size", context->getSettings().azure_max_single_part_copy_size);
settings->use_native_copy = config.getBool(config_prefix + ".use_native_copy", false);
settings->max_unexpected_write_error_retries = config.getUInt64(config_prefix + ".max_unexpected_write_error_retries", context->getSettings().azure_max_unexpected_write_error_retries);
settings->max_inflight_parts_for_one_file = config.getUInt64(config_prefix + ".max_inflight_parts_for_one_file", context->getSettings().azure_max_inflight_parts_for_one_file);
settings->strict_upload_part_size = config.getUInt64(config_prefix + ".strict_upload_part_size", context->getSettings().azure_strict_upload_part_size);
settings->upload_part_size_multiply_factor = config.getUInt64(config_prefix + ".upload_part_size_multiply_factor", context->getSettings().azure_upload_part_size_multiply_factor);
settings->upload_part_size_multiply_parts_count_threshold = config.getUInt64(config_prefix + ".upload_part_size_multiply_parts_count_threshold", context->getSettings().azure_upload_part_size_multiply_parts_count_threshold);
return settings;
}
}

View File

@ -265,10 +265,9 @@ std::unique_ptr<WriteBufferFromFileBase> AzureObjectStorage::writeObject( /// NO
return std::make_unique<WriteBufferFromAzureBlobStorage>(
client.get(),
object.remote_path,
settings.get()->max_single_part_upload_size,
settings.get()->max_unexpected_write_error_retries,
buf_size,
patchSettings(write_settings));
patchSettings(write_settings),
settings.get());
}
/// Remove file. Throws exception if file doesn't exists or it's a directory.

View File

@ -24,19 +24,29 @@ struct AzureObjectStorageSettings
int max_single_read_retries_,
int max_single_download_retries_,
int list_object_keys_size_,
size_t min_upload_part_size_,
size_t max_upload_part_size_,
size_t max_single_part_copy_size_,
bool use_native_copy_,
size_t max_unexpected_write_error_retries_)
size_t max_unexpected_write_error_retries_,
size_t max_inflight_parts_for_one_file_,
size_t strict_upload_part_size_,
size_t upload_part_size_multiply_factor_,
size_t upload_part_size_multiply_parts_count_threshold_)
: max_single_part_upload_size(max_single_part_upload_size_)
, min_bytes_for_seek(min_bytes_for_seek_)
, max_single_read_retries(max_single_read_retries_)
, max_single_download_retries(max_single_download_retries_)
, list_object_keys_size(list_object_keys_size_)
, min_upload_part_size(min_upload_part_size_)
, max_upload_part_size(max_upload_part_size_)
, max_single_part_copy_size(max_single_part_copy_size_)
, use_native_copy(use_native_copy_)
, max_unexpected_write_error_retries (max_unexpected_write_error_retries_)
, max_unexpected_write_error_retries(max_unexpected_write_error_retries_)
, max_inflight_parts_for_one_file(max_inflight_parts_for_one_file_)
, strict_upload_part_size(strict_upload_part_size_)
, upload_part_size_multiply_factor(upload_part_size_multiply_factor_)
, upload_part_size_multiply_parts_count_threshold(upload_part_size_multiply_parts_count_threshold_)
{
}
@ -52,6 +62,10 @@ struct AzureObjectStorageSettings
size_t max_single_part_copy_size = 256 * 1024 * 1024;
bool use_native_copy = false;
size_t max_unexpected_write_error_retries = 4;
size_t max_inflight_parts_for_one_file = 20;
size_t strict_upload_part_size = 0;
size_t upload_part_size_multiply_factor = 2;
size_t upload_part_size_multiply_parts_count_threshold = 500;
};
using AzureClient = Azure::Storage::Blobs::BlobContainerClient;

View File

@ -14,6 +14,8 @@ extract_into_parent_list(clickhouse_functions_sources dbms_sources
multiMatchAny.cpp
checkHyperscanRegexp.cpp
array/has.cpp
equals.cpp
notEquals.cpp
CastOverloadResolver.cpp
)
extract_into_parent_list(clickhouse_functions_headers dbms_headers

View File

@ -348,6 +348,7 @@ public:
String getName() const override { return Name::name; }
bool useDefaultImplementationForNulls() const override { return false; }
bool useDefaultImplementationForConstants() const override { return true; }
bool useDefaultImplementationForLowCardinalityColumns() const override { return false; }
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
{
@ -469,9 +470,6 @@ public:
else
return_type = json_return_type;
/// Top-level LowCardinality columns are processed outside JSON parser.
json_return_type = removeLowCardinality(json_return_type);
DataTypes argument_types;
argument_types.reserve(arguments.size());
for (const auto & argument : arguments)
@ -867,11 +865,9 @@ struct JSONExtractTree
explicit LowCardinalityFixedStringNode(const size_t fixed_length_) : fixed_length(fixed_length_) { }
bool insertResultToColumn(IColumn & dest, const Element & element) override
{
// If element is an object we delegate the insertion to JSONExtractRawImpl
if (element.isObject())
// For types other than string, delegate the insertion to JSONExtractRawImpl.
if (!element.isString())
return JSONExtractRawImpl<JSONParser>::insertResultToLowCardinalityFixedStringColumn(dest, element, fixed_length);
else if (!element.isString())
return false;
auto str = element.getString();
if (str.size() > fixed_length)
@ -1486,9 +1482,6 @@ public:
// We use insertResultToLowCardinalityFixedStringColumn in case we are inserting raw data in a Low Cardinality FixedString column
static bool insertResultToLowCardinalityFixedStringColumn(IColumn & dest, const Element & element, size_t fixed_length)
{
if (element.getObject().size() > fixed_length)
return false;
ColumnFixedString::Chars chars;
WriteBufferFromVector<ColumnFixedString::Chars> buf(chars, AppendModeTag());
traverse(element, buf);

View File

@ -13,6 +13,11 @@ REGISTER_FUNCTION(Equals)
factory.registerFunction<FunctionEquals>();
}
FunctionOverloadResolverPtr createInternalFunctionEqualOverloadResolver(bool decimal_check_overflow)
{
return std::make_unique<FunctionToOverloadResolverAdaptor>(std::make_shared<FunctionEquals>(decimal_check_overflow));
}
template <>
ColumnPtr FunctionComparison<EqualsOp, NameEquals>::executeTupleImpl(
const ColumnsWithTypeAndName & x, const ColumnsWithTypeAndName & y, size_t tuple_size, size_t input_rows_count) const

11
src/Functions/equals.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include <memory>
namespace DB
{
class IFunctionOverloadResolver;
using FunctionOverloadResolverPtr = std::shared_ptr<IFunctionOverloadResolver>;
FunctionOverloadResolverPtr createInternalFunctionEqualOverloadResolver(bool decimal_check_overflow);
}

View File

@ -0,0 +1,96 @@
#include <Functions/IFunction.h>
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionHelpers.h>
#include <DataTypes/DataTypeString.h>
#include <Columns/ColumnString.h>
#include <Interpreters/Context.h>
#include <Core/Field.h>
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
extern const int FUNCTION_NOT_ALLOWED;
}
namespace
{
class FunctionGetClientHTTPHeader : public IFunction, WithContext
{
public:
explicit FunctionGetClientHTTPHeader(ContextPtr context_)
: WithContext(context_)
{
if (!getContext()->getSettingsRef().allow_get_client_http_header)
throw Exception(ErrorCodes::FUNCTION_NOT_ALLOWED, "The function getClientHTTPHeader requires setting `allow_get_client_http_header` to be enabled.");
}
String getName() const override { return "getClientHTTPHeader"; }
bool useDefaultImplementationForConstants() const override { return true; }
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo &) const override { return false; }
size_t getNumberOfArguments() const override
{
return 1;
}
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
{
if (!isString(arguments[0]))
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The argument of function {} must be String", getName());
return std::make_shared<DataTypeString>();
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
{
const ClientInfo & client_info = getContext()->getClientInfo();
const auto & source = arguments[0].column;
auto result = result_type->createColumn();
result->reserve(input_rows_count);
for (size_t row = 0; row < input_rows_count; ++row)
{
Field header;
source->get(row, header);
if (auto it = client_info.http_headers.find(header.get<String>()); it != client_info.http_headers.end())
result->insert(it->second);
else
result->insertDefault();
}
return result;
}
};
}
REGISTER_FUNCTION(GetClientHTTPHeader)
{
factory.registerFunction("getClientHTTPHeader",
[](ContextPtr context) { return std::make_shared<FunctionGetClientHTTPHeader>(context); },
FunctionDocumentation{
.description = R"(
Get the value of an HTTP header.
If there is no such header or the current request is not performed via the HTTP interface, the function returns an empty string.
Certain HTTP headers (e.g., `Authentication` and `X-ClickHouse-*`) are restricted.
The function requires the setting `allow_get_client_http_header` to be enabled.
The setting is not enabled by default for security reasons, because some headers, such as `Cookie`, could contain sensitive info.
HTTP headers are case sensitive for this function.
If the function is used in the context of a distributed query, it returns non-empty result only on the initiator node.
",
.syntax = "getClientHTTPHeader(name)",
.arguments = {{"name", "The HTTP header name (String)"}},
.returned_value = "The value of the header (String).",
.categories{"Miscellaneous"}});
}
}

View File

@ -7,7 +7,6 @@
#include <Functions/PerformanceAdaptors.h>
#include <Interpreters/castColumn.h>
#include <Common/TargetSpecific.h>
#include <base/range.h>
#include <cmath>
#include <numbers>
@ -42,121 +41,6 @@ namespace ErrorCodes
namespace
{
constexpr double PI = std::numbers::pi_v<double>;
constexpr float PI_F = std::numbers::pi_v<float>;
constexpr float RAD_IN_DEG = static_cast<float>(PI / 180.0);
constexpr float RAD_IN_DEG_HALF = static_cast<float>(PI / 360.0);
constexpr size_t COS_LUT_SIZE = 1024; // maxerr 0.00063%
constexpr float COS_LUT_SIZE_F = 1024.0f; // maxerr 0.00063%
constexpr size_t ASIN_SQRT_LUT_SIZE = 512;
constexpr size_t METRIC_LUT_SIZE = 1024;
/** Earth radius in meters using WGS84 authalic radius.
* We use this value to be consistent with H3 library.
*/
constexpr float EARTH_RADIUS = 6371007.180918475f;
constexpr float EARTH_DIAMETER = 2 * EARTH_RADIUS;
float cos_lut[COS_LUT_SIZE + 1]; /// cos(x) table
float asin_sqrt_lut[ASIN_SQRT_LUT_SIZE + 1]; /// asin(sqrt(x)) * earth_diameter table
float sphere_metric_lut[METRIC_LUT_SIZE + 1]; /// sphere metric, unitless: the distance in degrees for one degree across longitude depending on latitude
float sphere_metric_meters_lut[METRIC_LUT_SIZE + 1]; /// sphere metric: the distance in meters for one degree across longitude depending on latitude
float wgs84_metric_meters_lut[2 * (METRIC_LUT_SIZE + 1)]; /// ellipsoid metric: the distance in meters across one degree latitude/longitude depending on latitude
inline double sqr(double v)
{
return v * v;
}
inline float sqrf(float v)
{
return v * v;
}
void geodistInit()
{
for (size_t i = 0; i <= COS_LUT_SIZE; ++i)
cos_lut[i] = static_cast<float>(cos(2 * PI * i / COS_LUT_SIZE)); // [0, 2 * pi] -> [0, COS_LUT_SIZE]
for (size_t i = 0; i <= ASIN_SQRT_LUT_SIZE; ++i)
asin_sqrt_lut[i] = static_cast<float>(asin(
sqrt(static_cast<double>(i) / ASIN_SQRT_LUT_SIZE))); // [0, 1] -> [0, ASIN_SQRT_LUT_SIZE]
for (size_t i = 0; i <= METRIC_LUT_SIZE; ++i)
{
double latitude = i * (PI / METRIC_LUT_SIZE) - PI * 0.5; // [-pi / 2, pi / 2] -> [0, METRIC_LUT_SIZE]
/// Squared metric coefficients (for the distance in meters) on a tangent plane, for latitude and longitude (in degrees),
/// depending on the latitude (in radians).
/// https://github.com/mapbox/cheap-ruler/blob/master/index.js#L67
wgs84_metric_meters_lut[i * 2] = static_cast<float>(sqr(111132.09 - 566.05 * cos(2 * latitude) + 1.20 * cos(4 * latitude)));
wgs84_metric_meters_lut[i * 2 + 1] = static_cast<float>(sqr(111415.13 * cos(latitude) - 94.55 * cos(3 * latitude) + 0.12 * cos(5 * latitude)));
sphere_metric_meters_lut[i] = static_cast<float>(sqr((EARTH_DIAMETER * PI / 360) * cos(latitude)));
sphere_metric_lut[i] = static_cast<float>(sqr(cos(latitude)));
}
}
inline NO_SANITIZE_UNDEFINED size_t floatToIndex(float x)
{
/// Implementation specific behaviour on overflow or infinite value.
return static_cast<size_t>(x);
}
inline float geodistDegDiff(float f)
{
f = fabsf(f);
if (f > 180)
f = 360 - f;
return f;
}
inline float geodistFastCos(float x)
{
float y = fabsf(x) * (COS_LUT_SIZE_F / PI_F / 2.0f);
size_t i = floatToIndex(y);
y -= i;
i &= (COS_LUT_SIZE - 1);
return cos_lut[i] + (cos_lut[i + 1] - cos_lut[i]) * y;
}
inline float geodistFastSin(float x)
{
float y = fabsf(x) * (COS_LUT_SIZE_F / PI_F / 2.0f);
size_t i = floatToIndex(y);
y -= i;
i = (i - COS_LUT_SIZE / 4) & (COS_LUT_SIZE - 1); // cos(x - pi / 2) = sin(x), costable / 4 = pi / 2
return cos_lut[i] + (cos_lut[i + 1] - cos_lut[i]) * y;
}
/// fast implementation of asin(sqrt(x))
/// max error in floats 0.00369%, in doubles 0.00072%
inline float geodistFastAsinSqrt(float x)
{
if (x < 0.122f)
{
// distance under 4546 km, Taylor error under 0.00072%
float y = sqrtf(x);
return y + x * y * 0.166666666666666f + x * x * y * 0.075f + x * x * x * y * 0.044642857142857f;
}
if (x < 0.948f)
{
// distance under 17083 km, 512-entry LUT error under 0.00072%
x *= ASIN_SQRT_LUT_SIZE;
size_t i = floatToIndex(x);
return asin_sqrt_lut[i] + (asin_sqrt_lut[i + 1] - asin_sqrt_lut[i]) * (x - i);
}
return asinf(sqrtf(x)); // distance over 17083 km, just compute exact
}
enum class Method
{
SPHERE_DEGREES,
@ -164,18 +48,117 @@ enum class Method
WGS84_METERS,
};
}
constexpr size_t ASIN_SQRT_LUT_SIZE = 512;
constexpr size_t COS_LUT_SIZE = 1024; // maxerr 0.00063%
constexpr size_t METRIC_LUT_SIZE = 1024;
/// Earth radius in meters using WGS84 authalic radius.
/// We use this value to be consistent with H3 library.
constexpr double EARTH_RADIUS = 6371007.180918475;
constexpr double EARTH_DIAMETER = 2.0 * EARTH_RADIUS;
constexpr double PI = std::numbers::pi_v<double>;
template <typename T>
T sqr(T v) { return v * v; }
template <typename T>
struct Impl
{
T cos_lut[COS_LUT_SIZE + 1]; /// cos(x) table
T asin_sqrt_lut[ASIN_SQRT_LUT_SIZE + 1]; /// asin(sqrt(x)) * earth_diameter table
T sphere_metric_lut[METRIC_LUT_SIZE + 1]; /// sphere metric, unitless: the distance in degrees for one degree across longitude depending on latitude
T sphere_metric_meters_lut[METRIC_LUT_SIZE + 1]; /// sphere metric: the distance in meters for one degree across longitude depending on latitude
T wgs84_metric_meters_lut[2 * (METRIC_LUT_SIZE + 1)]; /// ellipsoid metric: the distance in meters across one degree latitude/longitude depending on latitude
Impl()
{
for (size_t i = 0; i <= COS_LUT_SIZE; ++i)
cos_lut[i] = T(std::cos(2 * PI * static_cast<double>(i) / COS_LUT_SIZE)); // [0, 2 * pi] -> [0, COS_LUT_SIZE]
for (size_t i = 0; i <= ASIN_SQRT_LUT_SIZE; ++i)
asin_sqrt_lut[i] = T(std::asin(std::sqrt(static_cast<double>(i) / ASIN_SQRT_LUT_SIZE))); // [0, 1] -> [0, ASIN_SQRT_LUT_SIZE]
for (size_t i = 0; i <= METRIC_LUT_SIZE; ++i)
{
double latitude = i * (PI / METRIC_LUT_SIZE) - PI * 0.5; // [-pi / 2, pi / 2] -> [0, METRIC_LUT_SIZE]
/// Squared metric coefficients (for the distance in meters) on a tangent plane, for latitude and longitude (in degrees),
/// depending on the latitude (in radians).
/// https://github.com/mapbox/cheap-ruler/blob/master/index.js#L67
wgs84_metric_meters_lut[i * 2] = T(sqr(111132.09 - 566.05 * std::cos(2.0 * latitude) + 1.20 * std::cos(4.0 * latitude)));
wgs84_metric_meters_lut[i * 2 + 1] = T(sqr(111415.13 * std::cos(latitude) - 94.55 * std::cos(3.0 * latitude) + 0.12 * std::cos(5.0 * latitude)));
sphere_metric_meters_lut[i] = T(sqr((EARTH_DIAMETER * PI / 360) * std::cos(latitude)));
sphere_metric_lut[i] = T(sqr(std::cos(latitude)));
}
}
static inline NO_SANITIZE_UNDEFINED size_t toIndex(T x)
{
/// Implementation specific behaviour on overflow or infinite value.
return static_cast<size_t>(x);
}
static inline T degDiff(T f)
{
f = std::abs(f);
if (f > 180)
f = 360 - f;
return f;
}
inline T fastCos(T x)
{
T y = std::abs(x) * (T(COS_LUT_SIZE) / T(PI) / T(2.0));
size_t i = toIndex(y);
y -= i;
i &= (COS_LUT_SIZE - 1);
return cos_lut[i] + (cos_lut[i + 1] - cos_lut[i]) * y;
}
inline T fastSin(T x)
{
T y = std::abs(x) * (T(COS_LUT_SIZE) / T(PI) / T(2.0));
size_t i = toIndex(y);
y -= i;
i = (i - COS_LUT_SIZE / 4) & (COS_LUT_SIZE - 1); // cos(x - pi / 2) = sin(x), costable / 4 = pi / 2
return cos_lut[i] + (cos_lut[i + 1] - cos_lut[i]) * y;
}
/// fast implementation of asin(sqrt(x))
/// max error in floats 0.00369%, in doubles 0.00072%
inline T fastAsinSqrt(T x)
{
if (x < T(0.122))
{
// distance under 4546 km, Taylor error under 0.00072%
T y = std::sqrt(x);
return y + x * y * T(0.166666666666666) + x * x * y * T(0.075) + x * x * x * y * T(0.044642857142857);
}
if (x < T(0.948))
{
// distance under 17083 km, 512-entry LUT error under 0.00072%
x *= ASIN_SQRT_LUT_SIZE;
size_t i = toIndex(x);
return asin_sqrt_lut[i] + (asin_sqrt_lut[i + 1] - asin_sqrt_lut[i]) * (x - i);
}
return std::asin(std::sqrt(x)); /// distance is over 17083 km, just compute exact
}
};
template <typename T> Impl<T> impl;
DECLARE_MULTITARGET_CODE(
namespace
{
template <Method method>
float distance(float lon1deg, float lat1deg, float lon2deg, float lat2deg)
template <Method method, typename T>
T distance(T lon1deg, T lat1deg, T lon2deg, T lat2deg)
{
float lat_diff = geodistDegDiff(lat1deg - lat2deg);
float lon_diff = geodistDegDiff(lon1deg - lon2deg);
T lat_diff = impl<T>.degDiff(lat1deg - lat2deg);
T lon_diff = impl<T>.degDiff(lon1deg - lon2deg);
if (lon_diff < 13)
{
@ -187,51 +170,54 @@ float distance(float lon1deg, float lat1deg, float lon2deg, float lat2deg)
/// (Remember how a plane flies from Amsterdam to New York)
/// But if longitude is close but latitude is different enough, there is no difference between meridian and great circle line.
float latitude_midpoint = (lat1deg + lat2deg + 180) * METRIC_LUT_SIZE / 360; // [-90, 90] degrees -> [0, METRIC_LUT_SIZE] indexes
size_t latitude_midpoint_index = floatToIndex(latitude_midpoint) & (METRIC_LUT_SIZE - 1);
T latitude_midpoint = (lat1deg + lat2deg + 180) * METRIC_LUT_SIZE / 360; // [-90, 90] degrees -> [0, METRIC_LUT_SIZE] indexes
size_t latitude_midpoint_index = impl<T>.toIndex(latitude_midpoint) & (METRIC_LUT_SIZE - 1);
/// This is linear interpolation between two table items at index "latitude_midpoint_index" and "latitude_midpoint_index + 1".
float k_lat{};
float k_lon{};
T k_lat{};
T k_lon{};
if constexpr (method == Method::SPHERE_DEGREES)
{
k_lat = 1;
k_lon = sphere_metric_lut[latitude_midpoint_index]
+ (sphere_metric_lut[latitude_midpoint_index + 1] - sphere_metric_lut[latitude_midpoint_index]) * (latitude_midpoint - latitude_midpoint_index);
k_lon = impl<T>.sphere_metric_lut[latitude_midpoint_index]
+ (impl<T>.sphere_metric_lut[latitude_midpoint_index + 1] - impl<T>.sphere_metric_lut[latitude_midpoint_index]) * (latitude_midpoint - latitude_midpoint_index);
}
else if constexpr (method == Method::SPHERE_METERS)
{
k_lat = sqrf(EARTH_DIAMETER * PI_F / 360.0f);
k_lat = sqr(T(EARTH_DIAMETER) * T(PI) / T(360.0));
k_lon = sphere_metric_meters_lut[latitude_midpoint_index]
+ (sphere_metric_meters_lut[latitude_midpoint_index + 1] - sphere_metric_meters_lut[latitude_midpoint_index]) * (latitude_midpoint - latitude_midpoint_index);
k_lon = impl<T>.sphere_metric_meters_lut[latitude_midpoint_index]
+ (impl<T>.sphere_metric_meters_lut[latitude_midpoint_index + 1] - impl<T>.sphere_metric_meters_lut[latitude_midpoint_index]) * (latitude_midpoint - latitude_midpoint_index);
}
else if constexpr (method == Method::WGS84_METERS)
{
k_lat = wgs84_metric_meters_lut[latitude_midpoint_index * 2]
+ (wgs84_metric_meters_lut[(latitude_midpoint_index + 1) * 2] - wgs84_metric_meters_lut[latitude_midpoint_index * 2]) * (latitude_midpoint - latitude_midpoint_index);
k_lat = impl<T>.wgs84_metric_meters_lut[latitude_midpoint_index * 2]
+ (impl<T>.wgs84_metric_meters_lut[(latitude_midpoint_index + 1) * 2] - impl<T>.wgs84_metric_meters_lut[latitude_midpoint_index * 2]) * (latitude_midpoint - latitude_midpoint_index);
k_lon = wgs84_metric_meters_lut[latitude_midpoint_index * 2 + 1]
+ (wgs84_metric_meters_lut[(latitude_midpoint_index + 1) * 2 + 1] - wgs84_metric_meters_lut[latitude_midpoint_index * 2 + 1]) * (latitude_midpoint - latitude_midpoint_index);
k_lon = impl<T>.wgs84_metric_meters_lut[latitude_midpoint_index * 2 + 1]
+ (impl<T>.wgs84_metric_meters_lut[(latitude_midpoint_index + 1) * 2 + 1] - impl<T>.wgs84_metric_meters_lut[latitude_midpoint_index * 2 + 1]) * (latitude_midpoint - latitude_midpoint_index);
}
/// Metric on a tangent plane: it differs from Euclidean metric only by scale of coordinates.
return sqrtf(k_lat * lat_diff * lat_diff + k_lon * lon_diff * lon_diff);
return std::sqrt(k_lat * lat_diff * lat_diff + k_lon * lon_diff * lon_diff);
}
else
{
// points too far away; use haversine
/// Points are too far away: use Haversine.
float a = sqrf(geodistFastSin(lat_diff * RAD_IN_DEG_HALF))
+ geodistFastCos(lat1deg * RAD_IN_DEG) * geodistFastCos(lat2deg * RAD_IN_DEG) * sqrf(geodistFastSin(lon_diff * RAD_IN_DEG_HALF));
static constexpr T RAD_IN_DEG = T(PI / 180.0);
static constexpr T RAD_IN_DEG_HALF = T(PI / 360.0);
T a = sqr(impl<T>.fastSin(lat_diff * RAD_IN_DEG_HALF))
+ impl<T>.fastCos(lat1deg * RAD_IN_DEG) * impl<T>.fastCos(lat2deg * RAD_IN_DEG) * sqr(impl<T>.fastSin(lon_diff * RAD_IN_DEG_HALF));
if constexpr (method == Method::SPHERE_DEGREES)
return (360.0f / PI_F) * geodistFastAsinSqrt(a);
return (T(360.0) / T(PI)) * impl<T>.fastAsinSqrt(a);
else
return EARTH_DIAMETER * geodistFastAsinSqrt(a);
return T(EARTH_DIAMETER) * impl<T>.fastAsinSqrt(a);
}
}
@ -241,13 +227,24 @@ template <Method method>
class FunctionGeoDistance : public IFunction
{
public:
static constexpr auto name =
(method == Method::SPHERE_DEGREES) ? "greatCircleAngle"
: ((method == Method::SPHERE_METERS) ? "greatCircleDistance"
: "geoDistance");
explicit FunctionGeoDistance(ContextPtr context)
{
always_float32 = !context->getSettingsRef().geo_distance_returns_float64_on_float64_arguments;
}
private:
String getName() const override { return name; }
bool always_float32;
String getName() const override
{
if constexpr (method == Method::SPHERE_DEGREES)
return "greatCircleAngle";
if constexpr (method == Method::SPHERE_METERS)
return "greatCircleDistance";
else
return "geoDistance";
}
size_t getNumberOfArguments() const override { return 4; }
bool useDefaultImplementationForConstants() const override { return true; }
@ -255,22 +252,31 @@ private:
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
{
for (const auto arg_idx : collections::range(0, arguments.size()))
bool has_float64 = false;
for (size_t arg_idx = 0; arg_idx < 4; ++arg_idx)
{
const auto * arg = arguments[arg_idx].get();
if (!isNumber(WhichDataType(arg)))
WhichDataType which(arguments[arg_idx]);
if (!isNumber(which))
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument {} of function {}. "
"Must be numeric", arg->getName(), std::to_string(arg_idx + 1), getName());
"Must be numeric", arguments[arg_idx]->getName(), std::to_string(arg_idx + 1), getName());
if (which.isFloat64())
has_float64 = true;
}
return std::make_shared<DataTypeFloat32>();
if (has_float64 && !always_float32)
return std::make_shared<DataTypeFloat64>();
else
return std::make_shared<DataTypeFloat32>();
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
{
auto dst = ColumnVector<Float32>::create();
auto & dst_data = dst->getData();
dst_data.resize(input_rows_count);
bool returns_float64 = WhichDataType(result_type).isFloat64();
auto dst = result_type->createColumn();
auto arguments_copy = arguments;
for (auto & argument : arguments_copy)
@ -280,10 +286,24 @@ private:
argument.type = result_type;
}
const auto * col_lon1 = convertArgumentColumnToFloat32(arguments_copy, 0);
const auto * col_lat1 = convertArgumentColumnToFloat32(arguments_copy, 1);
const auto * col_lon2 = convertArgumentColumnToFloat32(arguments_copy, 2);
const auto * col_lat2 = convertArgumentColumnToFloat32(arguments_copy, 3);
if (returns_float64)
run<Float64>(arguments_copy, dst, input_rows_count);
else
run<Float32>(arguments_copy, dst, input_rows_count);
return dst;
}
template <typename T>
void run(const ColumnsWithTypeAndName & arguments, MutableColumnPtr & dst, size_t input_rows_count) const
{
const auto * col_lon1 = convertArgumentColumn<T>(arguments, 0);
const auto * col_lat1 = convertArgumentColumn<T>(arguments, 1);
const auto * col_lon2 = convertArgumentColumn<T>(arguments, 2);
const auto * col_lat2 = convertArgumentColumn<T>(arguments, 3);
auto & dst_data = assert_cast<ColumnVector<T> &>(*dst).getData();
dst_data.resize(input_rows_count);
for (size_t row_num = 0; row_num < input_rows_count; ++row_num)
{
@ -291,20 +311,20 @@ private:
col_lon1->getData()[row_num], col_lat1->getData()[row_num],
col_lon2->getData()[row_num], col_lat2->getData()[row_num]);
}
return dst;
}
const ColumnFloat32 * convertArgumentColumnToFloat32(const ColumnsWithTypeAndName & arguments, size_t argument_index) const
template <typename T>
const ColumnVector<T> * convertArgumentColumn(const ColumnsWithTypeAndName & arguments, size_t argument_index) const
{
const auto * column_typed = checkAndGetColumn<ColumnFloat32>(arguments[argument_index].column.get());
const auto * column_typed = checkAndGetColumn<ColumnVector<T>>(arguments[argument_index].column.get());
if (!column_typed)
throw Exception(
ErrorCodes::ILLEGAL_COLUMN,
"Illegal type {} of argument {} of function {}. Must be Float32.",
"Illegal type {} of argument {} of function {}. Must be {}.",
arguments[argument_index].type->getName(),
argument_index + 1,
getName());
getName(),
TypeName<T>);
return column_typed;
}
@ -316,18 +336,19 @@ template <Method method>
class FunctionGeoDistance : public TargetSpecific::Default::FunctionGeoDistance<method>
{
public:
explicit FunctionGeoDistance(ContextPtr context) : selector(context)
explicit FunctionGeoDistance(ContextPtr context)
: TargetSpecific::Default::FunctionGeoDistance<method>(context), selector(context)
{
selector.registerImplementation<TargetArch::Default,
TargetSpecific::Default::FunctionGeoDistance<method>>();
TargetSpecific::Default::FunctionGeoDistance<method>>(context);
#if USE_MULTITARGET_CODE
selector.registerImplementation<TargetArch::AVX,
TargetSpecific::AVX::FunctionGeoDistance<method>>();
TargetSpecific::AVX::FunctionGeoDistance<method>>(context);
selector.registerImplementation<TargetArch::AVX2,
TargetSpecific::AVX2::FunctionGeoDistance<method>>();
TargetSpecific::AVX2::FunctionGeoDistance<method>>(context);
selector.registerImplementation<TargetArch::AVX512F,
TargetSpecific::AVX512F::FunctionGeoDistance<method>>();
TargetSpecific::AVX512F::FunctionGeoDistance<method>>(context);
#endif
}
@ -345,12 +366,13 @@ private:
ImplementationSelector<IFunction> selector;
};
}
REGISTER_FUNCTION(GeoDistance)
{
geodistInit();
factory.registerFunction<FunctionGeoDistance<Method::SPHERE_DEGREES>>();
factory.registerFunction<FunctionGeoDistance<Method::SPHERE_METERS>>();
factory.registerFunction<FunctionGeoDistance<Method::WGS84_METERS>>();
factory.registerFunction("greatCircleAngle", [](ContextPtr context) { return std::make_shared<FunctionGeoDistance<Method::SPHERE_DEGREES>>(std::move(context)); });
factory.registerFunction("greatCircleDistance", [](ContextPtr context) { return std::make_shared<FunctionGeoDistance<Method::SPHERE_METERS>>(std::move(context)); });
factory.registerFunction("geoDistance", [](ContextPtr context) { return std::make_shared<FunctionGeoDistance<Method::WGS84_METERS>>(std::move(context)); });
}
}

View File

@ -12,6 +12,11 @@ REGISTER_FUNCTION(NotEquals)
factory.registerFunction<FunctionNotEquals>();
}
FunctionOverloadResolverPtr createInternalFunctionNotEqualOverloadResolver(bool decimal_check_overflow)
{
return std::make_unique<FunctionToOverloadResolverAdaptor>(std::make_shared<FunctionNotEquals>(decimal_check_overflow));
}
template <>
ColumnPtr FunctionComparison<NotEqualsOp, NameNotEquals>::executeTupleImpl(
const ColumnsWithTypeAndName & x, const ColumnsWithTypeAndName & y, size_t tuple_size, size_t input_rows_count) const

11
src/Functions/notEquals.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include <memory>
namespace DB
{
class IFunctionOverloadResolver;
using FunctionOverloadResolverPtr = std::shared_ptr<IFunctionOverloadResolver>;
FunctionOverloadResolverPtr createInternalFunctionNotEqualOverloadResolver(bool decimal_check_overflow);
}

View File

@ -79,7 +79,7 @@ inline char * writeVarInt(Int64 x, char * ostr)
return writeVarUInt(static_cast<UInt64>((x << 1) ^ (x >> 63)), ostr);
}
namespace impl
namespace varint_impl
{
template <bool check_eof>
@ -106,8 +106,8 @@ inline void readVarUInt(UInt64 & x, ReadBuffer & istr)
inline void readVarUInt(UInt64 & x, ReadBuffer & istr)
{
if (istr.buffer().end() - istr.position() >= 10)
return impl::readVarUInt<false>(x, istr);
return impl::readVarUInt<true>(x, istr);
return varint_impl::readVarUInt<false>(x, istr);
return varint_impl::readVarUInt<true>(x, istr);
}
inline void readVarUInt(UInt64 & x, std::istream & istr)

View File

@ -4,8 +4,8 @@
#include "StdIStreamFromMemory.h"
#include "WriteBufferFromS3.h"
#include "WriteBufferFromS3TaskTracker.h"
#include <Common/ThreadPoolTaskTracker.h>
#include <Common/logger_useful.h>
#include <Common/ProfileEvents.h>
#include <Common/Throttler.h>
@ -72,6 +72,19 @@ struct WriteBufferFromS3::PartData
}
};
BufferAllocationPolicyPtr createBufferAllocationPolicy(const S3Settings::RequestSettings::PartUploadSettings & settings)
{
BufferAllocationPolicy::Settings allocation_settings;
allocation_settings.strict_size = settings.strict_upload_part_size;
allocation_settings.min_size = settings.min_upload_part_size;
allocation_settings.max_size = settings.max_upload_part_size;
allocation_settings.multiply_factor = settings.upload_part_size_multiply_factor;
allocation_settings.multiply_parts_count_threshold = settings.upload_part_size_multiply_parts_count_threshold;
allocation_settings.max_single_size = settings.max_single_part_upload_size;
return BufferAllocationPolicy::create(allocation_settings);
}
WriteBufferFromS3::WriteBufferFromS3(
std::shared_ptr<const S3::Client> client_ptr_,
@ -91,9 +104,9 @@ WriteBufferFromS3::WriteBufferFromS3(
, write_settings(write_settings_)
, client_ptr(std::move(client_ptr_))
, object_metadata(std::move(object_metadata_))
, buffer_allocation_policy(ChooseBufferPolicy(upload_settings))
, buffer_allocation_policy(createBufferAllocationPolicy(upload_settings))
, task_tracker(
std::make_unique<WriteBufferFromS3::TaskTracker>(
std::make_unique<TaskTracker>(
std::move(schedule_),
upload_settings.max_inflight_parts_for_one_file,
limitedLog))
@ -320,14 +333,6 @@ void WriteBufferFromS3::detachBuffer()
detached_part_data.push_back({std::move(buf), data_size});
}
void WriteBufferFromS3::allocateFirstBuffer()
{
const auto max_first_buffer = buffer_allocation_policy->getBufferSize();
const auto size = std::min(size_t(DBMS_DEFAULT_BUFFER_SIZE), max_first_buffer);
memory = Memory(size);
WriteBuffer::set(memory.data(), memory.size());
}
void WriteBufferFromS3::allocateBuffer()
{
buffer_allocation_policy->nextBuffer();
@ -340,6 +345,14 @@ void WriteBufferFromS3::allocateBuffer()
WriteBuffer::set(memory.data(), memory.size());
}
void WriteBufferFromS3::allocateFirstBuffer()
{
const auto max_first_buffer = buffer_allocation_policy->getBufferSize();
const auto size = std::min(size_t(DBMS_DEFAULT_BUFFER_SIZE), max_first_buffer);
memory = Memory(size);
WriteBuffer::set(memory.data(), memory.size());
}
void WriteBufferFromS3::setFakeBufferWhenPreFinalized()
{
WriteBuffer::set(fake_buffer_when_prefinalized, sizeof(fake_buffer_when_prefinalized));

View File

@ -12,6 +12,8 @@
#include <Storages/StorageS3Settings.h>
#include <Common/threadPoolCallbackRunner.h>
#include <IO/S3/BlobStorageLogWriter.h>
#include <Common/ThreadPoolTaskTracker.h>
#include <Common/BufferAllocationPolicy.h>
#include <memory>
#include <vector>
@ -26,6 +28,8 @@ namespace DB
* Data is divided on chunks with size greater than 'minimum_upload_part_size'. Last chunk can be less than this threshold.
* Each chunk is written as a part to S3.
*/
class TaskTracker;
class WriteBufferFromS3 final : public WriteBufferFromFileBase
{
public:
@ -46,18 +50,6 @@ public:
std::string getFileName() const override { return key; }
void sync() override { next(); }
class IBufferAllocationPolicy
{
public:
virtual size_t getBufferNumber() const = 0;
virtual size_t getBufferSize() const = 0;
virtual void nextBuffer() = 0;
virtual ~IBufferAllocationPolicy() = 0;
};
using IBufferAllocationPolicyPtr = std::unique_ptr<IBufferAllocationPolicy>;
static IBufferAllocationPolicyPtr ChooseBufferPolicy(const S3Settings::RequestSettings::PartUploadSettings & settings_);
private:
/// Receives response from the server after sending all data.
void finalizeImpl() override;
@ -67,10 +59,10 @@ private:
struct PartData;
void hidePartialData();
void allocateFirstBuffer();
void reallocateFirstBuffer();
void detachBuffer();
void allocateBuffer();
void allocateFirstBuffer();
void setFakeBufferWhenPreFinalized();
S3::UploadPartRequest getUploadRequest(size_t part_number, PartData & data);
@ -94,7 +86,7 @@ private:
LoggerPtr log = getLogger("WriteBufferFromS3");
LogSeriesLimiterPtr limitedLog = std::make_shared<LogSeriesLimiter>(log, 1, 5);
IBufferAllocationPolicyPtr buffer_allocation_policy;
BufferAllocationPolicyPtr buffer_allocation_policy;
/// Upload in S3 is made in parts.
/// We initiate upload, then upload each part and get ETag as a response, and then finalizeImpl() upload with listing all our parts.
@ -119,7 +111,6 @@ private:
size_t total_size = 0;
size_t hidden_size = 0;
class TaskTracker;
std::unique_ptr<TaskTracker> task_tracker;
BlobStorageLogWriterPtr blob_log;

View File

@ -5,6 +5,7 @@
#include <IO/WriteHelpers.h>
#include <Core/ProtocolDefines.h>
#include <base/getFQDNOrHostName.h>
#include <Poco/Net/HTTPRequest.h>
#include <unistd.h>
#include <Common/config_version.h>
@ -255,7 +256,29 @@ String toString(ClientInfo::Interface interface)
return "TCP_INTERSERVER";
}
return std::format("Unknown {}!\n", static_cast<int>(interface));
return std::format("Unknown server interface ({}).", static_cast<int>(interface));
}
void ClientInfo::setFromHTTPRequest(const Poco::Net::HTTPRequest & request)
{
http_method = ClientInfo::HTTPMethod::UNKNOWN;
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET)
http_method = ClientInfo::HTTPMethod::GET;
else if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
http_method = ClientInfo::HTTPMethod::POST;
http_user_agent = request.get("User-Agent", "");
http_referer = request.get("Referer", "");
forwarded_for = request.get("X-Forwarded-For", "");
for (const auto & header : request)
{
/// These headers can contain authentication info and shouldn't be accessible by the user.
String key_lowercase = Poco::toLower(header.first);
if (key_lowercase.starts_with("x-clickhouse") || key_lowercase == "authentication")
continue;
http_headers[header.first] = header.second;
}
}
}

View File

@ -7,6 +7,12 @@
#include <Common/VersionNumber.h>
#include <boost/algorithm/string/trim.hpp>
namespace Poco::Net
{
class HTTPRequest;
}
namespace DB
{
@ -93,6 +99,7 @@ public:
HTTPMethod http_method = HTTPMethod::UNKNOWN;
String http_user_agent;
String http_referer;
std::unordered_map<String, String> http_headers;
/// For mysql and postgresql
UInt64 connection_id = 0;
@ -135,6 +142,9 @@ public:
/// Initialize parameters on client initiating query.
void setInitialQuery();
/// Initialize parameters related to HTTP request.
void setFromHTTPRequest(const Poco::Net::HTTPRequest & request);
bool clientVersionEquals(const ClientInfo & other, bool compare_patch) const;
String getVersionStr() const;

View File

@ -2490,7 +2490,8 @@ AsyncLoader & Context::getAsyncLoader() const
}
},
/* log_failures = */ true,
/* log_progress = */ true);
/* log_progress = */ true,
/* log_events = */ true);
});
return *shared->async_loader;
@ -4640,11 +4641,9 @@ void Context::setClientConnectionId(uint32_t connection_id_)
client_info.connection_id = connection_id_;
}
void Context::setHTTPClientInfo(ClientInfo::HTTPMethod http_method, const String & http_user_agent, const String & http_referer)
void Context::setHTTPClientInfo(const Poco::Net::HTTPRequest & request)
{
client_info.http_method = http_method;
client_info.http_user_agent = http_user_agent;
client_info.http_referer = http_referer;
client_info.setFromHTTPRequest(request);
need_recalculate_access = true;
}

View File

@ -642,7 +642,7 @@ public:
void setClientInterface(ClientInfo::Interface interface);
void setClientVersion(UInt64 client_version_major, UInt64 client_version_minor, UInt64 client_version_patch, unsigned client_tcp_protocol_version);
void setClientConnectionId(uint32_t connection_id);
void setHTTPClientInfo(ClientInfo::HTTPMethod http_method, const String & http_user_agent, const String & http_referer);
void setHTTPClientInfo(const Poco::Net::HTTPRequest & request);
void setForwardedFor(const String & forwarded_for);
void setQueryKind(ClientInfo::QueryKind query_kind);
void setQueryKindInitial();

View File

@ -1881,7 +1881,7 @@ void InterpreterCreateQuery::addColumnsDescriptionToCreateQueryIfNecessary(ASTCr
void InterpreterCreateQuery::processSQLSecurityOption(ContextPtr context_, ASTSQLSecurity & sql_security, bool is_attach, bool is_materialized_view)
{
/// If no SQL security is specified, apply default from default_*_view_sql_security setting.
if (!sql_security.type.has_value())
if (!sql_security.type)
{
SQLSecurityType default_security;

View File

@ -13,7 +13,6 @@
#include <Parsers/ASTTablesInSelectQuery.h>
#include <Parsers/ExpressionListParsers.h>
#include <Parsers/parseQuery.h>
#include <Parsers/FunctionParameterValuesVisitor.h>
#include <Access/Common/AccessFlags.h>
#include <Access/ContextAccess.h>
@ -73,7 +72,6 @@
#include <Processors/Transforms/FilterTransform.h>
#include <QueryPipeline/QueryPipelineBuilder.h>
#include <Storages/IStorage.h>
#include <Storages/MergeTree/MergeTreeWhereOptimizer.h>
#include <Storages/StorageDistributed.h>
#include <Storages/StorageDummy.h>
@ -85,7 +83,6 @@
#include <Core/ColumnNumbers.h>
#include <Core/Field.h>
#include <Core/ProtocolDefines.h>
#include <Functions/IFunction.h>
#include <Interpreters/Aggregator.h>
#include <Interpreters/IJoin.h>
#include <QueryPipeline/SizeLimits.h>

View File

@ -429,18 +429,12 @@ void Session::setClientConnectionId(uint32_t connection_id)
prepared_client_info->connection_id = connection_id;
}
void Session::setHTTPClientInfo(ClientInfo::HTTPMethod http_method, const String & http_user_agent, const String & http_referer)
void Session::setHTTPClientInfo(const Poco::Net::HTTPRequest & request)
{
if (session_context)
{
session_context->setHTTPClientInfo(http_method, http_user_agent, http_referer);
}
session_context->setHTTPClientInfo(request);
else
{
prepared_client_info->http_method = http_method;
prepared_client_info->http_user_agent = http_user_agent;
prepared_client_info->http_referer = http_referer;
}
prepared_client_info->setFromHTTPRequest(request);
}
void Session::setForwardedFor(const String & forwarded_for)

View File

@ -65,7 +65,7 @@ public:
void setClientInterface(ClientInfo::Interface interface);
void setClientVersion(UInt64 client_version_major, UInt64 client_version_minor, UInt64 client_version_patch, unsigned client_tcp_protocol_version);
void setClientConnectionId(uint32_t connection_id);
void setHTTPClientInfo(ClientInfo::HTTPMethod http_method, const String & http_user_agent, const String & http_referer);
void setHTTPClientInfo(const Poco::Net::HTTPRequest & request);
void setForwardedFor(const String & forwarded_for);
void setQuotaClientKey(const String & quota_key);
void setConnectionClientVersion(UInt64 client_version_major, UInt64 client_version_minor, UInt64 client_version_patch, unsigned client_tcp_protocol_version);

View File

@ -131,7 +131,7 @@ ColumnsDescription ZooKeeperLogElement::getColumnsDescription()
{"address", DataTypeFactory::instance().get("IPv6"), "IP address of ZooKeeper server that was used to make the request."},
{"port", std::make_shared<DataTypeUInt16>(), "The port of ZooKeeper server that was used to make the request."},
{"session_id", std::make_shared<DataTypeInt64>(), "The session ID that the ZooKeeper server sets for each connection."},
{"duration_ms", std::make_shared<DataTypeUInt64>(), "The time taken by ZooKeeper to execute the request."},
{"duration_microseconds", std::make_shared<DataTypeUInt64>(), "The time taken by ZooKeeper to execute the request."},
{"xid", std::make_shared<DataTypeInt32>(), "The ID of the request within the session. This is usually a sequential request number. It is the same for the request row and the paired response/finalize row."},
{"has_watch", std::make_shared<DataTypeUInt8>(), "The request whether the watch has been set."},
@ -183,7 +183,7 @@ void ZooKeeperLogElement::appendToBlock(MutableColumns & columns) const
columns[i++]->insertData(IPv6ToBinary(address.host()).data(), 16);
columns[i++]->insert(address.port());
columns[i++]->insert(session_id);
columns[i++]->insert(duration_ms);
columns[i++]->insert(duration_microseconds);
columns[i++]->insert(xid);
columns[i++]->insert(has_watch);

View File

@ -28,7 +28,7 @@ struct ZooKeeperLogElement
Poco::Net::SocketAddress address;
Int64 session_id = 0;
UInt64 duration_ms = 0;
UInt64 duration_microseconds = 0;
/// Common request info
Int32 xid = 0;

View File

@ -14,7 +14,7 @@ namespace DB
void ASTSQLSecurity::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
{
if (!type.has_value())
if (!type)
return;
if (definer || is_definer_current_user)

View File

@ -299,6 +299,7 @@ namespace DB
MR_MACROS(MOD, "MOD") \
MR_MACROS(MODIFY_COLUMN, "MODIFY COLUMN") \
MR_MACROS(MODIFY_COMMENT, "MODIFY COMMENT") \
MR_MACROS(MODIFY_DEFINER, "MODIFY DEFINER") \
MR_MACROS(MODIFY_ORDER_BY, "MODIFY ORDER BY") \
MR_MACROS(MODIFY_QUERY, "MODIFY QUERY") \
MR_MACROS(MODIFY_REFRESH, "MODIFY REFRESH") \
@ -445,6 +446,7 @@ namespace DB
MR_MACROS(SPATIAL, "SPATIAL") \
MR_MACROS(SQL_SECURITY, "SQL SECURITY") \
MR_MACROS(SS, "SS") \
MR_MACROS(START_TRANSACTION, "START TRANSACTION") \
MR_MACROS(STATISTIC, "STATISTIC") \
MR_MACROS(STEP, "STEP") \
MR_MACROS(STORAGE, "STORAGE") \
@ -554,7 +556,7 @@ namespace DB
MR_MACROS(SSH_KEY, "SSH_KEY") \
MR_MACROS(SSL_CERTIFICATE, "SSL_CERTIFICATE") \
MR_MACROS(STRICTLY_ASCENDING, "STRICTLY_ASCENDING") \
MR_MACROS(WITH_ITEMINDEX, "with_itemindex") \
MR_MACROS(WITH_ITEMINDEX, "WITH_ITEMINDEX") \
enum class Keyword : size_t
{

View File

@ -41,6 +41,7 @@ bool ParserAlterCommand::parseImpl(Pos & pos, ASTPtr & node, Expected & expected
ParserKeyword s_reset_setting(Keyword::RESET_SETTING);
ParserKeyword s_modify_query(Keyword::MODIFY_QUERY);
ParserKeyword s_modify_sql_security(Keyword::MODIFY_SQL_SECURITY);
ParserKeyword s_modify_definer(Keyword::MODIFY_DEFINER);
ParserKeyword s_modify_refresh(Keyword::MODIFY_REFRESH);
ParserKeyword s_add_index(Keyword::ADD_INDEX);
@ -862,11 +863,16 @@ bool ParserAlterCommand::parseImpl(Pos & pos, ASTPtr & node, Expected & expected
return false;
command->type = ASTAlterCommand::MODIFY_QUERY;
}
else if (s_modify_sql_security.ignore(pos, expected))
else if (s_modify_sql_security.checkWithoutMoving(pos, expected))
{
/// This is a hack so we can reuse parser from create and don't have to write `MODIFY SQL SECURITY SQL SECURITY INVOKER`
--pos;
--pos;
s_modify.ignore(pos, expected);
if (!sql_security_p.parse(pos, command_sql_security, expected))
return false;
command->type = ASTAlterCommand::MODIFY_SQL_SECURITY;
}
else if (s_modify_definer.checkWithoutMoving(pos, expected))
{
s_modify.ignore(pos, expected);
if (!sql_security_p.parse(pos, command_sql_security, expected))
return false;
command->type = ASTAlterCommand::MODIFY_SQL_SECURITY;

View File

@ -14,6 +14,8 @@ bool ParserTransactionControl::parseImpl(Pos & pos, ASTPtr & node, Expected & ex
if (ParserKeyword(Keyword::BEGIN_TRANSACTION).ignore(pos, expected))
action = ASTTransactionControl::BEGIN;
else if (ParserKeyword(Keyword::START_TRANSACTION).ignore(pos, expected))
action = ASTTransactionControl::BEGIN;
else if (ParserKeyword(Keyword::COMMIT).ignore(pos, expected))
action = ASTTransactionControl::COMMIT;
else if (ParserKeyword(Keyword::ROLLBACK).ignore(pos, expected))

View File

@ -291,11 +291,14 @@ void PrettyBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port_kind
{
// Write row number;
auto row_num_string = std::to_string(i + 1 + total_rows) + ". ";
for (size_t j = 0; j < row_number_width - row_num_string.size(); ++j)
{
writeCString(" ", out);
}
writeChar(' ', out);
if (color)
writeCString("\033[90m", out);
writeString(row_num_string, out);
if (color)
writeCString("\033[0m", out);
}
writeCString(grid_symbols.bar, out);

View File

@ -147,10 +147,12 @@ void PrettyCompactBlockOutputFormat::writeRow(
// Write row number;
auto row_num_string = std::to_string(row_num + 1 + total_rows) + ". ";
for (size_t i = 0; i < row_number_width - row_num_string.size(); ++i)
{
writeCString(" ", out);
}
writeChar(' ', out);
if (color)
writeCString("\033[90m", out);
writeString(row_num_string, out);
if (color)
writeCString("\033[0m", out);
}
const GridSymbols & grid_symbols = format_settings.pretty.charset == FormatSettings::Pretty::Charset::UTF8 ?

View File

@ -77,8 +77,13 @@ void PrettySpaceBlockOutputFormat::writeChunk(const Chunk & chunk, PortKind port
// Write row number;
auto row_num_string = std::to_string(row + 1 + total_rows) + ". ";
for (size_t i = 0; i < row_number_width - row_num_string.size(); ++i)
writeCString(" ", out);
writeChar(' ', out);
if (color)
writeCString("\033[90m", out);
writeString(row_num_string, out);
if (color)
writeCString("\033[0m", out);
}
for (size_t column = 0; column < num_columns; ++column)
{

View File

@ -10,6 +10,7 @@
#include <base/arithmeticOverflow.h>
#include <Columns/ColumnConst.h>
#include <Columns/ColumnAggregateFunction.h>
#include <Columns/ColumnNullable.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/getLeastSupertype.h>
#include <DataTypes/DataTypeLowCardinality.h>
@ -172,6 +173,79 @@ static int compareValuesWithOffsetFloat(const IColumn * _compared_column,
return result;
}
// Helper macros to dispatch on type of the ORDER BY column
#define APPLY_FOR_ONE_NEST_TYPE(FUNCTION, TYPE) \
else if (typeid_cast<const TYPE *>(nest_compared_column.get())) \
{ \
/* clang-tidy you're dumb, I can't put FUNCTION in braces here. */ \
nest_compare_function = FUNCTION<TYPE>; /* NOLINT */ \
}
#define APPLY_FOR_NEST_TYPES(FUNCTION) \
if (false) /* NOLINT */ \
{ \
/* Do nothing, a starter condition. */ \
} \
APPLY_FOR_ONE_NEST_TYPE(FUNCTION, ColumnVector<UInt8>) \
APPLY_FOR_ONE_NEST_TYPE(FUNCTION, ColumnVector<UInt16>) \
APPLY_FOR_ONE_NEST_TYPE(FUNCTION, ColumnVector<UInt32>) \
APPLY_FOR_ONE_NEST_TYPE(FUNCTION, ColumnVector<UInt64>) \
\
APPLY_FOR_ONE_NEST_TYPE(FUNCTION, ColumnVector<Int8>) \
APPLY_FOR_ONE_NEST_TYPE(FUNCTION, ColumnVector<Int16>) \
APPLY_FOR_ONE_NEST_TYPE(FUNCTION, ColumnVector<Int32>) \
APPLY_FOR_ONE_NEST_TYPE(FUNCTION, ColumnVector<Int64>) \
APPLY_FOR_ONE_NEST_TYPE(FUNCTION, ColumnVector<Int128>) \
\
APPLY_FOR_ONE_NEST_TYPE(FUNCTION##Float, ColumnVector<Float32>) \
APPLY_FOR_ONE_NEST_TYPE(FUNCTION##Float, ColumnVector<Float64>) \
\
else \
{ \
throw Exception(ErrorCodes::NOT_IMPLEMENTED, \
"The RANGE OFFSET frame for '{}' ORDER BY nest column is not implemented", \
demangle(typeid(nest_compared_column).name())); \
}
// A specialization of compareValuesWithOffset for nullable.
template <typename ColumnType>
static int compareValuesWithOffsetNullable(const IColumn * _compared_column,
size_t compared_row, const IColumn * _reference_column,
size_t reference_row,
const Field & _offset,
bool offset_is_preceding)
{
const auto * compared_column = assert_cast<const ColumnType *>(
_compared_column);
const auto * reference_column = assert_cast<const ColumnType *>(
_reference_column);
if (compared_column->isNullAt(compared_row) && !reference_column->isNullAt(reference_row))
{
return -1;
}
else if (compared_column->isNullAt(compared_row) && reference_column->isNullAt(reference_row))
{
return 0;
}
else if (!compared_column->isNullAt(compared_row) && reference_column->isNullAt(reference_row))
{
return 1;
}
ColumnPtr nest_compared_column = compared_column->getNestedColumnPtr();
ColumnPtr nest_reference_column = reference_column->getNestedColumnPtr();
std::function<int(
const IColumn * compared_column, size_t compared_row,
const IColumn * reference_column, size_t reference_row,
const Field & offset,
bool offset_is_preceding)> nest_compare_function;
APPLY_FOR_NEST_TYPES(compareValuesWithOffset)
return nest_compare_function(nest_compared_column.get(), compared_row,
nest_reference_column.get(), reference_row, _offset, offset_is_preceding);
}
// Helper macros to dispatch on type of the ORDER BY column
#define APPLY_FOR_ONE_TYPE(FUNCTION, TYPE) \
else if (typeid_cast<const TYPE *>(column)) \
@ -199,6 +273,7 @@ APPLY_FOR_ONE_TYPE(FUNCTION, ColumnVector<Int128>) \
APPLY_FOR_ONE_TYPE(FUNCTION##Float, ColumnVector<Float32>) \
APPLY_FOR_ONE_TYPE(FUNCTION##Float, ColumnVector<Float64>) \
\
APPLY_FOR_ONE_TYPE(FUNCTION##Nullable, ColumnNullable) \
else \
{ \
throw Exception(ErrorCodes::NOT_IMPLEMENTED, \

View File

@ -490,14 +490,7 @@ bool HTTPHandler::authenticateUser(
/// Set client info. It will be used for quota accounting parameters in 'setUser' method.
ClientInfo::HTTPMethod http_method = ClientInfo::HTTPMethod::UNKNOWN;
if (request.getMethod() == HTTPServerRequest::HTTP_GET)
http_method = ClientInfo::HTTPMethod::GET;
else if (request.getMethod() == HTTPServerRequest::HTTP_POST)
http_method = ClientInfo::HTTPMethod::POST;
session->setHTTPClientInfo(http_method, request.get("User-Agent", ""), request.get("Referer", ""));
session->setForwardedFor(request.get("X-Forwarded-For", ""));
session->setHTTPClientInfo(request);
session->setQuotaClientKey(quota_key);
/// Extract the last entry from comma separated list of forwarded_for addresses.

View File

@ -1352,8 +1352,9 @@ void IMergeTreeDataPart::loadExistingRowsCount()
if (existing_rows_count.has_value())
return;
if (!rows_count || !storage.getSettings()->load_existing_rows_count_for_old_parts || !supportLightweightDeleteMutate()
|| !hasLightweightDelete())
if (!rows_count || !supportLightweightDeleteMutate() || !hasLightweightDelete()
|| !storage.getSettings()->exclude_deleted_rows_for_part_size_in_merge
|| !storage.getSettings()->load_existing_rows_count_for_old_parts)
existing_rows_count = rows_count;
else
existing_rows_count = readExistingRowsCount();

View File

@ -673,7 +673,8 @@ private:
/// For the older format version calculates rows count from the size of a column with a fixed size.
void loadRowsCount();
/// Load existing rows count from _row_exists column if load_existing_rows_count_for_old_parts is true.
/// Load existing rows count from _row_exists column
/// if load_existing_rows_count_for_old_parts and exclude_deleted_rows_for_part_size_in_merge are both enabled.
void loadExistingRowsCount();
static void appendFilesOfRowsCount(Strings & files);

View File

@ -93,6 +93,7 @@ struct ReplicatedMergeTreeLogEntryData
MergeTreeDataPartFormat new_part_format;
String block_id; /// For parts of level zero, the block identifier for deduplication (node name in /blocks/).
mutable String actual_new_part_name; /// GET_PART could actually fetch a part covering 'new_part_name'.
mutable std::unordered_set<String> replace_range_actual_new_part_names; /// Same as above, but for REPLACE_RANGE
UUID new_part_uuid = UUIDHelpers::Nil;
Strings source_parts;

View File

@ -342,6 +342,11 @@ void ReplicatedMergeTreeQueue::updateStateOnQueueEntryRemoval(
/// NOTE actual_new_part_name is very confusing and error-prone. This approach must be fixed.
removeCoveredPartsFromMutations(entry->actual_new_part_name, /*remove_part = */ false, /*remove_covered_parts = */ true);
}
for (const auto & actual_part : entry->replace_range_actual_new_part_names)
{
LOG_TEST(log, "Entry {} has actual new part name {}, removing it from mutations", entry->znode_name, actual_part);
removeCoveredPartsFromMutations(actual_part, /*remove_part = */ false, /*remove_covered_parts = */ true);
}
LOG_TEST(log, "Adding parts [{}] to current parts", fmt::join(entry_virtual_parts, ", "));
@ -1180,9 +1185,9 @@ bool ReplicatedMergeTreeQueue::isCoveredByFuturePartsImpl(const LogEntry & entry
if (entry_for_same_part_it != future_parts.end())
{
const LogEntry & another_entry = *entry_for_same_part_it->second;
constexpr auto fmt_string = "Not executing log entry {} of type {} for part {} "
constexpr auto fmt_string = "Not executing log entry {} of type {} for part {} (actual part {})"
"because another log entry {} of type {} for the same part ({}) is being processed.";
LOG_INFO(LogToStr(out_reason, log), fmt_string, entry.znode_name, entry.type, entry.new_part_name,
LOG_INFO(LogToStr(out_reason, log), fmt_string, entry.znode_name, entry.type, entry.new_part_name, new_part_name,
another_entry.znode_name, another_entry.type, another_entry.new_part_name);
return true;
@ -1198,6 +1203,7 @@ bool ReplicatedMergeTreeQueue::isCoveredByFuturePartsImpl(const LogEntry & entry
auto result_part = MergeTreePartInfo::fromPartName(new_part_name, format_version);
/// It can slow down when the size of `future_parts` is large. But it can not be large, since background pool is limited.
/// (well, it can actually, thanks to REPLACE_RANGE, but it's a rare case)
for (const auto & future_part_elem : future_parts)
{
auto future_part = MergeTreePartInfo::fromPartName(future_part_elem.first, format_version);
@ -1608,26 +1614,39 @@ void ReplicatedMergeTreeQueue::CurrentlyExecuting::setActualPartName(
std::unique_lock<std::mutex> & state_lock,
std::vector<LogEntryPtr> & covered_entries_to_wait)
{
if (!entry.actual_new_part_name.empty())
throw Exception(ErrorCodes::LOGICAL_ERROR, "Entry actual part isn't empty yet. This is a bug.");
if (actual_part_name.empty())
throw Exception(ErrorCodes::LOGICAL_ERROR, "Actual part name is empty");
entry.actual_new_part_name = actual_part_name;
if (!entry.actual_new_part_name.empty())
throw Exception(ErrorCodes::LOGICAL_ERROR, "Entry {} actual part isn't empty yet: '{}'. This is a bug.",
entry.znode_name, entry.actual_new_part_name);
auto actual_part_info = MergeTreePartInfo::fromPartName(actual_part_name, queue.format_version);
for (const auto & other_part_name : entry.replace_range_actual_new_part_names)
if (!MergeTreePartInfo::fromPartName(other_part_name, queue.format_version).isDisjoint(actual_part_info))
throw Exception(ErrorCodes::LOGICAL_ERROR, "Entry {} already has actual part {} non-disjoint with {}. This is a bug.",
entry.actual_new_part_name, other_part_name, actual_part_name);
/// Check if it is the same (and already added) part.
if (entry.actual_new_part_name == entry.new_part_name)
if (actual_part_name == entry.new_part_name)
return;
if (!queue.future_parts.emplace(entry.actual_new_part_name, entry.shared_from_this()).second)
if (!queue.future_parts.emplace(actual_part_name, entry.shared_from_this()).second)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Attaching already existing future part {}. This is a bug. "
"It happened on attempt to execute {}: {}",
entry.actual_new_part_name, entry.znode_name, entry.toString());
actual_part_name, entry.znode_name, entry.toString());
if (entry.type == LogEntry::REPLACE_RANGE)
entry.replace_range_actual_new_part_names.insert(actual_part_name);
else
entry.actual_new_part_name = actual_part_name;
for (LogEntryPtr & covered_entry : covered_entries_to_wait)
{
if (&entry == covered_entry.get())
continue;
LOG_TRACE(queue.log, "Waiting for {} producing {} to finish before executing {} producing not disjoint part {}",
covered_entry->znode_name, covered_entry->new_part_name, entry.znode_name, entry.new_part_name);
LOG_TRACE(queue.log, "Waiting for {} producing {} to finish before executing {} producing not disjoint part {} (actual part {})",
covered_entry->znode_name, covered_entry->new_part_name, entry.znode_name, entry.new_part_name, actual_part_name);
covered_entry->execution_complete.wait(state_lock, [&covered_entry] { return !covered_entry->currently_executing; });
}
}
@ -1646,25 +1665,27 @@ ReplicatedMergeTreeQueue::CurrentlyExecuting::~CurrentlyExecuting()
entry->currently_executing = false;
entry->execution_complete.notify_all();
for (const String & new_part_name : entry->getVirtualPartNames(queue.format_version))
auto erase_and_check = [this](const String & part_name)
{
if (!queue.future_parts.erase(new_part_name))
if (!queue.future_parts.erase(part_name))
{
LOG_ERROR(queue.log, "Untagging already untagged future part {}. This is a bug.", new_part_name);
LOG_ERROR(queue.log, "Untagging already untagged future part {}. This is a bug.", part_name);
assert(false);
}
}
};
for (const String & new_part_name : entry->getVirtualPartNames(queue.format_version))
erase_and_check(new_part_name);
if (!entry->actual_new_part_name.empty())
{
if (entry->actual_new_part_name != entry->new_part_name && !queue.future_parts.erase(entry->actual_new_part_name))
{
LOG_ERROR(queue.log, "Untagging already untagged future part {}. This is a bug.", entry->actual_new_part_name);
assert(false);
}
erase_and_check(entry->actual_new_part_name);
entry->actual_new_part_name.clear();
}
entry->actual_new_part_name.clear();
for (const auto & actual_part : entry->replace_range_actual_new_part_names)
erase_and_check(actual_part);
entry->replace_range_actual_new_part_names.clear();
}

View File

@ -94,6 +94,8 @@ void StorageInMemoryMetadata::setSQLSecurity(const ASTSQLSecurity & sql_security
{
if (sql_security.definer)
definer = sql_security.definer->toString();
else
definer = std::nullopt;
sql_security_type = sql_security.type;
}

View File

@ -604,7 +604,12 @@ void StorageReplicatedMergeTree::waitMutationToFinishOnReplicas(
break;
}
/// Here we check mutation for errors on local replica. If they happen on this replica
/// they will happen on each replica, so we can check only in-memory info.
auto mutation_status = queue.getIncompleteMutationsStatus(mutation_id);
String mutation_pointer = fs::path(zookeeper_path) / "replicas" / replica / "mutation_pointer";
std::string mutation_pointer_value;
/// Replica could be removed
if (!zookeeper->tryGet(mutation_pointer, mutation_pointer_value, nullptr, wait_event))
@ -613,18 +618,31 @@ void StorageReplicatedMergeTree::waitMutationToFinishOnReplicas(
break;
}
else if (mutation_pointer_value >= mutation_id) /// Maybe we already processed more fresh mutation
break; /// (numbers like 0000000000 and 0000000001)
{
bool mutation_killed_or_done_locally = !mutation_status || mutation_status->is_done;
if (mutation_killed_or_done_locally)
{
LOG_TRACE(log, "Mutation {} is done because mutation pointer is {}", mutation_id, mutation_pointer_value);
break; /// (numbers like 0000000000 and 0000000001)
}
else
{
LOG_TRACE(log, "Mutation {} is done because mutation pointer is {}, but state is not updated in memory, will wait", mutation_id, mutation_pointer_value);
}
}
/// Replica can become inactive, so wait with timeout and recheck it
if (wait_event->tryWait(1000))
continue;
/// Here we check mutation for errors on local replica. If they happen on this replica
/// they will happen on each replica, so we can check only in-memory info.
auto mutation_status = queue.getIncompleteMutationsStatus(mutation_id);
/// If mutation status is empty, than local replica may just not loaded it into memory.
if (mutation_status && !mutation_status->latest_fail_reason.empty())
{
LOG_DEBUG(log, "Mutation {} is done {} or failed {} (status: '{}')", mutation_id, mutation_status->is_done, !mutation_status->latest_fail_reason.empty(), mutation_status->latest_fail_reason);
break;
}
/// Replica can become inactive, so wait with timeout, if nothing happened -> recheck it
if (!wait_event->tryWait(1000))
{
LOG_TRACE(log, "Failed to wait for mutation '{}', will recheck", mutation_id);
}
}
/// This replica inactive, don't check anything
@ -655,6 +673,8 @@ void StorageReplicatedMergeTree::waitMutationToFinishOnReplicas(
/// they will happen on each replica, so we can check only in-memory info.
auto mutation_status = queue.getIncompleteMutationsStatus(mutation_id, &mutation_ids);
checkMutationStatus(mutation_status, mutation_ids);
/// Mutation should be done or we should throw exception
chassert(mutation_status->is_done);
}
if (!inactive_replicas.empty())

View File

@ -306,7 +306,8 @@ TEST(TransformQueryForExternalDatabase, Aliases)
check(state, 1, {"field"},
"SELECT field AS value, field AS display FROM table WHERE field NOT IN ('') AND display LIKE '%test%'",
R"(SELECT "field" FROM "test"."table" WHERE ("field" NOT IN ('')) AND ("field" LIKE '%test%'))");
R"(SELECT "field" FROM "test"."table" WHERE ("field" NOT IN ('')) AND ("field" LIKE '%test%'))",
R"(SELECT "field" FROM "test"."table" WHERE ("field" != '') AND ("field" LIKE '%test%'))");
}
TEST(TransformQueryForExternalDatabase, ForeignColumnInWhere)
@ -408,5 +409,6 @@ TEST(TransformQueryForExternalDatabase, Analyzer)
check(state, 1, {"column", "apply_id", "apply_type", "apply_status", "create_time", "field", "value", "a", "b", "foo"},
"SELECT * FROM table WHERE (column) IN (1)",
R"(SELECT "column", "apply_id", "apply_type", "apply_status", "create_time", "field", "value", "a", "b", "foo" FROM "test"."table" WHERE "column" IN (1))");
R"(SELECT "column", "apply_id", "apply_type", "apply_status", "create_time", "field", "value", "a", "b", "foo" FROM "test"."table" WHERE "column" IN (1))",
R"(SELECT "column", "apply_id", "apply_type", "apply_status", "create_time", "field", "value", "a", "b", "foo" FROM "test"."table" WHERE "column" = 1)");
}

View File

@ -1033,22 +1033,6 @@ def _print_results(result: Any, outfile: Optional[str], pretty: bool = False) ->
raise AssertionError(f"Unexpected type for 'res': {type(result)}")
def _check_and_update_for_early_style_check(jobs_data: dict, docker_data: dict) -> None:
"""
This is temporary hack to start style check before docker build if possible
FIXME: need better solution to do style check as soon as possible and as fast as possible w/o dependency on docker job
"""
jobs_to_do = jobs_data.get("jobs_to_do", [])
docker_to_build = docker_data.get("missing_multi", [])
if (
JobNames.STYLE_CHECK in jobs_to_do
and docker_to_build
and "clickhouse/style-test" not in docker_to_build
):
index = jobs_to_do.index(JobNames.STYLE_CHECK)
jobs_to_do[index] = "Style check early"
def _update_config_for_docs_only(jobs_data: dict) -> None:
DOCS_CHECK_JOBS = [JobNames.DOCS_CHECK, JobNames.STYLE_CHECK]
print(f"NOTE: Will keep only docs related jobs: [{DOCS_CHECK_JOBS}]")
@ -1306,6 +1290,12 @@ def _configure_jobs(
if params["num_batches"] > 1:
params["batches"] = list(requested_batches)
if pr_info.is_merge_queue():
# FIXME: Quick support for MQ workflow which is only StyleCheck for now
jobs_to_do = [JobNames.STYLE_CHECK]
jobs_to_skip = []
print(f"NOTE: This is Merge Queue CI: set jobs to do: [{jobs_to_do}]")
return {
"digests": digests,
"jobs_to_do": jobs_to_do,
@ -1752,11 +1742,6 @@ def main() -> int:
else {}
)
# # FIXME: Early style check manipulates with job names might be not robust with await feature
# if pr_info.number != 0:
# # FIXME: it runs style check before docker build if possible (style-check images is not changed)
# # find a way to do style check always before docker build and others
# _check_and_update_for_early_style_check(jobs_data, docker_data)
if not args.skip_jobs and pr_info.has_changes_in_documentation_only():
_update_config_for_docs_only(jobs_data)

View File

@ -220,7 +220,7 @@ class JobConfig:
digest: DigestConfig = field(default_factory=DigestConfig)
# will be triggered for the job if omited in CI workflow yml
run_command: str = ""
# job timeout
# job timeout, seconds
timeout: Optional[int] = None
# sets number of batches for multi-batch job
num_batches: int = 1
@ -517,10 +517,11 @@ clickbench_test_params = {
),
"run_command": 'clickbench.py "$CHECK_NAME"',
}
install_test_params = {
"digest": install_check_digest,
"run_command": 'install_check.py "$CHECK_NAME"',
}
install_test_params = JobConfig(
digest=install_check_digest,
run_command='install_check.py "$CHECK_NAME"',
timeout=900,
)
@dataclass
@ -1105,10 +1106,10 @@ CI_CONFIG = CIConfig(
},
test_configs={
JobNames.INSTALL_TEST_AMD: TestConfig(
Build.PACKAGE_RELEASE, job_config=JobConfig(**install_test_params) # type: ignore
Build.PACKAGE_RELEASE, job_config=install_test_params
),
JobNames.INSTALL_TEST_ARM: TestConfig(
Build.PACKAGE_AARCH64, job_config=JobConfig(**install_test_params) # type: ignore
Build.PACKAGE_AARCH64, job_config=install_test_params
),
JobNames.STATEFUL_TEST_ASAN: TestConfig(
Build.PACKAGE_ASAN, job_config=JobConfig(**stateful_test_common_params) # type: ignore

View File

@ -1,5 +1,6 @@
from contextlib import contextmanager
import os
import signal
from typing import Any, List, Union, Iterator
from pathlib import Path
@ -48,3 +49,14 @@ class GHActions:
for line in lines:
print(line)
print("::endgroup::")
def set_job_timeout():
def timeout_handler(_signum, _frame):
print("Timeout expired")
raise TimeoutError("Job's KILL_TIMEOUT expired")
kill_timeout = int(os.getenv("KILL_TIMEOUT", "0"))
assert kill_timeout > 0, "kill timeout must be provided in KILL_TIMEOUT env"
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(kill_timeout)

View File

@ -14,10 +14,11 @@ from build_download_helper import download_builds_filter
from compress_files import compress_fast
from docker_images_helper import DockerImage, pull_image, get_docker_image
from env_helper import REPORT_PATH, TEMP_PATH as TEMP
from env_helper import CI, REPORT_PATH, TEMP_PATH as TEMP
from report import JobReport, TestResults, TestResult, FAILURE, FAIL, OK, SUCCESS
from stopwatch import Stopwatch
from tee_popen import TeePopen
from ci_utils import set_job_timeout
RPM_IMAGE = "clickhouse/install-rpm-test"
@ -255,6 +256,9 @@ def main():
args = parse_args()
if CI:
set_job_timeout()
TEMP_PATH.mkdir(parents=True, exist_ok=True)
LOGS_PATH.mkdir(parents=True, exist_ok=True)

View File

@ -215,6 +215,7 @@ class PRInfo:
.replace("{base}", base_sha)
.replace("{head}", self.sha)
)
self.commit_html_url = f"{repo_prefix}/commits/{self.sha}"
elif "commits" in github_event:
self.event_type = EventType.PUSH

View File

@ -5,7 +5,7 @@ import time
import pytz
import uuid
import grpc
from helpers.cluster import ClickHouseCluster, run_and_check
from helpers.cluster import ClickHouseCluster, is_arm, run_and_check
from threading import Thread
import gzip
import lz4.frame
@ -20,6 +20,10 @@ import clickhouse_grpc_pb2, clickhouse_grpc_pb2_grpc # Execute pb2/generate.py
GRPC_PORT = 9100
DEFAULT_ENCODING = "utf-8"
# GRPC is disabled on ARM build - skip tests
if is_arm():
pytestmark = pytest.mark.skip
# Utilities

View File

@ -37,6 +37,7 @@ def generate_cluster_def(port):
<account_name>devstoreaccount1</account_name>
<account_key>Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==</account_key>
<max_single_part_upload_size>100000</max_single_part_upload_size>
<min_upload_part_size>100000</min_upload_part_size>
<max_single_download_retries>10</max_single_download_retries>
<max_single_read_retries>10</max_single_read_retries>
</blob_storage_disk>

View File

@ -5,9 +5,13 @@ from string import Template
import pymysql.cursors
import pytest
from helpers.client import QueryRuntimeException
from helpers.cluster import ClickHouseCluster
from helpers.cluster import ClickHouseCluster, is_arm
from helpers.network import PartitionManager
if is_arm():
pytestmark = pytest.mark.skip
cluster = ClickHouseCluster(__file__)
clickhouse_node = cluster.add_instance(
"node1",

View File

@ -16,6 +16,7 @@ from helpers.cluster import ClickHouseCluster, ClickHouseInstance
from helpers.network import PartitionManager
from helpers.mock_servers import start_mock_servers
from helpers.test_tools import exec_query_with_retry
from helpers.test_tools import assert_logs_contain_with_retry
@pytest.fixture(scope="module")
@ -1320,3 +1321,25 @@ def test_format_detection(cluster):
)
assert result == expected_result
def test_parallel_read(cluster):
node = cluster.instances["node"]
connection_string = cluster.env_variables["AZURITE_CONNECTION_STRING"]
storage_account_url = cluster.env_variables["AZURITE_STORAGE_ACCOUNT_URL"]
account_name = "devstoreaccount1"
account_key = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
azure_query(
node,
f"INSERT INTO TABLE FUNCTION azureBlobStorage('{storage_account_url}', 'cont', 'test_parallel_read.parquet', '{account_name}', '{account_key}') "
f"select * from numbers(10000) settings azure_truncate_on_insert=1",
)
time.sleep(1)
res = azure_query(
node,
f"select count() from azureBlobStorage('{connection_string}', 'cont', 'test_parallel_read.parquet')",
)
assert int(res) == 10000
assert_logs_contain_with_retry(node, "AzureBlobStorage readBigAt read bytes")

View File

@ -4452,7 +4452,7 @@ def test_block_based_formats_1(kafka_cluster):
kafka_group_name = '{topic}',
kafka_format = 'PrettySpace';
INSERT INTO test.kafka SELECT number * 10 as key, number * 100 as value FROM numbers(5) settings max_block_size=2, optimize_trivial_insert_select=0, output_format_pretty_color=1;
INSERT INTO test.kafka SELECT number * 10 as key, number * 100 as value FROM numbers(5) settings max_block_size=2, optimize_trivial_insert_select=0, output_format_pretty_color=1, output_format_pretty_row_numbers=0;
"""
)

View File

@ -3202,7 +3202,7 @@ def test_block_based_formats_1(rabbitmq_cluster):
)
instance.query(
"INSERT INTO test.rabbitmq SELECT number * 10 as key, number * 100 as value FROM numbers(5) settings max_block_size=2, optimize_trivial_insert_select=0, output_format_pretty_color=1;"
"INSERT INTO test.rabbitmq SELECT number * 10 as key, number * 100 as value FROM numbers(5) settings max_block_size=2, optimize_trivial_insert_select=0, output_format_pretty_color=1, output_format_pretty_row_numbers=0;"
)
insert_messages = []

View File

@ -67,8 +67,8 @@ def test_rollback_unfinished_on_restart1(start_cluster):
tx(1, "insert into mt values (5, 50)")
tx(1, "alter table mt update m = m+n in partition id '1' where 1")
# check that uncommitted insert will be rolled back on restart
tx(3, "begin transaction")
# check that uncommitted insert will be rolled back on restart (using `START TRANSACTION` syntax)
tx(3, "start transaction")
tid5 = tx(3, "select transactionID()").strip()
tx(3, "insert into mt values (6, 70)")

View File

@ -0,0 +1,28 @@
<test>
<settings>
<max_insert_threads>8</max_insert_threads>
<max_threads>1</max_threads>
</settings>
<create_query>
CREATE TABLE t_nullable
(
key_string1 Nullable(String),
key_string2 Nullable(String),
key_string3 Nullable(String),
key_int64_1 Nullable(Int64),
key_int64_2 Nullable(Int64),
key_int64_3 Nullable(Int64),
key_int64_4 Nullable(Int64),
key_int64_5 Nullable(Int64),
m1 Int64,
m2 Int64
)
ENGINE = Memory
</create_query>
<fill_query>insert into t_nullable select ['aaaaaa','bbaaaa','ccaaaa','ddaaaa'][number % 101 + 1], ['aa','bb','cc','dd'][number % 100 + 1], ['aa','bb','cc','dd'][number % 102 + 1], number%10+1, number%10+2, number%10+3, number%10+4,number%10+5, number%6000+1, number%5000+2 from numbers_mt(30000000)</fill_query>
<query>select * from t_nullable where key_string1 in ('aaaaaa') format Null SETTINGS allow_experimental_analyzer=1</query>
<query>select * from t_nullable where key_string2 in ('3') format Null SETTINGS allow_experimental_analyzer=1</query>
<drop_query>drop table if exists t_nullable</drop_query>
</test>

View File

@ -1,3 +1,3 @@
┌─x───────────────────────────┐
│ ('2000-01-01','2000-01-01') │
└─────────────────────────────┘
┌─x───────────────────────────┐
1. │ ('2000-01-01','2000-01-01') │
└─────────────────────────────┘

View File

@ -1,18 +1,18 @@
1
1
1
1
1.  1
1
1
1
1.  1
1
1
1
2.  1
1
1
1
1.  1
1
1
1
2.  1
1
1
3.  1

View File

@ -1,17 +1,17 @@
┌─x─────┬─y─┐
│ Hello │ 0 │
└───────┴───┘
┌─x─────┬─y─┐
│ Hello │ 0 │
│ \ │ 0 │
└───────┴───┘
┌─x────────┬─y─┐
│ Hello │ 0 │
│ \ │ 0 │
│ \t │ 0 │
└──────────┴───┘
┌─x────────┬─y─┬─toInt8(x)─┬─s─────┬─casted─┐
│ Hello │ 0 │ -100 │ Hello │ Hello │
│ \ │ 0 │ 0 │ \ │ \ │
│ \t │ 0 │ 111 │ \t │ \t │
└──────────┴───┴───────────┴───────┴────────┘
┌─x─────┬─y─┐
1. │ Hello │ 0 │
└───────┴───┘
┌─x─────┬─y─┐
1. │ Hello │ 0 │
2. │ \ │ 0 │
└───────┴───┘
┌─x────────┬─y─┐
1. │ Hello │ 0 │
2. │ \ │ 0 │
3. │ \t │ 0 │
└──────────┴───┘
┌─x────────┬─y─┬─toInt8(x)─┬─s─────┬─casted─┐
1. │ Hello │ 0 │ -100 │ Hello │ Hello │
2. │ \ │ 0 │ 0 │ \ │ \ │
3. │ \t │ 0 │ 111 │ \t │ \t │
└──────────┴───┴───────────┴───────┴────────┘

View File

@ -1,19 +1,19 @@
name value changed
name value changed
max_rows_to_read 10000 1
readonly 0 0
name value changed
1. max_rows_to_read 10000 1
2. readonly 0 0
name value changed
max_rows_to_read 10000 1
readonly 2 1
name value changed
1. max_rows_to_read 10000 1
2. readonly 2 1
name value changed
max_rows_to_read 10000 1
readonly 1 1
name value changed
1. max_rows_to_read 10000 1
2. readonly 1 1
name value changed
max_rows_to_read 10000 1
readonly 2 1
1. max_rows_to_read 10000 1
2. readonly 2 1
Ok
Ok
0

View File

@ -1,3 +1,3 @@
┌─x─────────┬─y───────────┐
│ ['hello'] │ (1,'hello') │
└───────────┴─────────────┘
┌─x─────────┬─y───────────┐
1. │ ['hello'] │ (1,'hello') │
└───────────┴─────────────┘

View File

@ -1,32 +1,32 @@
one block
┌─number─┐
│ 0 │
│ 1 │
└────────┘
┌─number─┐
1. │ 0 │
2. │ 1 │
└────────┘
two blocks
┌─number─┐
│ 0 │
│ 0 │
└────────┘
┌─number─┐
1. │ 0 │
2. │ 0 │
└────────┘
extremes
┌─number─┐
│ 0 │
│ 1 │
│ 2 │
└────────┘
┌─number─┐
1. │ 0 │
2. │ 1 │
3. │ 2 │
└────────┘
Extremes:
┌─number─┐
│ 0 │
│ 2 │
└────────┘
┌─number─┐
1. │ 0 │
2. │ 2 │
└────────┘
totals
┌─sum(number)─┐
│ 2 │
│ 1 │
└─────────────┘
┌─sum(number)─┐
1. │ 2 │
2. │ 1 │
└─────────────┘
Totals:
┌─sum(number)─┐
│ 3 │
└─────────────┘
┌─sum(number)─┐
1. │ 3 │
└─────────────┘

View File

@ -1,363 +1,363 @@
0
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
2. │ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
3. │ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
6. │ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
8. │ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
9. │ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
0 0 (0,'0') ᴺᵁᴸᴸ
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') ᴺᵁᴸᴸ
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1. 0 0 (0,'0') ᴺᵁᴸᴸ
2. 1 1 (1,'1') 1
3. 2 2 (2,'2') 2
4. 3 3 (3,'3') ᴺᵁᴸᴸ
5. 4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6 6 (6,'6') ᴺᵁᴸᴸ
7 7 (7,'7') 1
8 8 (8,'8') 2
9 9 (9,'9') ᴺᵁᴸᴸ
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
6. 5 5 (5,'5') 2
7. 6 6 (6,'6') ᴺᵁᴸᴸ
8. 7 7 (7,'7') 1
9. 8 8 (8,'8') 2
10. 9 9 (9,'9') ᴺᵁᴸᴸ
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
2. │ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
3. │ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
6. │ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
8. │ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
9. │ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
0 0 (0,'0') ᴺᵁᴸᴸ
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') ᴺᵁᴸᴸ
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1. 0 0 (0,'0') ᴺᵁᴸᴸ
2. 1 1 (1,'1') 1
3. 2 2 (2,'2') 2
4. 3 3 (3,'3') ᴺᵁᴸᴸ
5. 4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6 6 (6,'6') ᴺᵁᴸᴸ
7 7 (7,'7') 1
8 8 (8,'8') 2
9 9 (9,'9') ᴺᵁᴸᴸ
6. 5 5 (5,'5') 2
7. 6 6 (6,'6') ᴺᵁᴸᴸ
8. 7 7 (7,'7') 1
9. 8 8 (8,'8') 2
10. 9 9 (9,'9') ᴺᵁᴸᴸ
1
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
2. │ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
3. │ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
6. │ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
8. │ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
9. │ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
0 0 (0,'0') ᴺᵁᴸᴸ
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') ᴺᵁᴸᴸ
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1.  0 0 (0,'0') ᴺᵁᴸᴸ
2.  1 1 (1,'1') 1
3.  2 2 (2,'2') 2
4.  3 3 (3,'3') ᴺᵁᴸᴸ
5.  4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6 6 (6,'6') ᴺᵁᴸᴸ
7 7 (7,'7') 1
8 8 (8,'8') 2
9 9 (9,'9') ᴺᵁᴸᴸ
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
6.  5 5 (5,'5') 2
7.  6 6 (6,'6') ᴺᵁᴸᴸ
8.  7 7 (7,'7') 1
9.  8 8 (8,'8') 2
10.  9 9 (9,'9') ᴺᵁᴸᴸ
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
2. │ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
3. │ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
6. │ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
8. │ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
9. │ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
0 0 (0,'0') ᴺᵁᴸᴸ
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') ᴺᵁᴸᴸ
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1. 0 0 (0,'0') ᴺᵁᴸᴸ
2. 1 1 (1,'1') 1
3. 2 2 (2,'2') 2
4. 3 3 (3,'3') ᴺᵁᴸᴸ
5. 4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6 6 (6,'6') ᴺᵁᴸᴸ
7 7 (7,'7') 1
8 8 (8,'8') 2
9 9 (9,'9') ᴺᵁᴸᴸ
6. 5 5 (5,'5') 2
7. 6 6 (6,'6') ᴺᵁᴸᴸ
8. 7 7 (7,'7') 1
9. 8 8 (8,'8') 2
10. 9 9 (9,'9') ᴺᵁᴸᴸ
auto
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
2. │ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
3. │ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
6. │ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
8. │ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
9. │ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
0 0 (0,'0') ᴺᵁᴸᴸ
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') ᴺᵁᴸᴸ
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1. 0 0 (0,'0') ᴺᵁᴸᴸ
2. 1 1 (1,'1') 1
3. 2 2 (2,'2') 2
4. 3 3 (3,'3') ᴺᵁᴸᴸ
5. 4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6 6 (6,'6') ᴺᵁᴸᴸ
7 7 (7,'7') 1
8 8 (8,'8') 2
9 9 (9,'9') ᴺᵁᴸᴸ
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
6. 5 5 (5,'5') 2
7. 6 6 (6,'6') ᴺᵁᴸᴸ
8. 7 7 (7,'7') 1
9. 8 8 (8,'8') 2
10. 9 9 (9,'9') ᴺᵁᴸᴸ
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
2. │ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
3. │ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
6. │ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
8. │ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
9. │ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
0 0 (0,'0') ᴺᵁᴸᴸ
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') ᴺᵁᴸᴸ
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1. 0 0 (0,'0') ᴺᵁᴸᴸ
2. 1 1 (1,'1') 1
3. 2 2 (2,'2') 2
4. 3 3 (3,'3') ᴺᵁᴸᴸ
5. 4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6 6 (6,'6') ᴺᵁᴸᴸ
7 7 (7,'7') 1
8 8 (8,'8') 2
9 9 (9,'9') ᴺᵁᴸᴸ
6. 5 5 (5,'5') 2
7. 6 6 (6,'6') ᴺᵁᴸᴸ
8. 7 7 (7,'7') 1
9. 8 8 (8,'8') 2
10. 9 9 (9,'9') ᴺᵁᴸᴸ

View File

@ -1,306 +1,306 @@
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
2. │ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
3. │ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
6. │ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
8. │ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
9. │ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
0 0 (0,'0') ᴺᵁᴸᴸ
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') ᴺᵁᴸᴸ
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1.  0 0 (0,'0') ᴺᵁᴸᴸ
2.  1 1 (1,'1') 1
3.  2 2 (2,'2') 2
4.  3 3 (3,'3') ᴺᵁᴸᴸ
5.  4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6 6 (6,'6') ᴺᵁᴸᴸ
7 7 (7,'7') 1
8 8 (8,'8') 2
9 9 (9,'9') ᴺᵁᴸᴸ
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 5 │ 5 │ (5,'5') │ 2 │
│ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
│ 7 │ 7 │ (7,'7') │ 1 │
│ 8 │ 8 │ (8,'8') │ 2 │
│ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
6.  5 5 (5,'5') 2
7.  6 6 (6,'6') ᴺᵁᴸᴸ
8.  7 7 (7,'7') 1
9.  8 8 (8,'8') 2
10.  9 9 (9,'9') ᴺᵁᴸᴸ
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
2. │ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
3. │ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
6. │ 5 │ 5 │ (5,'5') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
8. │ 7 │ 7 │ (7,'7') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
9. │ 8 │ 8 │ (8,'8') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
6. │ 5 │ 5 │ (5,'5') │ 2 │
7. │ 6 │ 6 │ (6,'6') │ ᴺᵁᴸᴸ │
8. │ 7 │ 7 │ (7,'7') │ 1 │
9. │ 8 │ 8 │ (8,'8') │ 2 │
10. │ 9 │ 9 │ (9,'9') │ ᴺᵁᴸᴸ │
└───────┴───────┴─────────┴─────────────────┘
hello world tuple sometimes_nulls
0 0 (0,'0') ᴺᵁᴸᴸ
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') ᴺᵁᴸᴸ
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1. 0 0 (0,'0') ᴺᵁᴸᴸ
2. 1 1 (1,'1') 1
3. 2 2 (2,'2') 2
4. 3 3 (3,'3') ᴺᵁᴸᴸ
5. 4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6 6 (6,'6') ᴺᵁᴸᴸ
7 7 (7,'7') 1
8 8 (8,'8') 2
9 9 (9,'9') ᴺᵁᴸᴸ
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 5 │ 5 │ (5,'5') │ 2 │
└───────┴───────┴─────────┴─────────────────┘
6. 5 5 (5,'5') 2
7. 6 6 (6,'6') ᴺᵁᴸᴸ
8. 7 7 (7,'7') 1
9. 8 8 (8,'8') 2
10. 9 9 (9,'9') ᴺᵁᴸᴸ
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
2. │ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
3. │ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
hello ┃ world ┃ tuple  ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
6. │ 5 │ 5 │ (5,'5') │ 2 │
└───────┴───────┴─────────┴─────────────────┘
Showed first 6.
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 5 │ 5 │ (5,'5') │ 2 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
6. │ 5 │ 5 │ (5,'5') │ 2 │
└───────┴───────┴─────────┴─────────────────┘
Showed first 6.
hello world tuple sometimes_nulls
hello world tuple sometimes_nulls
0 0 (0,'0') ᴺᵁᴸᴸ
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') ᴺᵁᴸᴸ
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1.  0 0 (0,'0') ᴺᵁᴸᴸ
2.  1 1 (1,'1') 1
3.  2 2 (2,'2') 2
4.  3 3 (3,'3') ᴺᵁᴸᴸ
5.  4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6.  5 5 (5,'5') 2
Showed first 6.
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
│ 5 │ 5 │ (5,'5') │ 2 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
6. │ 5 │ 5 │ (5,'5') │ 2 │
└───────┴───────┴─────────┴─────────────────┘
Showed first 6.
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
│ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ 5 │ 5 │ (5,'5') │ 2 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
2. │ 1 │ 1 │ (1,'1') │ 1 │
├───────┼───────┼─────────┼─────────────────┤
3. │ 2 │ 2 │ (2,'2') │ 2 │
├───────┼───────┼─────────┼─────────────────┤
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
├───────┼───────┼─────────┼─────────────────┤
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┏━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ hello ┃ world ┃ tuple ┃ sometimes_nulls ┃
┡━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
6. │ 5 │ 5 │ (5,'5') │ 2 │
└───────┴───────┴─────────┴─────────────────┘
Showed first 6.
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
│ 1 │ 1 │ (1,'1') │ 1 │
│ 2 │ 2 │ (2,'2') │ 2 │
│ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
│ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
│ 5 │ 5 │ (5,'5') │ 2 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
1. │ 0 │ 0 │ (0,'0') │ ᴺᵁᴸᴸ │
2. │ 1 │ 1 │ (1,'1') │ 1 │
3. │ 2 │ 2 │ (2,'2') │ 2 │
4. │ 3 │ 3 │ (3,'3') │ ᴺᵁᴸᴸ │
5. │ 4 │ 4 │ (4,'4') │ 1 │
└───────┴───────┴─────────┴─────────────────┘
┌─hello─┬─world─┬─tuple───┬─sometimes_nulls─┐
6. │ 5 │ 5 │ (5,'5') │ 2 │
└───────┴───────┴─────────┴─────────────────┘
Showed first 6.
hello world tuple sometimes_nulls
hello world tuple sometimes_nulls
0 0 (0,'0') ᴺᵁᴸᴸ
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') ᴺᵁᴸᴸ
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1. 0 0 (0,'0') ᴺᵁᴸᴸ
2. 1 1 (1,'1') 1
3. 2 2 (2,'2') 2
4. 3 3 (3,'3') ᴺᵁᴸᴸ
5. 4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6. 5 5 (5,'5') 2
Showed first 6.
+-------+-------+---------+-----------------+
| hello | world | tuple  | sometimes_nulls |
+-------+-------+---------+-----------------+
| 0 | 0 | (0,'0') | NULL |
+-------+-------+---------+-----------------+
| 1 | 1 | (1,'1') | 1 |
+-------+-------+---------+-----------------+
| 2 | 2 | (2,'2') | 2 |
+-------+-------+---------+-----------------+
| 3 | 3 | (3,'3') | NULL |
+-------+-------+---------+-----------------+
| 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-------+-------+---------+-----------------+
| hello | world | tuple  | sometimes_nulls |
+-------+-------+---------+-----------------+
| 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
+-------+-------+---------+-----------------+
| hello | world | tuple  | sometimes_nulls |
+-------+-------+---------+-----------------+
1. | 0 | 0 | (0,'0') | NULL |
+-------+-------+---------+-----------------+
2. | 1 | 1 | (1,'1') | 1 |
+-------+-------+---------+-----------------+
3. | 2 | 2 | (2,'2') | 2 |
+-------+-------+---------+-----------------+
4. | 3 | 3 | (3,'3') | NULL |
+-------+-------+---------+-----------------+
5. | 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-------+-------+---------+-----------------+
| hello | world | tuple  | sometimes_nulls |
+-------+-------+---------+-----------------+
6. | 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
Showed first 6.
+-hello-+-world-+-tuple---+-sometimes_nulls-+
| 0 | 0 | (0,'0') | NULL |
| 1 | 1 | (1,'1') | 1 |
| 2 | 2 | (2,'2') | 2 |
| 3 | 3 | (3,'3') | NULL |
| 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-hello-+-world-+-tuple---+-sometimes_nulls-+
| 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
+-hello-+-world-+-tuple---+-sometimes_nulls-+
1. | 0 | 0 | (0,'0') | NULL |
2. | 1 | 1 | (1,'1') | 1 |
3. | 2 | 2 | (2,'2') | 2 |
4. | 3 | 3 | (3,'3') | NULL |
5. | 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-hello-+-world-+-tuple---+-sometimes_nulls-+
6. | 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
Showed first 6.
hello world tuple sometimes_nulls
hello world tuple sometimes_nulls
0 0 (0,'0') NULL
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') NULL
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1.  0 0 (0,'0') NULL
2.  1 1 (1,'1') 1
3.  2 2 (2,'2') 2
4.  3 3 (3,'3') NULL
5.  4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6.  5 5 (5,'5') 2
Showed first 6.
+-hello-+-world-+-tuple---+-sometimes_nulls-+
| 0 | 0 | (0,'0') | NULL |
| 1 | 1 | (1,'1') | 1 |
| 2 | 2 | (2,'2') | 2 |
| 3 | 3 | (3,'3') | NULL |
| 4 | 4 | (4,'4') | 1 |
| 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
+-hello-+-world-+-tuple---+-sometimes_nulls-+
1. | 0 | 0 | (0,'0') | NULL |
2. | 1 | 1 | (1,'1') | 1 |
3. | 2 | 2 | (2,'2') | 2 |
4. | 3 | 3 | (3,'3') | NULL |
5. | 4 | 4 | (4,'4') | 1 |
6. | 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
Showed first 6.
+-------+-------+---------+-----------------+
| hello | world | tuple | sometimes_nulls |
+-------+-------+---------+-----------------+
| 0 | 0 | (0,'0') | NULL |
+-------+-------+---------+-----------------+
| 1 | 1 | (1,'1') | 1 |
+-------+-------+---------+-----------------+
| 2 | 2 | (2,'2') | 2 |
+-------+-------+---------+-----------------+
| 3 | 3 | (3,'3') | NULL |
+-------+-------+---------+-----------------+
| 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-------+-------+---------+-----------------+
| hello | world | tuple | sometimes_nulls |
+-------+-------+---------+-----------------+
| 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
+-------+-------+---------+-----------------+
| hello | world | tuple | sometimes_nulls |
+-------+-------+---------+-----------------+
1. | 0 | 0 | (0,'0') | NULL |
+-------+-------+---------+-----------------+
2. | 1 | 1 | (1,'1') | 1 |
+-------+-------+---------+-----------------+
3. | 2 | 2 | (2,'2') | 2 |
+-------+-------+---------+-----------------+
4. | 3 | 3 | (3,'3') | NULL |
+-------+-------+---------+-----------------+
5. | 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-------+-------+---------+-----------------+
| hello | world | tuple | sometimes_nulls |
+-------+-------+---------+-----------------+
6. | 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
Showed first 6.
+-hello-+-world-+-tuple---+-sometimes_nulls-+
| 0 | 0 | (0,'0') | NULL |
| 1 | 1 | (1,'1') | 1 |
| 2 | 2 | (2,'2') | 2 |
| 3 | 3 | (3,'3') | NULL |
| 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-hello-+-world-+-tuple---+-sometimes_nulls-+
| 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
+-hello-+-world-+-tuple---+-sometimes_nulls-+
1. | 0 | 0 | (0,'0') | NULL |
2. | 1 | 1 | (1,'1') | 1 |
3. | 2 | 2 | (2,'2') | 2 |
4. | 3 | 3 | (3,'3') | NULL |
5. | 4 | 4 | (4,'4') | 1 |
+-------+-------+---------+-----------------+
+-hello-+-world-+-tuple---+-sometimes_nulls-+
6. | 5 | 5 | (5,'5') | 2 |
+-------+-------+---------+-----------------+
Showed first 6.
hello world tuple sometimes_nulls
hello world tuple sometimes_nulls
0 0 (0,'0') NULL
1 1 (1,'1') 1
2 2 (2,'2') 2
3 3 (3,'3') NULL
4 4 (4,'4') 1
hello world tuple sometimes_nulls
1. 0 0 (0,'0') NULL
2. 1 1 (1,'1') 1
3. 2 2 (2,'2') 2
4. 3 3 (3,'3') NULL
5. 4 4 (4,'4') 1
hello world tuple sometimes_nulls
5 5 (5,'5') 2
6. 5 5 (5,'5') 2
Showed first 6.

View File

@ -1,15 +1,15 @@
┌─tuple─────────┐
│ (0,NULL,NULL) │
│ (1,1,'1') │
│ (2,2,NULL) │
│ (3,NULL,'1') │
│ (4,1,NULL) │
│ (5,2,'1') │
│ (6,NULL,NULL) │
│ (7,1,'1') │
│ (8,2,NULL) │
│ (9,NULL,'1') │
└───────────────┘
┌─x────┬─y──────┐
│ ᴺᵁᴸᴸ │ (NULL) │
└──────┴────────┘
┌─tuple─────────┐
1. │ (0,NULL,NULL) │
2. │ (1,1,'1') │
3. │ (2,2,NULL) │
4. │ (3,NULL,'1') │
5. │ (4,1,NULL) │
6. │ (5,2,'1') │
7. │ (6,NULL,NULL) │
8. │ (7,1,'1') │
9. │ (8,2,NULL) │
10. │ (9,NULL,'1') │
└───────────────┘
┌─x────┬─y──────┐
1. │ ᴺᵁᴸᴸ │ (NULL) │
└──────┴────────┘

View File

@ -1,67 +1,67 @@
┏━━━━━━━━━━━━┳━━━━━━━━━━━━┓
 x ┃ s  ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ 1 │ 1 │
├────────────┼────────────┤
│ 10 │ 10 │
├────────────┼────────────┤
│ 100 │ 100 │
├────────────┼────────────┤
│ 1000 │ 1000 │
├────────────┼────────────┤
│ 10000 │ 10000 │
├────────────┼────────────┤
│ 100000 │ 100000 │
├────────────┼────────────┤
│ 1000000 │ 1000000 │
├────────────┼────────────┤
│ 10000000 │ 10000000 │
├────────────┼────────────┤
│ 100000000 │ 100000000 │
├────────────┼────────────┤
│ 1000000000 │ 1000000000 │
└────────────┴────────────┘
┌──────────x─┬─s──────────┐
│ 1 │ 1 │
│ 10 │ 10 │
│ 100 │ 100 │
│ 1000 │ 1000 │
│ 10000 │ 10000 │
│ 100000 │ 100000 │
│ 1000000 │ 1000000 │
│ 10000000 │ 10000000 │
│ 100000000 │ 100000000 │
│ 1000000000 │ 1000000000 │
└────────────┴────────────┘
x s
┏━━━━━━━━━━━━┳━━━━━━━━━━━━┓
 x ┃ s  ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━┩
1. │ 1 │ 1 │
├────────────┼────────────┤
2. │ 10 │ 10 │
├────────────┼────────────┤
3. │ 100 │ 100 │
├────────────┼────────────┤
4. │ 1000 │ 1000 │
├────────────┼────────────┤
5. │ 10000 │ 10000 │
├────────────┼────────────┤
6. │ 100000 │ 100000 │
├────────────┼────────────┤
7. │ 1000000 │ 1000000 │
├────────────┼────────────┤
8. │ 10000000 │ 10000000 │
├────────────┼────────────┤
9. │ 100000000 │ 100000000 │
├────────────┼────────────┤
10. │ 1000000000 │ 1000000000 │
└────────────┴────────────┘
┌──────────x─┬─s──────────┐
1. │ 1 │ 1 │
2. │ 10 │ 10 │
3. │ 100 │ 100 │
4. │ 1000 │ 1000 │
5. │ 10000 │ 10000 │
6. │ 100000 │ 100000 │
7. │ 1000000 │ 1000000 │
8. │ 10000000 │ 10000000 │
9. │ 100000000 │ 100000000 │
10. │ 1000000000 │ 1000000000 │
└────────────┴────────────┘
x s
1 1
10 10
100 100
1000 1000
10000 10000
100000 100000
1000000 1000000
10000000 10000000
100000000 100000000
1000000000 1000000000
┌──────────x─┬─s──────────┐
│ 1 │ 1 │
│ 10 │ 10 │
│ 100 │ 100 │
│ 1000 │ 1000 │
│ 10000 │ 10000 │
│ 100000 │ 100000 │
│ 1000000 │ 1000000 │
│ 10000000 │ 10000000 │
│ 100000000 │ 100000000 │
│ 1000000000 │ 1000000000 │
└────────────┴────────────┘
┏━━━━━━━━━━┓
'\\\'\'' ┃
┡━━━━━━━━━━┩
│ \'' │
└──────────┘
1.  1 1
2.  10 10
3.  100 100
4.  1000 1000
5.  10000 10000
6.  100000 100000
7.  1000000 1000000
8.  10000000 10000000
9.  100000000 100000000
10.  1000000000 1000000000
┌──────────x─┬─s──────────┐
1. │ 1 │ 1 │
2. │ 10 │ 10 │
3. │ 100 │ 100 │
4. │ 1000 │ 1000 │
5. │ 10000 │ 10000 │
6. │ 100000 │ 100000 │
7. │ 1000000 │ 1000000 │
8. │ 10000000 │ 10000000 │
9. │ 100000000 │ 100000000 │
10. │ 1000000000 │ 1000000000 │
└────────────┴────────────┘
┏━━━━━━━━━━┓
'\\\'\'' ┃
┡━━━━━━━━━━┩
1. │ \'' │
└──────────┘
Row 1:
──────
'\\\'\'': \''

View File

@ -1,106 +1,106 @@
s a b
s a b
0 ᴺᵁᴸᴸ 1970-01-01 00:00:00
0000 ᴺᵁᴸᴸ 1970-01-01 00:00:00
2000-01-01 00:00:00 2000-01-01 00:00:00 2000-01-01 00:00:00
2000-01-01 01:00:00 2000-01-01 01:00:00 2000-01-01 01:00:00
02/01/17 010203 MSK 2017-01-01 22:02:03 2017-01-01 22:02:03
02/01/17 010203 MSK+0100 2017-01-01 21:02:03 2017-01-01 21:02:03
02/01/17 010203 UTC+0300 2017-01-01 22:02:03 2017-01-01 22:02:03
02/01/17 010203Z 2017-01-02 01:02:03 2017-01-02 01:02:03
02/01/1970 010203Z 1970-01-02 01:02:03 1970-01-02 01:02:03
02/01/70 010203Z 1970-01-02 01:02:03 1970-01-02 01:02:03
11 Feb 2018 06:40:50 +0300 2018-02-11 03:40:50 2018-02-11 03:40:50
17 Apr 2000 2 1:2:3 2000-04-17 01:02:03 2000-04-17 01:02:03
19700102 01:00:00 1970-01-02 01:00:00 1970-01-02 01:00:00
1970010201:00:00 ᴺᵁᴸᴸ 1970-01-01 00:00:00
19700102010203 1970-01-02 01:02:03 1970-01-02 01:02:03
19700102010203Z 1970-01-02 01:02:03 1970-01-02 01:02:03
1970/01/02 010203Z 1970-01-02 01:02:03 1970-01-02 01:02:03
20 2000 2000-01-20 00:00:00 2000-01-20 00:00:00
201 ᴺᵁᴸᴸ 1970-01-01 00:00:00
20160101 2016-01-01 00:00:00 2016-01-01 00:00:00
2016-01-01 2016-01-01 00:00:00 2016-01-01 00:00:00
201601-01 2016-01-01 01:00:00 2016-01-01 01:00:00
2016-01-01MSD 2015-12-31 20:00:00 2015-12-31 20:00:00
2016-01-01 MSD 2015-12-31 20:00:00 2015-12-31 20:00:00
201601-01 MSD 2016-01-01 04:00:00 2016-01-01 04:00:00
2016-01-01UTC 2016-01-01 00:00:00 2016-01-01 00:00:00
2016-01-01Z 2016-01-01 00:00:00 2016-01-01 00:00:00
2017 2017-01-01 00:00:00 2017-01-01 00:00:00
2017/01/00 2017-01-01 00:00:00 2017-01-01 00:00:00
2017/01/00 MSD 2016-12-31 20:00:00 2016-12-31 20:00:00
2017/01/00 MSD Jun 2017-05-31 20:00:00 2017-05-31 20:00:00
2017/01/01 2017-01-01 00:00:00 2017-01-01 00:00:00
201701 02 010203 UTC+0300 2017-01-01 22:02:03 2017-01-01 22:02:03
2017-01-02 03:04:05 2017-01-02 03:04:05 2017-01-02 03:04:05
2017-01-0203:04:05 ᴺᵁᴸᴸ 1970-01-01 00:00:00
2017-01-02 03:04:05+0 2017-01-02 03:04:05 2017-01-02 03:04:05
2017-01-02 03:04:05+00 2017-01-02 03:04:05 2017-01-02 03:04:05
2017-01-02 03:04:05+0000 2017-01-02 03:04:05 2017-01-02 03:04:05
2017-01-02 03:04:05 -0100 2017-01-02 04:04:05 2017-01-02 04:04:05
2017-01-02 03:04:05+030 2017-01-02 02:34:05 2017-01-02 02:34:05
2017-01-02 03:04:05+0300 2017-01-02 00:04:05 2017-01-02 00:04:05
2017-01-02 03:04:05+1 2017-01-02 02:04:05 2017-01-02 02:04:05
2017-01-02 03:04:05+300 2017-01-02 00:04:05 2017-01-02 00:04:05
2017-01-02 03:04:05+900 2017-01-01 18:04:05 2017-01-01 18:04:05
2017-01-02 03:04:05GMT 2017-01-02 03:04:05 2017-01-02 03:04:05
2017-01-02 03:04:05 MSD 2017-01-01 23:04:05 2017-01-01 23:04:05
2017-01-02 03:04:05 MSD Feb 2017-02-01 23:04:05 2017-02-01 23:04:05
2017-01-02 03:04:05 MSD Jun 2017-06-01 23:04:05 2017-06-01 23:04:05
2017-01-02 03:04:05 MSK 2017-01-02 00:04:05 2017-01-02 00:04:05
2017-01-02T03:04:05 2017-01-02 03:04:05 2017-01-02 03:04:05
2017-01-02T03:04:05+00 2017-01-02 03:04:05 2017-01-02 03:04:05
2017-01-02T03:04:05 -0100 2017-01-02 04:04:05 2017-01-02 04:04:05
2017-01-02T03:04:05-0100 2017-01-02 04:04:05 2017-01-02 04:04:05
2017-01-02T03:04:05+0100 2017-01-02 02:04:05 2017-01-02 02:04:05
2017-01-02T03:04:05Z 2017-01-02 03:04:05 2017-01-02 03:04:05
2017-01 03:04:05 MSD Jun 2017-05-31 23:04:05 2017-05-31 23:04:05
2017-01 03:04 MSD Jun 2017-05-31 23:04:00 2017-05-31 23:04:00
2017/01/31 2017-01-31 00:00:00 2017-01-31 00:00:00
2017/01/32 ᴺᵁᴸᴸ 1970-01-01 00:00:00
2017-01 MSD Jun 2017-05-31 20:00:00 2017-05-31 20:00:00
201701 MSD Jun 2017-05-31 20:00:00 2017-05-31 20:00:00
2017 25 1:2:3 ᴺᵁᴸᴸ 1970-01-01 00:00:00
2017 25 Apr 1:2:3 2017-04-01 01:02:03 2017-04-01 01:02:03
2017 Apr 01 11:22:33 2017-04-01 11:22:33 2017-04-01 11:22:33
2017 Apr 02 01/02/03 UTC+0300 ᴺᵁᴸᴸ 1970-01-01 00:00:00
2017 Apr 02 010203 UTC+0300 2017-04-01 22:02:03 2017-04-01 22:02:03
2017 Apr 02 01:2:3 UTC+0300 2017-04-01 22:02:03 2017-04-01 22:02:03
2017 Apr 02 1:02:3 2017-04-02 01:02:03 2017-04-02 01:02:03
2017 Apr 02 11:22:33 2017-04-02 11:22:33 2017-04-02 11:22:33
2017 Apr 02 1:2:03 2017-04-02 01:02:03 2017-04-02 01:02:03
2017 Apr 02 1:22:33 2017-04-02 01:22:33 2017-04-02 01:22:33
2017 Apr 02 1:2:3 2017-04-02 01:02:03 2017-04-02 01:02:03
2017 Apr 02 1:2:33 2017-04-02 01:02:33 2017-04-02 01:02:33
2017 Apr 02 1:2:3 MSK 2017-04-01 22:02:03 2017-04-01 22:02:03
2017 Apr 02 1:2:3 MSK 2017 ᴺᵁᴸᴸ 1970-01-01 00:00:00
2017 Apr 02 1:2:3 MSK 2018 ᴺᵁᴸᴸ 1970-01-01 00:00:00
2017 Apr 02 1:2:3 UTC+0000 2017-04-02 01:02:03 2017-04-02 01:02:03
2017 Apr 02 1:2:3 UTC+0300 2017-04-01 22:02:03 2017-04-01 22:02:03
2017 Apr 02 1:2:3 UTC+0400 2017-04-01 21:02:03 2017-04-01 21:02:03
2017 Apr 2 1:2:3 2017-04-02 01:02:03 2017-04-02 01:02:03
2017 Jan 02 010203 UTC+0300 2017-01-01 22:02:03 2017-01-01 22:02:03
25 Apr 2017 01:02:03 2017-04-25 01:02:03 2017-04-25 01:02:03
25 Apr 2017 1:2:3 2017-04-25 01:02:03 2017-04-25 01:02:03
25 Jan 2017 1:2:3 2017-01-25 01:02:03 2017-01-25 01:02:03
25 Jan 2017 1:2:3 MSK 2017-01-24 22:02:03 2017-01-24 22:02:03
25 Jan 2017 1:2:3 PM 2017-01-25 13:02:03 2017-01-25 13:02:03
25 Jan 2017 1:2:3Z 2017-01-25 01:02:03 2017-01-25 01:02:03
25 Jan 2017 1:2:3 Z 2017-01-25 01:02:03 2017-01-25 01:02:03
25 Jan 2017 1:2:3 Z +0300 2017-01-24 22:02:03 2017-01-24 22:02:03
25 Jan 2017 1:2:3 Z+03:00 2017-01-24 22:02:03 2017-01-24 22:02:03
25 Jan 2017 1:2:3 Z +0300 OM ᴺᵁᴸᴸ 1970-01-01 00:00:00
25 Jan 2017 1:2:3 Z +03:00 PM 2017-01-25 10:02:03 2017-01-25 10:02:03
25 Jan 2017 1:2:3 Z +0300 PM 2017-01-25 10:02:03 2017-01-25 10:02:03
25 Jan 2017 1:2:3 Z+03:00 PM 2017-01-25 10:02:03 2017-01-25 10:02:03
25 Jan 2017 1:2:3 Z +03:30 PM 2017-01-25 09:32:03 2017-01-25 09:32:03
25 Jan 2017 1:2:3Z Mo ᴺᵁᴸᴸ 1970-01-01 00:00:00
25 Jan 2017 1:2:3Z Mon 2017-01-25 01:02:03 2017-01-25 01:02:03
25 Jan 2017 1:2:3Z Moo ᴺᵁᴸᴸ 1970-01-01 00:00:00
25 Jan 2017 1:2:3 Z PM 2017-01-25 13:02:03 2017-01-25 13:02:03
25 Jan 2017 1:2:3Z PM 2017-01-25 13:02:03 2017-01-25 13:02:03
25 Jan 2017 1:2:3 Z PM +03:00 2017-01-25 10:02:03 2017-01-25 10:02:03
Jun, 11 Feb 2018 06:40:50 +0300 ᴺᵁᴸᴸ 1970-01-01 00:00:00
Sun 11 Feb 2018 06:40:50 +0300 2018-02-11 03:40:50 2018-02-11 03:40:50
Sun, 11 Feb 2018 06:40:50 +0300 2018-02-11 03:40:50 2018-02-11 03:40:50
1. 0 ᴺᵁᴸᴸ 1970-01-01 00:00:00
2. 0000 ᴺᵁᴸᴸ 1970-01-01 00:00:00
3. 2000-01-01 00:00:00 2000-01-01 00:00:00 2000-01-01 00:00:00
4. 2000-01-01 01:00:00 2000-01-01 01:00:00 2000-01-01 01:00:00
5. 02/01/17 010203 MSK 2017-01-01 22:02:03 2017-01-01 22:02:03
6. 02/01/17 010203 MSK+0100 2017-01-01 21:02:03 2017-01-01 21:02:03
7. 02/01/17 010203 UTC+0300 2017-01-01 22:02:03 2017-01-01 22:02:03
8. 02/01/17 010203Z 2017-01-02 01:02:03 2017-01-02 01:02:03
9. 02/01/1970 010203Z 1970-01-02 01:02:03 1970-01-02 01:02:03
10. 02/01/70 010203Z 1970-01-02 01:02:03 1970-01-02 01:02:03
11. 11 Feb 2018 06:40:50 +0300 2018-02-11 03:40:50 2018-02-11 03:40:50
12. 17 Apr 2000 2 1:2:3 2000-04-17 01:02:03 2000-04-17 01:02:03
13. 19700102 01:00:00 1970-01-02 01:00:00 1970-01-02 01:00:00
14. 1970010201:00:00 ᴺᵁᴸᴸ 1970-01-01 00:00:00
15. 19700102010203 1970-01-02 01:02:03 1970-01-02 01:02:03
16. 19700102010203Z 1970-01-02 01:02:03 1970-01-02 01:02:03
17. 1970/01/02 010203Z 1970-01-02 01:02:03 1970-01-02 01:02:03
18. 20 2000 2000-01-20 00:00:00 2000-01-20 00:00:00
19. 201 ᴺᵁᴸᴸ 1970-01-01 00:00:00
20. 20160101 2016-01-01 00:00:00 2016-01-01 00:00:00
21. 2016-01-01 2016-01-01 00:00:00 2016-01-01 00:00:00
22. 201601-01 2016-01-01 01:00:00 2016-01-01 01:00:00
23. 2016-01-01MSD 2015-12-31 20:00:00 2015-12-31 20:00:00
24. 2016-01-01 MSD 2015-12-31 20:00:00 2015-12-31 20:00:00
25. 201601-01 MSD 2016-01-01 04:00:00 2016-01-01 04:00:00
26. 2016-01-01UTC 2016-01-01 00:00:00 2016-01-01 00:00:00
27. 2016-01-01Z 2016-01-01 00:00:00 2016-01-01 00:00:00
28. 2017 2017-01-01 00:00:00 2017-01-01 00:00:00
29. 2017/01/00 2017-01-01 00:00:00 2017-01-01 00:00:00
30. 2017/01/00 MSD 2016-12-31 20:00:00 2016-12-31 20:00:00
31. 2017/01/00 MSD Jun 2017-05-31 20:00:00 2017-05-31 20:00:00
32. 2017/01/01 2017-01-01 00:00:00 2017-01-01 00:00:00
33. 201701 02 010203 UTC+0300 2017-01-01 22:02:03 2017-01-01 22:02:03
34. 2017-01-02 03:04:05 2017-01-02 03:04:05 2017-01-02 03:04:05
35. 2017-01-0203:04:05 ᴺᵁᴸᴸ 1970-01-01 00:00:00
36. 2017-01-02 03:04:05+0 2017-01-02 03:04:05 2017-01-02 03:04:05
37. 2017-01-02 03:04:05+00 2017-01-02 03:04:05 2017-01-02 03:04:05
38. 2017-01-02 03:04:05+0000 2017-01-02 03:04:05 2017-01-02 03:04:05
39. 2017-01-02 03:04:05 -0100 2017-01-02 04:04:05 2017-01-02 04:04:05
40. 2017-01-02 03:04:05+030 2017-01-02 02:34:05 2017-01-02 02:34:05
41. 2017-01-02 03:04:05+0300 2017-01-02 00:04:05 2017-01-02 00:04:05
42. 2017-01-02 03:04:05+1 2017-01-02 02:04:05 2017-01-02 02:04:05
43. 2017-01-02 03:04:05+300 2017-01-02 00:04:05 2017-01-02 00:04:05
44. 2017-01-02 03:04:05+900 2017-01-01 18:04:05 2017-01-01 18:04:05
45. 2017-01-02 03:04:05GMT 2017-01-02 03:04:05 2017-01-02 03:04:05
46. 2017-01-02 03:04:05 MSD 2017-01-01 23:04:05 2017-01-01 23:04:05
47. 2017-01-02 03:04:05 MSD Feb 2017-02-01 23:04:05 2017-02-01 23:04:05
48. 2017-01-02 03:04:05 MSD Jun 2017-06-01 23:04:05 2017-06-01 23:04:05
49. 2017-01-02 03:04:05 MSK 2017-01-02 00:04:05 2017-01-02 00:04:05
50. 2017-01-02T03:04:05 2017-01-02 03:04:05 2017-01-02 03:04:05
51. 2017-01-02T03:04:05+00 2017-01-02 03:04:05 2017-01-02 03:04:05
52. 2017-01-02T03:04:05 -0100 2017-01-02 04:04:05 2017-01-02 04:04:05
53. 2017-01-02T03:04:05-0100 2017-01-02 04:04:05 2017-01-02 04:04:05
54. 2017-01-02T03:04:05+0100 2017-01-02 02:04:05 2017-01-02 02:04:05
55. 2017-01-02T03:04:05Z 2017-01-02 03:04:05 2017-01-02 03:04:05
56. 2017-01 03:04:05 MSD Jun 2017-05-31 23:04:05 2017-05-31 23:04:05
57. 2017-01 03:04 MSD Jun 2017-05-31 23:04:00 2017-05-31 23:04:00
58. 2017/01/31 2017-01-31 00:00:00 2017-01-31 00:00:00
59. 2017/01/32 ᴺᵁᴸᴸ 1970-01-01 00:00:00
60. 2017-01 MSD Jun 2017-05-31 20:00:00 2017-05-31 20:00:00
61. 201701 MSD Jun 2017-05-31 20:00:00 2017-05-31 20:00:00
62. 2017 25 1:2:3 ᴺᵁᴸᴸ 1970-01-01 00:00:00
63. 2017 25 Apr 1:2:3 2017-04-01 01:02:03 2017-04-01 01:02:03
64. 2017 Apr 01 11:22:33 2017-04-01 11:22:33 2017-04-01 11:22:33
65. 2017 Apr 02 01/02/03 UTC+0300 ᴺᵁᴸᴸ 1970-01-01 00:00:00
66. 2017 Apr 02 010203 UTC+0300 2017-04-01 22:02:03 2017-04-01 22:02:03
67. 2017 Apr 02 01:2:3 UTC+0300 2017-04-01 22:02:03 2017-04-01 22:02:03
68. 2017 Apr 02 1:02:3 2017-04-02 01:02:03 2017-04-02 01:02:03
69. 2017 Apr 02 11:22:33 2017-04-02 11:22:33 2017-04-02 11:22:33
70. 2017 Apr 02 1:2:03 2017-04-02 01:02:03 2017-04-02 01:02:03
71. 2017 Apr 02 1:22:33 2017-04-02 01:22:33 2017-04-02 01:22:33
72. 2017 Apr 02 1:2:3 2017-04-02 01:02:03 2017-04-02 01:02:03
73. 2017 Apr 02 1:2:33 2017-04-02 01:02:33 2017-04-02 01:02:33
74. 2017 Apr 02 1:2:3 MSK 2017-04-01 22:02:03 2017-04-01 22:02:03
75. 2017 Apr 02 1:2:3 MSK 2017 ᴺᵁᴸᴸ 1970-01-01 00:00:00
76. 2017 Apr 02 1:2:3 MSK 2018 ᴺᵁᴸᴸ 1970-01-01 00:00:00
77. 2017 Apr 02 1:2:3 UTC+0000 2017-04-02 01:02:03 2017-04-02 01:02:03
78. 2017 Apr 02 1:2:3 UTC+0300 2017-04-01 22:02:03 2017-04-01 22:02:03
79. 2017 Apr 02 1:2:3 UTC+0400 2017-04-01 21:02:03 2017-04-01 21:02:03
80. 2017 Apr 2 1:2:3 2017-04-02 01:02:03 2017-04-02 01:02:03
81. 2017 Jan 02 010203 UTC+0300 2017-01-01 22:02:03 2017-01-01 22:02:03
82. 25 Apr 2017 01:02:03 2017-04-25 01:02:03 2017-04-25 01:02:03
83. 25 Apr 2017 1:2:3 2017-04-25 01:02:03 2017-04-25 01:02:03
84. 25 Jan 2017 1:2:3 2017-01-25 01:02:03 2017-01-25 01:02:03
85. 25 Jan 2017 1:2:3 MSK 2017-01-24 22:02:03 2017-01-24 22:02:03
86. 25 Jan 2017 1:2:3 PM 2017-01-25 13:02:03 2017-01-25 13:02:03
87. 25 Jan 2017 1:2:3Z 2017-01-25 01:02:03 2017-01-25 01:02:03
88. 25 Jan 2017 1:2:3 Z 2017-01-25 01:02:03 2017-01-25 01:02:03
89. 25 Jan 2017 1:2:3 Z +0300 2017-01-24 22:02:03 2017-01-24 22:02:03
90. 25 Jan 2017 1:2:3 Z+03:00 2017-01-24 22:02:03 2017-01-24 22:02:03
91. 25 Jan 2017 1:2:3 Z +0300 OM ᴺᵁᴸᴸ 1970-01-01 00:00:00
92. 25 Jan 2017 1:2:3 Z +03:00 PM 2017-01-25 10:02:03 2017-01-25 10:02:03
93. 25 Jan 2017 1:2:3 Z +0300 PM 2017-01-25 10:02:03 2017-01-25 10:02:03
94. 25 Jan 2017 1:2:3 Z+03:00 PM 2017-01-25 10:02:03 2017-01-25 10:02:03
95. 25 Jan 2017 1:2:3 Z +03:30 PM 2017-01-25 09:32:03 2017-01-25 09:32:03
96. 25 Jan 2017 1:2:3Z Mo ᴺᵁᴸᴸ 1970-01-01 00:00:00
97. 25 Jan 2017 1:2:3Z Mon 2017-01-25 01:02:03 2017-01-25 01:02:03
98. 25 Jan 2017 1:2:3Z Moo ᴺᵁᴸᴸ 1970-01-01 00:00:00
99. 25 Jan 2017 1:2:3 Z PM 2017-01-25 13:02:03 2017-01-25 13:02:03
100. 25 Jan 2017 1:2:3Z PM 2017-01-25 13:02:03 2017-01-25 13:02:03
101. 25 Jan 2017 1:2:3 Z PM +03:00 2017-01-25 10:02:03 2017-01-25 10:02:03
102. Jun, 11 Feb 2018 06:40:50 +0300 ᴺᵁᴸᴸ 1970-01-01 00:00:00
103. Sun 11 Feb 2018 06:40:50 +0300 2018-02-11 03:40:50 2018-02-11 03:40:50
104. Sun, 11 Feb 2018 06:40:50 +0300 2018-02-11 03:40:50 2018-02-11 03:40:50

View File

@ -1,102 +1,102 @@
┌─range(number)──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ [] │
│ [0] │
│ [0,1] │
│ [0,1,2] │
│ [0,1,2,3] │
│ [0,1,2,3,4] │
│ [0,1,2,3,4,5] │
│ [0,1,2,3,4,5,6] │
│ [0,1,2,3,4,5,6,7] │
│ [0,1,2,3,4,5,6,7,8] │
│ [0,1,2,3,4,5,6,7,8,9] │
│ [0,1,2,3,4,5,6,7,8,9,10] │
│ [0,1,2,3,4,5,6,7,8,9,10,11] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97] │
│ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98] │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
┌─range(number)──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
1. │ [] │
2. │ [0] │
3. │ [0,1] │
4. │ [0,1,2] │
5. │ [0,1,2,3] │
6. │ [0,1,2,3,4] │
7. │ [0,1,2,3,4,5] │
8. │ [0,1,2,3,4,5,6] │
9. │ [0,1,2,3,4,5,6,7] │
10. │ [0,1,2,3,4,5,6,7,8] │
11. │ [0,1,2,3,4,5,6,7,8,9] │
12. │ [0,1,2,3,4,5,6,7,8,9,10] │
13. │ [0,1,2,3,4,5,6,7,8,9,10,11] │
14. │ [0,1,2,3,4,5,6,7,8,9,10,11,12] │
15. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13] │
16. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14] │
17. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] │
18. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] │
19. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17] │
20. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18] │
21. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19] │
22. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] │
23. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21] │
24. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22] │
25. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23] │
26. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24] │
27. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25] │
28. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26] │
29. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27] │
30. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28] │
31. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29] │
32. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30] │
33. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31] │
34. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32] │
35. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33] │
36. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34] │
37. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35] │
38. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36] │
39. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37] │
40. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38] │
41. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39] │
42. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40] │
43. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41] │
44. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42] │
45. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43] │
46. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44] │
47. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45] │
48. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46] │
49. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47] │
50. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48] │
51. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49] │
52. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50] │
53. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51] │
54. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52] │
55. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53] │
56. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54] │
57. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55] │
58. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56] │
59. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57] │
60. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58] │
61. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59] │
62. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60] │
63. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61] │
64. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62] │
65. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63] │
66. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64] │
67. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65] │
68. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66] │
69. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67] │
70. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68] │
71. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69] │
72. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70] │
73. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71] │
74. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72] │
75. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73] │
76. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74] │
77. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75] │
78. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76] │
79. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77] │
80. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78] │
81. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79] │
82. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80] │
83. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81] │
84. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82] │
85. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83] │
86. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84] │
87. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85] │
88. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86] │
89. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87] │
90. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88] │
91. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89] │
92. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90] │
93. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91] │
94. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92] │
95. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93] │
96. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94] │
97. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95] │
98. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96] │
99. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97] │
100. │ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98] │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

View File

@ -1,39 +1,39 @@
┌─database─┬─name─┐
│ system │ one │
└──────────┴──────┘
┌─database─┬─name─┐
│ system │ one │
└──────────┴──────┘
┌─database─┬─name─┐
│ system │ one │
└──────────┴──────┘
┌─x──────┬─name─┐
│ system │ one │
└────────┴──────┘
┌─database─┬─name─┐
│ system │ one │
└──────────┴──────┘
┌─x──────┬─name─┐
│ system │ one │
└────────┴──────┘
┌─database─┬─name─┐
│ system │ one │
└──────────┴──────┘
┌─db.x───┬─name─┐
│ system │ one │
└────────┴──────┘
┌─db.name─┬─name─┐
│ system │ one │
└─────────┴──────┘
┌─db.name─┬─name─┐
│ system │ one │
└─────────┴──────┘
┌─database─┬─name─┐
│ system │ one │
└──────────┴──────┘
┌─database─┬─name─┐
│ system │ one │
└──────────┴──────┘
┌─database─┬─name─┐
1. │ system │ one │
└──────────┴──────┘
┌─database─┬─name─┐
1. │ system │ one │
└──────────┴──────┘
┌─database─┬─name─┐
1. │ system │ one │
└──────────┴──────┘
┌─x──────┬─name─┐
1. │ system │ one │
└────────┴──────┘
┌─database─┬─name─┐
1. │ system │ one │
└──────────┴──────┘
┌─x──────┬─name─┐
1. │ system │ one │
└────────┴──────┘
┌─database─┬─name─┐
1. │ system │ one │
└──────────┴──────┘
┌─db.x───┬─name─┐
1. │ system │ one │
└────────┴──────┘
┌─db.name─┬─name─┐
1. │ system │ one │
└─────────┴──────┘
┌─db.name─┬─name─┐
1. │ system │ one │
└─────────┴──────┘
┌─database─┬─name─┐
1. │ system │ one │
└──────────┴──────┘
┌─database─┬─name─┐
1. │ system │ one │
└──────────┴──────┘
2
2
2

View File

@ -1,5 +1,6 @@
-- Tags: long, no-replicated-database
-- Tag no-replicated-database: Unsupported type of ALTER query
SET output_format_pretty_row_numbers = 0;
DROP TABLE IF EXISTS check_query_comment_column;

View File

@ -1,88 +1,88 @@
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Здравствуйте │ Этот код можно отредактировать и запустить! │
└──────────────┴─────────────────────────────────────────────┘
┏━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 你好 │ 这段代码是可以编辑并且能够运行的! │
└──────┴────────────────────────────────────┘
┏━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Hola │ ¡Este código es editable y ejecutable! │
└──────┴────────────────────────────────────────┘
┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Bonjour │ Ce code est modifiable et exécutable ! │
└─────────┴────────────────────────────────────────┘
┏━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Ciao │ Questo codice è modificabile ed eseguibile! │
└──────┴─────────────────────────────────────────────┘
┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ こんにちは │ このコードは編集して実行出来ます! │
└────────────┴────────────────────────────────────┘
┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 안녕하세요 │ 여기에서 코드를 수정하고 실행할 수 있습니다! │
└────────────┴──────────────────────────────────────────────┘
┏━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Cześć │ Ten kod można edytować oraz uruchomić! │
└───────┴────────────────────────────────────────┘
┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Olá │ Este código é editável e executável! │
└─────┴──────────────────────────────────────┘
┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Chào bạn │ Bạn có thể edit và run code trực tiếp! │
└──────────┴────────────────────────────────────────┘
┏━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Hallo │ Dieser Code kann bearbeitet und ausgeführt werden! │
└───────┴────────────────────────────────────────────────────┘
┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Hej │ Den här koden kan redigeras och köras! │
└─────┴────────────────────────────────────────┘
┏━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Ahoj │ Tento kód můžete upravit a spustit │
└──────┴────────────────────────────────────┘
┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ Tabs Tabs │ Non-first Tabs │
└─────────────┴───────────────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Control characters  with zero width │ Invalid UTF-8 which eats pending characters <20>, or invalid by itself <20> with zero width │
└─────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────┘
┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Russian ё and ё │ Zero bytes in middle │
└──────────────────┴────────────────────────┘
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ 'Tabs \t Tabs' ┃ 'Long\tTitle' ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ Tabs Tabs │ Long Title │
└────────────────┴───────────────┘
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
1. │ Здравствуйте │ Этот код можно отредактировать и запустить! │
└──────────────┴─────────────────────────────────────────────┘
┏━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
2. │ 你好 │ 这段代码是可以编辑并且能够运行的! │
└──────┴────────────────────────────────────┘
┏━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
3. │ Hola │ ¡Este código es editable y ejecutable! │
└──────┴────────────────────────────────────────┘
┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
4. │ Bonjour │ Ce code est modifiable et exécutable ! │
└─────────┴────────────────────────────────────────┘
┏━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
5. │ Ciao │ Questo codice è modificabile ed eseguibile! │
└──────┴─────────────────────────────────────────────┘
┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
6. │ こんにちは │ このコードは編集して実行出来ます! │
└────────────┴────────────────────────────────────┘
┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
7. │ 안녕하세요 │ 여기에서 코드를 수정하고 실행할 수 있습니다! │
└────────────┴──────────────────────────────────────────────┘
┏━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
8. │ Cześć │ Ten kod można edytować oraz uruchomić! │
└───────┴────────────────────────────────────────┘
┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
9. │ Olá │ Este código é editável e executável! │
└─────┴──────────────────────────────────────┘
┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
10. │ Chào bạn │ Bạn có thể edit và run code trực tiếp! │
└──────────┴────────────────────────────────────────┘
┏━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
11. │ Hallo │ Dieser Code kann bearbeitet und ausgeführt werden! │
└───────┴────────────────────────────────────────────────────┘
┏━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
12. │ Hej │ Den här koden kan redigeras och köras! │
└─────┴────────────────────────────────────────┘
┏━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
13. │ Ahoj │ Tento kód můžete upravit a spustit │
└──────┴────────────────────────────────────┘
┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
14. │ Tabs Tabs │ Non-first Tabs │
└─────────────┴───────────────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
15. │ Control characters  with zero width │ Invalid UTF-8 which eats pending characters <20>, or invalid by itself <20> with zero width │
└─────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────┘
┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ c1 ┃ c2 ┃
┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
16. │ Russian ё and ё │ Zero bytes in middle │
└──────────────────┴────────────────────────┘
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ 'Tabs \t Tabs' ┃ 'Long\tTitle' ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
1. │ Tabs Tabs │ Long Title │
└────────────────┴───────────────┘
Row 1:
──────
'你好': 你好

View File

@ -1,4 +1,5 @@
-- Tags: long, no-s3-storage, no-random-merge-tree-settings
SET output_format_pretty_row_numbers = 0;
DROP TABLE IF EXISTS check_system_tables;

View File

@ -1,22 +1,22 @@
s a b
s a b
24.12.2018 2018-12-24 00:00:00 2018-12-24 00:00:00
24-12-2018 2018-12-24 00:00:00 2018-12-24 00:00:00
24.12.18 2018-12-24 00:00:00 2018-12-24 00:00:00
24-12-18 2018-12-24 00:00:00 2018-12-24 00:00:00
24-Dec-18 2018-12-24 00:00:00 2018-12-24 00:00:00
24/DEC/18 2018-12-24 00:00:00 2018-12-24 00:00:00
24/DEC/2018 2018-12-24 00:00:00 2018-12-24 00:00:00
01-OCT-2015 2015-10-01 00:00:00 2015-10-01 00:00:00
24.12.2018 2018-12-24 00:00:00 2018-12-24 00:00:00
24-12-2018 2018-12-24 00:00:00 2018-12-24 00:00:00
24.12.18 2018-12-24 00:00:00 2018-12-24 00:00:00
24-12-18 2018-12-24 00:00:00 2018-12-24 00:00:00
24-Dec-18 2018-12-24 00:00:00 2018-12-24 00:00:00
24/DEC/18 2018-12-24 00:00:00 2018-12-24 00:00:00
24/DEC/2018 2018-12-24 00:00:00 2018-12-24 00:00:00
01-OCT-2015 2015-10-01 00:00:00 2015-10-01 00:00:00
24.12.18 010203 2018-12-24 01:02:03 2018-12-24 01:02:03
24.12.18 01:02:03 2018-12-24 01:02:03 2018-12-24 01:02:03
24.DEC.18T01:02:03.000+0300 2018-12-23 22:02:03 2018-12-23 22:02:03
01-September-2018 11:22 2018-09-01 11:22:00 2018-09-01 11:22:00
1. 24.12.2018 2018-12-24 00:00:00 2018-12-24 00:00:00
2. 24-12-2018 2018-12-24 00:00:00 2018-12-24 00:00:00
3. 24.12.18 2018-12-24 00:00:00 2018-12-24 00:00:00
4. 24-12-18 2018-12-24 00:00:00 2018-12-24 00:00:00
5. 24-Dec-18 2018-12-24 00:00:00 2018-12-24 00:00:00
6. 24/DEC/18 2018-12-24 00:00:00 2018-12-24 00:00:00
7. 24/DEC/2018 2018-12-24 00:00:00 2018-12-24 00:00:00
8. 01-OCT-2015 2015-10-01 00:00:00 2015-10-01 00:00:00
9. 24.12.2018 2018-12-24 00:00:00 2018-12-24 00:00:00
10. 24-12-2018 2018-12-24 00:00:00 2018-12-24 00:00:00
11. 24.12.18 2018-12-24 00:00:00 2018-12-24 00:00:00
12. 24-12-18 2018-12-24 00:00:00 2018-12-24 00:00:00
13. 24-Dec-18 2018-12-24 00:00:00 2018-12-24 00:00:00
14. 24/DEC/18 2018-12-24 00:00:00 2018-12-24 00:00:00
15. 24/DEC/2018 2018-12-24 00:00:00 2018-12-24 00:00:00
16. 01-OCT-2015 2015-10-01 00:00:00 2015-10-01 00:00:00
17. 24.12.18 010203 2018-12-24 01:02:03 2018-12-24 01:02:03
18. 24.12.18 01:02:03 2018-12-24 01:02:03 2018-12-24 01:02:03
19. 24.DEC.18T01:02:03.000+0300 2018-12-23 22:02:03 2018-12-23 22:02:03
20. 01-September-2018 11:22 2018-09-01 11:22:00 2018-09-01 11:22:00

View File

@ -1,19 +1,19 @@
┌─a─┬──────────b─┐
│ a │ 2018-01-01 │
│ b │ 2018-01-01 │
│ c │ 2018-01-01 │
└───┴────────────┘
┌─c─┬─table2.a─┬──────────d─┬─a─┬──────────b─┐
│ B │ b │ 2018-01-01 │ B │ 2018-01-01 │
│ C │ c │ 2018-01-01 │ C │ 2018-01-01 │
│ D │ d │ 2018-01-01 │ D │ 2018-01-01 │
└───┴──────────┴────────────┴───┴────────────┘
┌─a─┬──────────b─┬─c─┬──────────d─┬─c─┐
│ a │ 2018-01-01 │ │ 1970-01-01 │ │
│ b │ 2018-01-01 │ B │ 2018-01-01 │ B │
│ c │ 2018-01-01 │ C │ 2018-01-01 │ C │
└───┴────────────┴───┴────────────┴───┘
┌─a─┬──────────b─┬─c─┬──────────d─┬─c─┐
│ b │ 2018-01-01 │ B │ 2018-01-01 │ B │
│ c │ 2018-01-01 │ C │ 2018-01-01 │ C │
└───┴────────────┴───┴────────────┴───┘
┌─a─┬──────────b─┐
1. │ a │ 2018-01-01 │
2. │ b │ 2018-01-01 │
3. │ c │ 2018-01-01 │
└───┴────────────┘
┌─c─┬─table2.a─┬──────────d─┬─a─┬──────────b─┐
1. │ B │ b │ 2018-01-01 │ B │ 2018-01-01 │
2. │ C │ c │ 2018-01-01 │ C │ 2018-01-01 │
3. │ D │ d │ 2018-01-01 │ D │ 2018-01-01 │
└───┴──────────┴────────────┴───┴────────────┘
┌─a─┬──────────b─┬─c─┬──────────d─┬─c─┐
1. │ a │ 2018-01-01 │ │ 1970-01-01 │ │
2. │ b │ 2018-01-01 │ B │ 2018-01-01 │ B │
3. │ c │ 2018-01-01 │ C │ 2018-01-01 │ C │
└───┴────────────┴───┴────────────┴───┘
┌─a─┬──────────b─┬─c─┬──────────d─┬─c─┐
1. │ b │ 2018-01-01 │ B │ 2018-01-01 │ B │
2. │ c │ 2018-01-01 │ C │ 2018-01-01 │ C │
└───┴────────────┴───┴────────────┴───┘

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