mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 15:42:02 +00:00
Merge branch 'master' into fix-comment
This commit is contained in:
commit
5722557391
@ -96,5 +96,4 @@ rg -Fa "Fatal" /var/log/clickhouse-server/clickhouse-server.log ||:
|
||||
zstd < /var/log/clickhouse-server/clickhouse-server.log > /test_output/clickhouse-server.log.zst &
|
||||
|
||||
# Compressed (FIXME: remove once only github actions will be left)
|
||||
rm /var/log/clickhouse-server/clickhouse-server.log
|
||||
mv /var/log/clickhouse-server/stderr.log /test_output/ ||:
|
||||
|
@ -16,14 +16,14 @@ All available clusters are listed in the [system.clusters](../../operations/syst
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
cluster('cluster_name', db.table[, sharding_key])
|
||||
cluster('cluster_name', db, table[, sharding_key])
|
||||
clusterAllReplicas('cluster_name', db.table[, sharding_key])
|
||||
clusterAllReplicas('cluster_name', db, table[, sharding_key])
|
||||
cluster(['cluster_name', db.table, sharding_key])
|
||||
cluster(['cluster_name', db, table, sharding_key])
|
||||
clusterAllReplicas(['cluster_name', db.table, sharding_key])
|
||||
clusterAllReplicas(['cluster_name', db, table, sharding_key])
|
||||
```
|
||||
**Arguments**
|
||||
|
||||
- `cluster_name` – Name of a cluster that is used to build a set of addresses and connection parameters to remote and local servers.
|
||||
- `cluster_name` – Name of a cluster that is used to build a set of addresses and connection parameters to remote and local servers, set `default` if not specified.
|
||||
- `db.table` or `db`, `table` - Name of a database and a table.
|
||||
- `sharding_key` - A sharding key. Optional. Needs to be specified if the cluster has more than one shard.
|
||||
|
||||
|
@ -13,10 +13,10 @@ Both functions can be used in `SELECT` and `INSERT` queries.
|
||||
## Syntax
|
||||
|
||||
``` sql
|
||||
remote('addresses_expr', db, table[, 'user'[, 'password'], sharding_key])
|
||||
remote('addresses_expr', db.table[, 'user'[, 'password'], sharding_key])
|
||||
remoteSecure('addresses_expr', db, table[, 'user'[, 'password'], sharding_key])
|
||||
remoteSecure('addresses_expr', db.table[, 'user'[, 'password'], sharding_key])
|
||||
remote('addresses_expr', [db, table, 'user'[, 'password'], sharding_key])
|
||||
remote('addresses_expr', [db.table, 'user'[, 'password'], sharding_key])
|
||||
remoteSecure('addresses_expr', [db, table, 'user'[, 'password'], sharding_key])
|
||||
remoteSecure('addresses_expr', [db.table, 'user'[, 'password'], sharding_key])
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -29,6 +29,8 @@ remoteSecure('addresses_expr', db.table[, 'user'[, 'password'], sharding_key])
|
||||
|
||||
The port is required for an IPv6 address.
|
||||
|
||||
If only specify this parameter, `db` and `table` will use `system.one` by default.
|
||||
|
||||
Type: [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
- `db` — Database name. Type: [String](../../sql-reference/data-types/string.md).
|
||||
|
@ -266,8 +266,16 @@ void KeeperClient::runInteractive()
|
||||
|
||||
LineReader::Patterns query_extenders = {"\\"};
|
||||
LineReader::Patterns query_delimiters = {};
|
||||
char word_break_characters[] = " \t\v\f\a\b\r\n/";
|
||||
|
||||
ReplxxLineReader lr(suggest, history_file, false, query_extenders, query_delimiters, {});
|
||||
ReplxxLineReader lr(
|
||||
suggest,
|
||||
history_file,
|
||||
/* multiline= */ false,
|
||||
query_extenders,
|
||||
query_delimiters,
|
||||
word_break_characters,
|
||||
/* highlighter_= */ {});
|
||||
lr.enableBracketedPaste();
|
||||
|
||||
while (true)
|
||||
|
@ -466,6 +466,11 @@ int main(int argc_, char ** argv_)
|
||||
checkHarmfulEnvironmentVariables(argv_);
|
||||
#endif
|
||||
|
||||
/// This is used for testing. For example,
|
||||
/// clickhouse-local should be able to run a simple query without throw/catch.
|
||||
if (getenv("CLICKHOUSE_TERMINATE_ON_ANY_EXCEPTION")) // NOLINT(concurrency-mt-unsafe)
|
||||
DB::terminate_on_any_exception = true;
|
||||
|
||||
/// Reset new handler to default (that throws std::bad_alloc)
|
||||
/// It is needed because LLVM library clobbers it.
|
||||
std::set_new_handler(nullptr);
|
||||
|
231
rust/Cargo.lock
generated
231
rust/Cargo.lock
generated
@ -78,6 +78,55 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is-terminal",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.72"
|
||||
@ -89,9 +138,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ariadne"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "367fd0ad87307588d087544707bc5fbf4805ded96c7db922b70d368fa1cb5702"
|
||||
checksum = "72fe02fc62033df9ba41cba57ee19acf5e742511a140c7dbc3a873e19a19a1bd"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
"yansi",
|
||||
@ -142,6 +191,12 @@ version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.4.1"
|
||||
@ -204,7 +259,7 @@ version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23170228b96236b5a7299057ac284a321457700bc8c41a4476052f0f4ba5349d"
|
||||
dependencies = [
|
||||
"hashbrown 0.12.3",
|
||||
"hashbrown",
|
||||
"stacker",
|
||||
]
|
||||
|
||||
@ -218,6 +273,12 @@ dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.3.0"
|
||||
@ -488,21 +549,36 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "enum-as-inner"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116"
|
||||
checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
name = "errno"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
@ -555,12 +631,6 @@ dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
@ -603,13 +673,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.0.0"
|
||||
name = "is-terminal"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.0",
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -621,6 +692,15 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
@ -657,6 +737,12 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.19"
|
||||
@ -708,7 +794,7 @@ version = "0.24.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
@ -720,7 +806,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset 0.6.5",
|
||||
@ -787,31 +873,55 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prql-compiler"
|
||||
version = "0.8.1"
|
||||
name = "prql-ast"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c99b52154002ac7f286dd2293c2f8d4e30526c1d396b14deef5ada1deef3c9ff"
|
||||
checksum = "71194e75f14dbe7debdf2b5eca0812c978021a1bd23d6fe1da98b58e407e035a"
|
||||
dependencies = [
|
||||
"enum-as-inner",
|
||||
"semver",
|
||||
"serde",
|
||||
"strum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prql-compiler"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ff28e838b1be4227cc567a75c11caa3be25c5015f0e5fd21279c06e944ba44f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anyhow",
|
||||
"ariadne",
|
||||
"chumsky",
|
||||
"csv",
|
||||
"enum-as-inner",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"itertools 0.11.0",
|
||||
"log",
|
||||
"once_cell",
|
||||
"prql-ast",
|
||||
"prql-parser",
|
||||
"regex",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"sqlformat",
|
||||
"sqlparser",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prql-parser"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3182e2ef0465a960eb02519b18768e39123d3c3a0037a2d2934055a3ef901870"
|
||||
dependencies = [
|
||||
"chumsky",
|
||||
"itertools 0.11.0",
|
||||
"prql-ast",
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psm"
|
||||
version = "0.1.21"
|
||||
@ -858,7 +968,7 @@ version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -907,6 +1017,19 @@ version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ee020b1716f0a80e2ace9b03441a749e402e86712f15f16fe8a8f75afac732f"
|
||||
dependencies = [
|
||||
"bitflags 2.3.3",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
@ -971,19 +1094,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "skim"
|
||||
version = "0.10.4"
|
||||
@ -991,7 +1101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d28de0a6cb2cdd83a076f1de9d965b973ae08b244df1aa70b432946dda0f32"
|
||||
dependencies = [
|
||||
"beef",
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"chrono",
|
||||
"crossbeam",
|
||||
"defer-drop",
|
||||
@ -1015,16 +1125,16 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"itertools 0.10.5",
|
||||
"nom",
|
||||
"unicode_categories",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlparser"
|
||||
version = "0.33.0"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "355dc4d4b6207ca8a3434fc587db0a8016130a574dbcdbfb93d7f7b5bc5b211a"
|
||||
checksum = "2eaa1e88e78d2c2460d78b7dc3f0c08dbb606ab4222f9aff36f420d36e307d87"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
@ -1051,24 +1161,24 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.24.1"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.24.3"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
||||
checksum = "6069ca09d878a33f883cc06aaa9718ede171841d3832450354410b718b097232"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1191,7 +1301,7 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e19c6ab038babee3d50c8c12ff8b910bdb2196f62278776422f50390d8e53d8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 1.3.2",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"nix 0.24.3",
|
||||
@ -1223,12 +1333,6 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
@ -1368,6 +1472,15 @@ dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.1"
|
||||
|
@ -1,12 +1,12 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "_ch_rust_prql"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
prql-compiler = "0.8.1"
|
||||
prql-compiler = "0.9.3"
|
||||
serde_json = "1.0"
|
||||
|
||||
[lib]
|
||||
|
@ -2313,15 +2313,28 @@ void ClientBase::runInteractive()
|
||||
|
||||
LineReader::Patterns query_extenders = {"\\"};
|
||||
LineReader::Patterns query_delimiters = {";", "\\G", "\\G;"};
|
||||
char word_break_characters[] = " \t\v\f\a\b\r\n`~!@#$%^&*()-=+[{]}\\|;:'\",<.>/?";
|
||||
|
||||
#if USE_REPLXX
|
||||
replxx::Replxx::highlighter_callback_t highlight_callback{};
|
||||
if (config().getBool("highlight", true))
|
||||
highlight_callback = highlight;
|
||||
|
||||
ReplxxLineReader lr(*suggest, history_file, config().has("multiline"), query_extenders, query_delimiters, highlight_callback);
|
||||
ReplxxLineReader lr(
|
||||
*suggest,
|
||||
history_file,
|
||||
config().has("multiline"),
|
||||
query_extenders,
|
||||
query_delimiters,
|
||||
word_break_characters,
|
||||
highlight_callback);
|
||||
#else
|
||||
LineReader lr(history_file, config().has("multiline"), query_extenders, query_delimiters);
|
||||
LineReader lr(
|
||||
history_file,
|
||||
config().has("multiline"),
|
||||
query_extenders,
|
||||
query_delimiters,
|
||||
word_break_characters);
|
||||
#endif
|
||||
|
||||
static const std::initializer_list<std::pair<String, String>> backslash_aliases =
|
||||
|
@ -66,7 +66,7 @@ void addNewWords(Words & to, const Words & from, Compare comp)
|
||||
namespace DB
|
||||
{
|
||||
|
||||
replxx::Replxx::completions_t LineReader::Suggest::getCompletions(const String & prefix, size_t prefix_length)
|
||||
replxx::Replxx::completions_t LineReader::Suggest::getCompletions(const String & prefix, size_t prefix_length, const char * word_break_characters)
|
||||
{
|
||||
std::string_view last_word;
|
||||
|
||||
@ -135,7 +135,10 @@ void LineReader::Suggest::addWords(Words && new_words)
|
||||
}
|
||||
|
||||
LineReader::LineReader(const String & history_file_path_, bool multiline_, Patterns extenders_, Patterns delimiters_)
|
||||
: history_file_path(history_file_path_), multiline(multiline_), extenders(std::move(extenders_)), delimiters(std::move(delimiters_))
|
||||
: history_file_path(history_file_path_)
|
||||
, multiline(multiline_)
|
||||
, extenders(std::move(extenders_))
|
||||
, delimiters(std::move(delimiters_))
|
||||
{
|
||||
/// FIXME: check extender != delimiter
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public:
|
||||
using Callback = std::function<Words(const String & prefix, size_t prefix_length)>;
|
||||
|
||||
/// Get vector for the matched range of words if any.
|
||||
replxx::Replxx::completions_t getCompletions(const String & prefix, size_t prefix_length);
|
||||
replxx::Replxx::completions_t getCompletions(const String & prefix, size_t prefix_length, const char * word_break_characters);
|
||||
void addWords(Words && new_words);
|
||||
|
||||
void setCompletionsCallback(Callback && callback) { custom_completions_callback = callback; }
|
||||
@ -65,7 +65,6 @@ protected:
|
||||
};
|
||||
|
||||
const String history_file_path;
|
||||
static constexpr char word_break_characters[] = " \t\v\f\a\b\r\n`~!@#$%^&*()-=+[{]}\\|;:'\",<.>/?";
|
||||
|
||||
String input;
|
||||
|
||||
|
@ -287,8 +287,10 @@ ReplxxLineReader::ReplxxLineReader(
|
||||
bool multiline_,
|
||||
Patterns extenders_,
|
||||
Patterns delimiters_,
|
||||
const char word_break_characters_[],
|
||||
replxx::Replxx::highlighter_callback_t highlighter_)
|
||||
: LineReader(history_file_path_, multiline_, std::move(extenders_), std::move(delimiters_)), highlighter(std::move(highlighter_))
|
||||
, word_break_characters(word_break_characters_)
|
||||
, editor(getEditor())
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
@ -326,9 +328,9 @@ ReplxxLineReader::ReplxxLineReader(
|
||||
|
||||
rx.install_window_change_handler();
|
||||
|
||||
auto callback = [&suggest] (const String & context, size_t context_size)
|
||||
auto callback = [&suggest, this] (const String & context, size_t context_size)
|
||||
{
|
||||
return suggest.getCompletions(context, context_size);
|
||||
return suggest.getCompletions(context, context_size, word_break_characters);
|
||||
};
|
||||
|
||||
rx.set_completion_callback(callback);
|
||||
|
@ -15,6 +15,7 @@ public:
|
||||
bool multiline,
|
||||
Patterns extenders_,
|
||||
Patterns delimiters_,
|
||||
const char word_break_characters_[],
|
||||
replxx::Replxx::highlighter_callback_t highlighter_);
|
||||
~ReplxxLineReader() override;
|
||||
|
||||
@ -33,6 +34,8 @@ private:
|
||||
replxx::Replxx rx;
|
||||
replxx::Replxx::highlighter_callback_t highlighter;
|
||||
|
||||
const char * word_break_characters;
|
||||
|
||||
// used to call flock() to synchronize multiple clients using same history file
|
||||
int history_file_fd = -1;
|
||||
bool bracketed_paste_enabled = false;
|
||||
|
@ -50,6 +50,8 @@ void abortOnFailedAssertion(const String & description)
|
||||
abort();
|
||||
}
|
||||
|
||||
bool terminate_on_any_exception = false;
|
||||
|
||||
/// - Aborts the process if error code is LOGICAL_ERROR.
|
||||
/// - Increments error codes statistics.
|
||||
void handle_error_code([[maybe_unused]] const std::string & msg, int code, bool remote, const Exception::FramePointers & trace)
|
||||
@ -84,6 +86,8 @@ Exception::Exception(const MessageMasked & msg_masked, int code, bool remote_)
|
||||
: Poco::Exception(msg_masked.msg, code)
|
||||
, remote(remote_)
|
||||
{
|
||||
if (terminate_on_any_exception)
|
||||
std::terminate();
|
||||
capture_thread_frame_pointers = thread_frame_pointers;
|
||||
handle_error_code(msg_masked.msg, code, remote, getStackFramePointers());
|
||||
}
|
||||
@ -92,6 +96,8 @@ Exception::Exception(MessageMasked && msg_masked, int code, bool remote_)
|
||||
: Poco::Exception(msg_masked.msg, code)
|
||||
, remote(remote_)
|
||||
{
|
||||
if (terminate_on_any_exception)
|
||||
std::terminate();
|
||||
capture_thread_frame_pointers = thread_frame_pointers;
|
||||
handle_error_code(message(), code, remote, getStackFramePointers());
|
||||
}
|
||||
@ -99,6 +105,8 @@ Exception::Exception(MessageMasked && msg_masked, int code, bool remote_)
|
||||
Exception::Exception(CreateFromPocoTag, const Poco::Exception & exc)
|
||||
: Poco::Exception(exc.displayText(), ErrorCodes::POCO_EXCEPTION)
|
||||
{
|
||||
if (terminate_on_any_exception)
|
||||
std::terminate();
|
||||
capture_thread_frame_pointers = thread_frame_pointers;
|
||||
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
|
||||
auto * stack_trace_frames = exc.get_stack_trace_frames();
|
||||
@ -111,6 +119,8 @@ Exception::Exception(CreateFromPocoTag, const Poco::Exception & exc)
|
||||
Exception::Exception(CreateFromSTDTag, const std::exception & exc)
|
||||
: Poco::Exception(demangle(typeid(exc).name()) + ": " + String(exc.what()), ErrorCodes::STD_EXCEPTION)
|
||||
{
|
||||
if (terminate_on_any_exception)
|
||||
std::terminate();
|
||||
capture_thread_frame_pointers = thread_frame_pointers;
|
||||
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
|
||||
auto * stack_trace_frames = exc.get_stack_trace_frames();
|
||||
|
@ -20,6 +20,10 @@ namespace DB
|
||||
|
||||
void abortOnFailedAssertion(const String & description);
|
||||
|
||||
/// This flag can be set for testing purposes - to check that no exceptions are thrown.
|
||||
extern bool terminate_on_any_exception;
|
||||
|
||||
|
||||
class Exception : public Poco::Exception
|
||||
{
|
||||
public:
|
||||
@ -27,17 +31,23 @@ public:
|
||||
|
||||
Exception()
|
||||
{
|
||||
if (terminate_on_any_exception)
|
||||
std::terminate();
|
||||
capture_thread_frame_pointers = thread_frame_pointers;
|
||||
}
|
||||
|
||||
Exception(const PreformattedMessage & msg, int code): Exception(msg.text, code)
|
||||
{
|
||||
if (terminate_on_any_exception)
|
||||
std::terminate();
|
||||
capture_thread_frame_pointers = thread_frame_pointers;
|
||||
message_format_string = msg.format_string;
|
||||
}
|
||||
|
||||
Exception(PreformattedMessage && msg, int code): Exception(std::move(msg.text), code)
|
||||
{
|
||||
if (terminate_on_any_exception)
|
||||
std::terminate();
|
||||
capture_thread_frame_pointers = thread_frame_pointers;
|
||||
message_format_string = msg.format_string;
|
||||
}
|
||||
|
@ -783,6 +783,7 @@ class IColumn;
|
||||
M(UInt64, extract_kvp_max_pairs_per_row, 1000, "Max number pairs that can be produced by extractKeyValuePairs function. Used to safeguard against consuming too much memory.", 0) \
|
||||
M(Timezone, session_timezone, "", "This setting can be removed in the future due to potential caveats. It is experimental and is not suitable for production usage. The default timezone for current session or query. The server default timezone if empty.", 0) \
|
||||
M(Bool, allow_create_index_without_type, false, "Allow CREATE INDEX query without TYPE. Query will be ignored. Made for SQL compatibility tests.", 0)\
|
||||
M(Bool, create_index_ignore_unique, false, "Ignore UNIQUE keyword in CREATE UNIQUE INDEX. Made for SQL compatibility tests.", 0)\
|
||||
// End of COMMON_SETTINGS
|
||||
// Please add settings related to formats into the FORMAT_FACTORY_SETTINGS and move obsolete settings to OBSOLETE_SETTINGS.
|
||||
|
||||
|
@ -77,7 +77,6 @@ public:
|
||||
void deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override;
|
||||
void serializeTextJSONPretty(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings, size_t indent) const override;
|
||||
|
||||
|
||||
void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const override;
|
||||
};
|
||||
|
||||
|
@ -11,9 +11,11 @@
|
||||
#include <Storages/IStorage.h>
|
||||
#include <TableFunctions/TableFunctionFactory.h>
|
||||
#include <Common/filesystemHelpers.h>
|
||||
#include <Formats/FormatFactory.h>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace DB
|
||||
@ -75,10 +77,8 @@ bool DatabaseFilesystem::checkTableFilePath(const std::string & table_path, Cont
|
||||
/// Check access for file before checking its existence.
|
||||
if (check_path && !fileOrSymlinkPathStartsWith(table_path, user_files_path))
|
||||
{
|
||||
if (throw_on_error)
|
||||
throw Exception(ErrorCodes::PATH_ACCESS_DENIED, "File is not inside {}", user_files_path);
|
||||
else
|
||||
return false;
|
||||
/// Access denied is thrown regardless of 'throw_on_error'
|
||||
throw Exception(ErrorCodes::PATH_ACCESS_DENIED, "File is not inside {}", user_files_path);
|
||||
}
|
||||
|
||||
/// Check if the corresponding file exists.
|
||||
@ -128,20 +128,25 @@ bool DatabaseFilesystem::isTableExist(const String & name, ContextPtr context_)
|
||||
if (tryGetTableFromCache(name))
|
||||
return true;
|
||||
|
||||
return checkTableFilePath(getTablePath(name), context_, /* throw_on_error */false);
|
||||
return checkTableFilePath(getTablePath(name), context_, /* throw_on_error */ false);
|
||||
}
|
||||
|
||||
StoragePtr DatabaseFilesystem::getTableImpl(const String & name, ContextPtr context_) const
|
||||
StoragePtr DatabaseFilesystem::getTableImpl(const String & name, ContextPtr context_, bool throw_on_error) const
|
||||
{
|
||||
/// Check if table exists in loaded tables map.
|
||||
if (auto table = tryGetTableFromCache(name))
|
||||
return table;
|
||||
|
||||
auto table_path = getTablePath(name);
|
||||
checkTableFilePath(table_path, context_, /* throw_on_error */true);
|
||||
if (!checkTableFilePath(table_path, context_, throw_on_error))
|
||||
return {};
|
||||
|
||||
String format = FormatFactory::instance().getFormatFromFileName(table_path, throw_on_error);
|
||||
if (format.empty())
|
||||
return {};
|
||||
|
||||
/// If the file exists, create a new table using TableFunctionFile and return it.
|
||||
auto args = makeASTFunction("file", std::make_shared<ASTLiteral>(table_path));
|
||||
auto args = makeASTFunction("file", std::make_shared<ASTLiteral>(table_path), std::make_shared<ASTLiteral>(format));
|
||||
|
||||
auto table_function = TableFunctionFactory::instance().get(args, context_);
|
||||
if (!table_function)
|
||||
@ -158,7 +163,7 @@ StoragePtr DatabaseFilesystem::getTableImpl(const String & name, ContextPtr cont
|
||||
StoragePtr DatabaseFilesystem::getTable(const String & name, ContextPtr context_) const
|
||||
{
|
||||
/// getTableImpl can throw exceptions, do not catch them to show correct error to user.
|
||||
if (auto storage = getTableImpl(name, context_))
|
||||
if (auto storage = getTableImpl(name, context_, true))
|
||||
return storage;
|
||||
|
||||
throw Exception(ErrorCodes::UNKNOWN_TABLE, "Table {}.{} doesn't exist",
|
||||
@ -167,20 +172,7 @@ StoragePtr DatabaseFilesystem::getTable(const String & name, ContextPtr context_
|
||||
|
||||
StoragePtr DatabaseFilesystem::tryGetTable(const String & name, ContextPtr context_) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return getTableImpl(name, context_);
|
||||
}
|
||||
catch (const Exception & e)
|
||||
{
|
||||
/// Ignore exceptions thrown by TableFunctionFile, which indicate that there is no table
|
||||
/// see tests/02722_database_filesystem.sh for more details.
|
||||
if (e.code() == ErrorCodes::FILE_DOESNT_EXIST)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
return getTableImpl(name, context_, false);
|
||||
}
|
||||
|
||||
bool DatabaseFilesystem::empty() const
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
DatabaseTablesIteratorPtr getTablesIterator(ContextPtr, const FilterByNameFunction &) const override;
|
||||
|
||||
protected:
|
||||
StoragePtr getTableImpl(const String & name, ContextPtr context) const;
|
||||
StoragePtr getTableImpl(const String & name, ContextPtr context, bool throw_on_error) const;
|
||||
|
||||
StoragePtr tryGetTableFromCache(const std::string & name) const;
|
||||
|
||||
|
@ -42,50 +42,13 @@ void ZstdDeflatingAppendableWriteBuffer::nextImpl()
|
||||
if (!offset())
|
||||
return;
|
||||
|
||||
input.src = reinterpret_cast<unsigned char *>(working_buffer.begin());
|
||||
input.size = offset();
|
||||
input.pos = 0;
|
||||
|
||||
if (first_write && append_to_existing_file && isNeedToAddEmptyBlock())
|
||||
{
|
||||
addEmptyBlock();
|
||||
first_write = false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bool ended = false;
|
||||
do
|
||||
{
|
||||
out->nextIfAtEnd();
|
||||
|
||||
output.dst = reinterpret_cast<unsigned char *>(out->buffer().begin());
|
||||
output.size = out->buffer().size();
|
||||
output.pos = out->offset();
|
||||
|
||||
size_t compression_result = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_flush);
|
||||
if (ZSTD_isError(compression_result))
|
||||
throw Exception(
|
||||
ErrorCodes::ZSTD_ENCODER_FAILED,
|
||||
"ZSTD stream decoding failed: error code: {}; ZSTD version: {}",
|
||||
ZSTD_getErrorName(compression_result), ZSTD_VERSION_STRING);
|
||||
|
||||
first_write = false;
|
||||
out->position() = out->buffer().begin() + output.pos;
|
||||
|
||||
bool everything_was_compressed = (input.pos == input.size);
|
||||
bool everything_was_flushed = compression_result == 0;
|
||||
|
||||
ended = everything_was_compressed && everything_was_flushed;
|
||||
} while (!ended);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
/// Do not try to write next time after exception.
|
||||
out->position() = out->buffer().begin();
|
||||
throw;
|
||||
}
|
||||
|
||||
flush(ZSTD_e_flush);
|
||||
}
|
||||
|
||||
ZstdDeflatingAppendableWriteBuffer::~ZstdDeflatingAppendableWriteBuffer()
|
||||
@ -103,58 +66,58 @@ void ZstdDeflatingAppendableWriteBuffer::finalizeImpl()
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
finalizeBefore();
|
||||
out->finalize();
|
||||
finalizeAfter();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
/// Do not try to flush next time after exception.
|
||||
out->position() = out->buffer().begin();
|
||||
throw;
|
||||
}
|
||||
finalizeBefore();
|
||||
out->finalize();
|
||||
finalizeAfter();
|
||||
}
|
||||
}
|
||||
|
||||
void ZstdDeflatingAppendableWriteBuffer::finalizeBefore()
|
||||
{
|
||||
next();
|
||||
|
||||
out->nextIfAtEnd();
|
||||
|
||||
input.src = reinterpret_cast<unsigned char *>(working_buffer.begin());
|
||||
input.size = offset();
|
||||
input.pos = 0;
|
||||
|
||||
output.dst = reinterpret_cast<unsigned char *>(out->buffer().begin());
|
||||
output.size = out->buffer().size();
|
||||
output.pos = out->offset();
|
||||
|
||||
/// Actually we can use ZSTD_e_flush here and add empty termination
|
||||
/// block on each new buffer creation for non-empty file unconditionally (without isNeedToAddEmptyBlock).
|
||||
/// However ZSTD_decompressStream is able to read non-terminated frame (we use it in reader buffer),
|
||||
/// but console zstd utility cannot.
|
||||
size_t remaining = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_end);
|
||||
while (remaining != 0)
|
||||
flush(ZSTD_e_end);
|
||||
}
|
||||
|
||||
void ZstdDeflatingAppendableWriteBuffer::flush(ZSTD_EndDirective mode)
|
||||
{
|
||||
input.src = reinterpret_cast<unsigned char *>(working_buffer.begin());
|
||||
input.size = offset();
|
||||
input.pos = 0;
|
||||
|
||||
try
|
||||
{
|
||||
if (ZSTD_isError(remaining))
|
||||
throw Exception(ErrorCodes::ZSTD_ENCODER_FAILED,
|
||||
"ZSTD stream encoder end failed: error: '{}' ZSTD version: {}",
|
||||
ZSTD_getErrorName(remaining), ZSTD_VERSION_STRING);
|
||||
|
||||
remaining = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_end);
|
||||
|
||||
out->position() = out->buffer().begin() + output.pos;
|
||||
|
||||
if (!out->hasPendingData())
|
||||
bool ended = false;
|
||||
do
|
||||
{
|
||||
out->next();
|
||||
out->nextIfAtEnd();
|
||||
|
||||
output.dst = reinterpret_cast<unsigned char *>(out->buffer().begin());
|
||||
output.size = out->buffer().size();
|
||||
output.pos = out->offset();
|
||||
}
|
||||
|
||||
size_t compression_result = ZSTD_compressStream2(cctx, &output, &input, mode);
|
||||
if (ZSTD_isError(compression_result))
|
||||
throw Exception(
|
||||
ErrorCodes::ZSTD_ENCODER_FAILED,
|
||||
"ZSTD stream decoding failed: error code: {}; ZSTD version: {}",
|
||||
ZSTD_getErrorName(compression_result), ZSTD_VERSION_STRING);
|
||||
|
||||
out->position() = out->buffer().begin() + output.pos;
|
||||
|
||||
bool everything_was_compressed = (input.pos == input.size);
|
||||
bool everything_was_flushed = compression_result == 0;
|
||||
|
||||
ended = everything_was_compressed && everything_was_flushed;
|
||||
} while (!ended);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
/// Do not try to write next time after exception.
|
||||
out->position() = out->buffer().begin();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,8 @@ private:
|
||||
/// NOTE: will fill compressed data to the out.working_buffer, but will not call out.next method until the buffer is full
|
||||
void nextImpl() override;
|
||||
|
||||
void flush(ZSTD_EndDirective mode);
|
||||
|
||||
/// Write terminating ZSTD_e_end: empty block + frame epilogue. BTW it
|
||||
/// should be almost noop, because frame epilogue contains only checksums,
|
||||
/// and they are disabled for this buffer.
|
||||
|
@ -32,13 +32,8 @@ ZstdDeflatingWriteBuffer::ZstdDeflatingWriteBuffer(
|
||||
|
||||
ZstdDeflatingWriteBuffer::~ZstdDeflatingWriteBuffer() = default;
|
||||
|
||||
void ZstdDeflatingWriteBuffer::nextImpl()
|
||||
void ZstdDeflatingWriteBuffer::flush(ZSTD_EndDirective mode)
|
||||
{
|
||||
if (!offset())
|
||||
return;
|
||||
|
||||
ZSTD_EndDirective mode = ZSTD_e_flush;
|
||||
|
||||
input.src = reinterpret_cast<unsigned char *>(working_buffer.begin());
|
||||
input.size = offset();
|
||||
input.pos = 0;
|
||||
@ -54,7 +49,6 @@ void ZstdDeflatingWriteBuffer::nextImpl()
|
||||
output.size = out->buffer().size();
|
||||
output.pos = out->offset();
|
||||
|
||||
|
||||
size_t compression_result = ZSTD_compressStream2(cctx, &output, &input, mode);
|
||||
if (ZSTD_isError(compression_result))
|
||||
throw Exception(
|
||||
@ -78,24 +72,15 @@ void ZstdDeflatingWriteBuffer::nextImpl()
|
||||
}
|
||||
}
|
||||
|
||||
void ZstdDeflatingWriteBuffer::nextImpl()
|
||||
{
|
||||
if (offset())
|
||||
flush(ZSTD_e_flush);
|
||||
}
|
||||
|
||||
void ZstdDeflatingWriteBuffer::finalizeBefore()
|
||||
{
|
||||
next();
|
||||
|
||||
out->nextIfAtEnd();
|
||||
|
||||
input.src = reinterpret_cast<unsigned char *>(working_buffer.begin());
|
||||
input.size = offset();
|
||||
input.pos = 0;
|
||||
|
||||
output.dst = reinterpret_cast<unsigned char *>(out->buffer().begin());
|
||||
output.size = out->buffer().size();
|
||||
output.pos = out->offset();
|
||||
|
||||
size_t remaining = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_end);
|
||||
if (ZSTD_isError(remaining))
|
||||
throw Exception(ErrorCodes::ZSTD_ENCODER_FAILED, "zstd stream encoder end failed: zstd version: {}", ZSTD_VERSION_STRING);
|
||||
out->position() = out->buffer().begin() + output.pos;
|
||||
flush(ZSTD_e_end);
|
||||
}
|
||||
|
||||
void ZstdDeflatingWriteBuffer::finalizeAfter()
|
||||
|
@ -37,6 +37,8 @@ private:
|
||||
void finalizeBefore() override;
|
||||
void finalizeAfter() override;
|
||||
|
||||
void flush(ZSTD_EndDirective mode);
|
||||
|
||||
ZSTD_CCtx * cctx;
|
||||
ZSTD_inBuffer input;
|
||||
ZSTD_outBuffer output;
|
||||
|
@ -587,7 +587,7 @@ KeyMetadata::iterator FileCache::addFileSegment(
|
||||
}
|
||||
}
|
||||
|
||||
bool FileCache::tryReserve(FileSegment & file_segment, const size_t size)
|
||||
bool FileCache::tryReserve(FileSegment & file_segment, const size_t size, FileCacheReserveStat & reserve_stat)
|
||||
{
|
||||
ProfileEventTimeIncrement<Microseconds> watch(ProfileEvents::FilesystemCacheReserveMicroseconds);
|
||||
|
||||
@ -653,6 +653,7 @@ bool FileCache::tryReserve(FileSegment & file_segment, const size_t size)
|
||||
{
|
||||
chassert(segment_metadata->file_segment->assertCorrectness());
|
||||
|
||||
auto & stat_by_kind = reserve_stat.stat_by_kind[segment_metadata->file_segment->getKind()];
|
||||
if (segment_metadata->releasable())
|
||||
{
|
||||
const auto & key = segment_metadata->file_segment->key();
|
||||
@ -661,9 +662,18 @@ bool FileCache::tryReserve(FileSegment & file_segment, const size_t size)
|
||||
it = to_delete.emplace(key, locked_key.getKeyMetadata()).first;
|
||||
it->second.add(segment_metadata);
|
||||
|
||||
stat_by_kind.releasable_size += segment_metadata->size();
|
||||
++stat_by_kind.releasable_count;
|
||||
|
||||
freeable_space += segment_metadata->size();
|
||||
++freeable_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
stat_by_kind.non_releasable_size += segment_metadata->size();
|
||||
++stat_by_kind.non_releasable_count;
|
||||
}
|
||||
|
||||
return PriorityIterationResult::CONTINUE;
|
||||
};
|
||||
|
||||
@ -718,6 +728,10 @@ bool FileCache::tryReserve(FileSegment & file_segment, const size_t size)
|
||||
return is_overflow;
|
||||
};
|
||||
|
||||
/// If we have enough space in query_priority, we are not interested about stat there anymore.
|
||||
/// Clean the stat before iterating main_priority to avoid calculating any segment stat twice.
|
||||
reserve_stat.stat_by_kind.clear();
|
||||
|
||||
if (is_main_priority_overflow())
|
||||
{
|
||||
main_priority->iterate(
|
||||
|
@ -30,6 +30,22 @@ namespace ErrorCodes
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
/// Track acquired space in cache during reservation
|
||||
/// to make error messages when no space left more informative.
|
||||
struct FileCacheReserveStat
|
||||
{
|
||||
struct Stat
|
||||
{
|
||||
size_t releasable_size;
|
||||
size_t releasable_count;
|
||||
|
||||
size_t non_releasable_size;
|
||||
size_t non_releasable_count;
|
||||
};
|
||||
|
||||
std::unordered_map<FileSegmentKind, Stat> stat_by_kind;
|
||||
};
|
||||
|
||||
/// Local cache for remote filesystem files, represented as a set of non-overlapping non-empty file segments.
|
||||
/// Different caching algorithms are implemented using IFileCachePriority.
|
||||
class FileCache : private boost::noncopyable
|
||||
@ -106,7 +122,7 @@ public:
|
||||
|
||||
size_t getMaxFileSegmentSize() const { return max_file_segment_size; }
|
||||
|
||||
bool tryReserve(FileSegment & file_segment, size_t size);
|
||||
bool tryReserve(FileSegment & file_segment, size_t size, FileCacheReserveStat & stat);
|
||||
|
||||
FileSegmentsHolderPtr getSnapshot();
|
||||
|
||||
|
@ -186,9 +186,7 @@ bool FileSegment::isDownloaded() const
|
||||
|
||||
String FileSegment::getCallerId()
|
||||
{
|
||||
if (!CurrentThread::isInitialized()
|
||||
|| !CurrentThread::get().getQueryContext()
|
||||
|| CurrentThread::getQueryId().empty())
|
||||
if (!CurrentThread::isInitialized() || CurrentThread::getQueryId().empty())
|
||||
return "None:" + toString(getThreadId());
|
||||
|
||||
return std::string(CurrentThread::getQueryId()) + ":" + toString(getThreadId());
|
||||
@ -478,7 +476,7 @@ LockedKeyPtr FileSegment::lockKeyMetadata(bool assert_exists) const
|
||||
return metadata->tryLock();
|
||||
}
|
||||
|
||||
bool FileSegment::reserve(size_t size_to_reserve)
|
||||
bool FileSegment::reserve(size_t size_to_reserve, FileCacheReserveStat * reserve_stat)
|
||||
{
|
||||
if (!size_to_reserve)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Zero space reservation is not allowed");
|
||||
@ -514,9 +512,8 @@ bool FileSegment::reserve(size_t size_to_reserve)
|
||||
|
||||
size_t already_reserved_size = reserved_size - expected_downloaded_size;
|
||||
|
||||
bool reserved = already_reserved_size >= size_to_reserve;
|
||||
if (reserved)
|
||||
return reserved;
|
||||
if (already_reserved_size >= size_to_reserve)
|
||||
return true;
|
||||
|
||||
size_to_reserve = size_to_reserve - already_reserved_size;
|
||||
|
||||
@ -525,7 +522,12 @@ bool FileSegment::reserve(size_t size_to_reserve)
|
||||
if (is_unbound && is_file_segment_size_exceeded)
|
||||
segment_range.right = range().left + expected_downloaded_size + size_to_reserve;
|
||||
|
||||
reserved = cache->tryReserve(*this, size_to_reserve);
|
||||
/// if reserve_stat is not passed then use dummy stat and discard the result.
|
||||
FileCacheReserveStat dummy_stat;
|
||||
if (!reserve_stat)
|
||||
reserve_stat = &dummy_stat;
|
||||
|
||||
bool reserved = cache->tryReserve(*this, size_to_reserve, *reserve_stat);
|
||||
|
||||
if (!reserved)
|
||||
setDownloadFailedUnlocked(lockFileSegment());
|
||||
|
@ -26,6 +26,7 @@ namespace DB
|
||||
{
|
||||
|
||||
class ReadBufferFromFileBase;
|
||||
struct FileCacheReserveStat;
|
||||
|
||||
/*
|
||||
* FileSegmentKind is used to specify the eviction policy for file segments.
|
||||
@ -243,12 +244,7 @@ public:
|
||||
|
||||
/// Try to reserve exactly `size` bytes (in addition to the getDownloadedSize() bytes already downloaded).
|
||||
/// Returns true if reservation was successful, false otherwise.
|
||||
bool reserve(size_t size_to_reserve);
|
||||
|
||||
/// Try to reserve at max `size_to_reserve` bytes.
|
||||
/// Returns actual size reserved. It can be less than size_to_reserve in non strict mode.
|
||||
/// In strict mode throws an error on attempt to reserve space too much space.
|
||||
size_t tryReserve(size_t size_to_reserve, bool strict = false);
|
||||
bool reserve(size_t size_to_reserve, FileCacheReserveStat * reserve_stat = nullptr);
|
||||
|
||||
/// Write data into reserved space.
|
||||
void write(const char * from, size_t size, size_t offset);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <Interpreters/Cache/WriteBufferToFileSegment.h>
|
||||
#include <Interpreters/Cache/FileSegment.h>
|
||||
#include <Interpreters/Cache/FileCache.h>
|
||||
#include <IO/SwapHelper.h>
|
||||
#include <IO/ReadBufferFromFile.h>
|
||||
|
||||
@ -44,11 +45,25 @@ void WriteBufferToFileSegment::nextImpl()
|
||||
|
||||
size_t bytes_to_write = offset();
|
||||
|
||||
FileCacheReserveStat reserve_stat;
|
||||
/// In case of an error, we don't need to finalize the file segment
|
||||
/// because it will be deleted soon and completed in the holder's destructor.
|
||||
bool ok = file_segment->reserve(bytes_to_write);
|
||||
bool ok = file_segment->reserve(bytes_to_write, &reserve_stat);
|
||||
|
||||
if (!ok)
|
||||
throw Exception(ErrorCodes::NOT_ENOUGH_SPACE, "Failed to reserve space for the file cache ({})", file_segment->getInfoForLog());
|
||||
{
|
||||
String reserve_stat_msg;
|
||||
for (const auto & [kind, stat] : reserve_stat.stat_by_kind)
|
||||
reserve_stat_msg += fmt::format("{} hold {}, can release {}; ",
|
||||
toString(kind), ReadableSize(stat.non_releasable_size), ReadableSize(stat.releasable_size));
|
||||
|
||||
throw Exception(ErrorCodes::NOT_ENOUGH_SPACE, "Failed to reserve {} bytes for {}: {}(segment info: {})",
|
||||
bytes_to_write,
|
||||
file_segment->getKind() == FileSegmentKind::Temporary ? "temporary file" : "the file in cache",
|
||||
reserve_stat_msg,
|
||||
file_segment->getInfoForLog()
|
||||
);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -336,7 +336,6 @@ DatabaseAndTable DatabaseCatalog::getTableImpl(
|
||||
return db_and_table;
|
||||
}
|
||||
|
||||
|
||||
if (table_id.database_name == TEMPORARY_DATABASE)
|
||||
{
|
||||
/// For temporary tables UUIDs are set in Context::resolveStorageID(...).
|
||||
@ -369,8 +368,24 @@ DatabaseAndTable DatabaseCatalog::getTableImpl(
|
||||
database = it->second;
|
||||
}
|
||||
|
||||
auto table = database->tryGetTable(table_id.table_name, context_);
|
||||
if (!table && exception)
|
||||
StoragePtr table;
|
||||
if (exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
table = database->getTable(table_id.table_name, context_);
|
||||
}
|
||||
catch (const Exception & e)
|
||||
{
|
||||
exception->emplace(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
table = database->tryGetTable(table_id.table_name, context_);
|
||||
}
|
||||
|
||||
if (!table && exception && !exception->has_value())
|
||||
exception->emplace(Exception(ErrorCodes::UNKNOWN_TABLE, "Table {} doesn't exist", table_id.getNameForLogs()));
|
||||
|
||||
if (!table)
|
||||
|
@ -16,6 +16,7 @@ namespace ErrorCodes
|
||||
{
|
||||
extern const int TABLE_IS_READ_ONLY;
|
||||
extern const int INCORRECT_QUERY;
|
||||
extern const int NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +25,15 @@ BlockIO InterpreterCreateIndexQuery::execute()
|
||||
auto current_context = getContext();
|
||||
const auto & create_index = query_ptr->as<ASTCreateIndexQuery &>();
|
||||
|
||||
if (create_index.unique)
|
||||
{
|
||||
if (!current_context->getSettingsRef().create_index_ignore_unique)
|
||||
{
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "CREATE UNIQUE INDEX is not supported."
|
||||
" SET create_index_ignore_unique=1 to ignore this UNIQUE keyword.");
|
||||
}
|
||||
|
||||
}
|
||||
// Noop if allow_create_index_without_type = true. throw otherwise
|
||||
if (!create_index.index_decl->as<ASTIndexDeclaration>()->type)
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ void ASTCreateIndexQuery::formatQueryImpl(const FormatSettings & settings, Forma
|
||||
|
||||
settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str;
|
||||
|
||||
settings.ostr << "CREATE INDEX " << (if_not_exists ? "IF NOT EXISTS " : "");
|
||||
settings.ostr << "CREATE " << (unique ? "UNIQUE " : "") << "INDEX " << (if_not_exists ? "IF NOT EXISTS " : "");
|
||||
index_name->formatImpl(settings, state, frame);
|
||||
settings.ostr << " ON ";
|
||||
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
ASTPtr index_decl;
|
||||
|
||||
bool if_not_exists{false};
|
||||
bool unique{false};
|
||||
|
||||
String getID(char delim) const override;
|
||||
|
||||
|
@ -80,6 +80,7 @@ bool ParserCreateIndexQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expect
|
||||
node = query;
|
||||
|
||||
ParserKeyword s_create("CREATE");
|
||||
ParserKeyword s_unique("UNIQUE");
|
||||
ParserKeyword s_index("INDEX");
|
||||
ParserKeyword s_if_not_exists("IF NOT EXISTS");
|
||||
ParserKeyword s_on("ON");
|
||||
@ -91,10 +92,14 @@ bool ParserCreateIndexQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expect
|
||||
|
||||
String cluster_str;
|
||||
bool if_not_exists = false;
|
||||
bool unique = false;
|
||||
|
||||
if (!s_create.ignore(pos, expected))
|
||||
return false;
|
||||
|
||||
if (s_unique.ignore(pos, expected))
|
||||
unique = true;
|
||||
|
||||
if (!s_index.ignore(pos, expected))
|
||||
return false;
|
||||
|
||||
@ -131,6 +136,7 @@ bool ParserCreateIndexQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expect
|
||||
query->children.push_back(index_decl);
|
||||
|
||||
query->if_not_exists = if_not_exists;
|
||||
query->unique = unique;
|
||||
query->cluster = cluster_str;
|
||||
|
||||
if (query->database)
|
||||
|
@ -6,7 +6,7 @@ namespace DB
|
||||
{
|
||||
|
||||
/** Query like this:
|
||||
* CREATE INDEX [IF NOT EXISTS] name ON [db].name (expression) TYPE type GRANULARITY value
|
||||
* CREATE [UNIQUE] INDEX [IF NOT EXISTS] name ON [db].name (expression) TYPE type GRANULARITY value
|
||||
*/
|
||||
|
||||
class ParserCreateIndexQuery : public IParserBase
|
||||
|
@ -37,8 +37,10 @@ namespace
|
||||
template <typename T, typename SourceType>
|
||||
struct StatisticsNumeric
|
||||
{
|
||||
T min = std::numeric_limits<T>::max();
|
||||
T max = std::numeric_limits<T>::min();
|
||||
T min = std::numeric_limits<T>::has_infinity
|
||||
? std::numeric_limits<T>::infinity() : std::numeric_limits<T>::max();
|
||||
T max = std::numeric_limits<T>::has_infinity
|
||||
? -std::numeric_limits<T>::infinity() : std::numeric_limits<T>::lowest();
|
||||
|
||||
void add(SourceType x)
|
||||
{
|
||||
|
@ -37,7 +37,10 @@ void TableFunctionRemote::parseArguments(const ASTPtr & ast_function, ContextPtr
|
||||
|
||||
String cluster_name;
|
||||
String cluster_description;
|
||||
String database, table, username = "default", password;
|
||||
String database = "system";
|
||||
String table = "one"; /// The table containing one row is used by default for queries without explicit table specification.
|
||||
String username = "default";
|
||||
String password;
|
||||
|
||||
if (args_func.size() != 1)
|
||||
throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
@ -86,7 +89,7 @@ void TableFunctionRemote::parseArguments(const ASTPtr & ast_function, ContextPtr
|
||||
else
|
||||
{
|
||||
/// Supported signatures:
|
||||
///
|
||||
/// remote('addresses_expr')
|
||||
/// remote('addresses_expr', db.table)
|
||||
/// remote('addresses_expr', 'db', 'table')
|
||||
/// remote('addresses_expr', db.table, 'user')
|
||||
@ -102,6 +105,8 @@ void TableFunctionRemote::parseArguments(const ASTPtr & ast_function, ContextPtr
|
||||
///
|
||||
/// remoteSecure() - same as remote()
|
||||
///
|
||||
/// cluster()
|
||||
/// cluster('cluster_name')
|
||||
/// cluster('cluster_name', db.table)
|
||||
/// cluster('cluster_name', 'db', 'table')
|
||||
/// cluster('cluster_name', db.table, sharding_key)
|
||||
@ -109,7 +114,7 @@ void TableFunctionRemote::parseArguments(const ASTPtr & ast_function, ContextPtr
|
||||
///
|
||||
/// clusterAllReplicas() - same as cluster()
|
||||
|
||||
if (args.size() < 2 || args.size() > max_args)
|
||||
if ((!is_cluster_function && args.empty()) || args.size() > max_args)
|
||||
throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
size_t arg_num = 0;
|
||||
@ -128,8 +133,15 @@ void TableFunctionRemote::parseArguments(const ASTPtr & ast_function, ContextPtr
|
||||
|
||||
if (is_cluster_function)
|
||||
{
|
||||
args[arg_num] = evaluateConstantExpressionOrIdentifierAsLiteral(args[arg_num], context);
|
||||
cluster_name = checkAndGetLiteralArgument<String>(args[arg_num], "cluster_name");
|
||||
if (!args.empty())
|
||||
{
|
||||
args[arg_num] = evaluateConstantExpressionOrIdentifierAsLiteral(args[arg_num], context);
|
||||
cluster_name = checkAndGetLiteralArgument<String>(args[arg_num], "cluster_name");
|
||||
}
|
||||
else
|
||||
{
|
||||
cluster_name = "default";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -141,44 +153,49 @@ void TableFunctionRemote::parseArguments(const ASTPtr & ast_function, ContextPtr
|
||||
}
|
||||
|
||||
++arg_num;
|
||||
const auto * function = args[arg_num]->as<ASTFunction>();
|
||||
if (function && TableFunctionFactory::instance().isTableFunctionName(function->name))
|
||||
{
|
||||
remote_table_function_ptr = args[arg_num];
|
||||
++arg_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
args[arg_num] = evaluateConstantExpressionForDatabaseName(args[arg_num], context);
|
||||
database = checkAndGetLiteralArgument<String>(args[arg_num], "database");
|
||||
|
||||
++arg_num;
|
||||
|
||||
auto qualified_name = QualifiedTableName::parseFromString(database);
|
||||
if (qualified_name.database.empty())
|
||||
/// Names of database and table is not necessary.
|
||||
if (arg_num < args.size())
|
||||
{
|
||||
const auto * function = args[arg_num]->as<ASTFunction>();
|
||||
if (function && TableFunctionFactory::instance().isTableFunctionName(function->name))
|
||||
{
|
||||
if (arg_num >= args.size())
|
||||
remote_table_function_ptr = args[arg_num];
|
||||
++arg_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
args[arg_num] = evaluateConstantExpressionForDatabaseName(args[arg_num], context);
|
||||
database = checkAndGetLiteralArgument<String>(args[arg_num], "database");
|
||||
|
||||
++arg_num;
|
||||
|
||||
auto qualified_name = QualifiedTableName::parseFromString(database);
|
||||
if (qualified_name.database.empty())
|
||||
{
|
||||
throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
if (arg_num >= args.size())
|
||||
{
|
||||
throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::swap(qualified_name.database, qualified_name.table);
|
||||
args[arg_num] = evaluateConstantExpressionOrIdentifierAsLiteral(args[arg_num], context);
|
||||
qualified_name.table = checkAndGetLiteralArgument<String>(args[arg_num], "table");
|
||||
++arg_num;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
database = std::move(qualified_name.database);
|
||||
table = std::move(qualified_name.table);
|
||||
|
||||
/// Cluster function may have sharding key for insert
|
||||
if (is_cluster_function && arg_num < args.size())
|
||||
{
|
||||
std::swap(qualified_name.database, qualified_name.table);
|
||||
args[arg_num] = evaluateConstantExpressionOrIdentifierAsLiteral(args[arg_num], context);
|
||||
qualified_name.table = checkAndGetLiteralArgument<String>(args[arg_num], "table");
|
||||
sharding_key = args[arg_num];
|
||||
++arg_num;
|
||||
}
|
||||
}
|
||||
|
||||
database = std::move(qualified_name.database);
|
||||
table = std::move(qualified_name.table);
|
||||
|
||||
/// Cluster function may have sharding key for insert
|
||||
if (is_cluster_function && arg_num < args.size())
|
||||
{
|
||||
sharding_key = args[arg_num];
|
||||
++arg_num;
|
||||
}
|
||||
}
|
||||
|
||||
/// Username and password parameters are prohibited in cluster version of the function
|
||||
@ -329,11 +346,13 @@ TableFunctionRemote::TableFunctionRemote(const std::string & name_, bool secure_
|
||||
{
|
||||
is_cluster_function = (name == "cluster" || name == "clusterAllReplicas");
|
||||
help_message = PreformattedMessage::create(
|
||||
"Table function '{}' requires from 2 to {} parameters: "
|
||||
"<addresses pattern or cluster name>, <name of remote database>, <name of remote table>{}",
|
||||
"Table function '{}' requires from {} to {} parameters: "
|
||||
"{}",
|
||||
name,
|
||||
is_cluster_function ? 0 : 1,
|
||||
is_cluster_function ? 4 : 6,
|
||||
is_cluster_function ? " [, sharding_key]" : " [, username[, password], sharding_key]");
|
||||
is_cluster_function ? "[<cluster name or default if not specify>, <name of remote database>, <name of remote table>] [, sharding_key]"
|
||||
: "<addresses pattern> [, <name of remote database>, <name of remote table>] [, username[, password], sharding_key]");
|
||||
}
|
||||
|
||||
void registerTableFunctionRemote(TableFunctionFactory & factory)
|
||||
|
@ -2,6 +2,7 @@
|
||||
# pylint: disable=redefined-outer-name
|
||||
|
||||
import pytest
|
||||
import fnmatch
|
||||
|
||||
from helpers.cluster import ClickHouseCluster
|
||||
from helpers.client import QueryRuntimeException
|
||||
@ -68,7 +69,9 @@ def test_cache_evicted_by_temporary_data(start_cluster):
|
||||
"max_bytes_before_external_sort": "4M",
|
||||
},
|
||||
)
|
||||
assert "Failed to reserve space for the file cache" in str(exc.value)
|
||||
assert fnmatch.fnmatch(
|
||||
str(exc.value), "*Failed to reserve * for temporary file*"
|
||||
), exc.value
|
||||
|
||||
# Some data evicted from cache by temporary data
|
||||
cache_size_after_eviction = get_cache_size()
|
||||
@ -104,6 +107,8 @@ def test_cache_evicted_by_temporary_data(start_cluster):
|
||||
"SELECT randomPrintableASCII(1024) FROM numbers(32 * 1024) FORMAT TSV",
|
||||
params={"buffer_size": 0, "wait_end_of_query": 1},
|
||||
)
|
||||
assert "Failed to reserve space for the file cache" in str(exc.value)
|
||||
assert fnmatch.fnmatch(
|
||||
str(exc.value), "*Failed to reserve * for temporary file*"
|
||||
), exc.value
|
||||
|
||||
q("DROP TABLE IF EXISTS t1")
|
||||
|
@ -1,2 +1,4 @@
|
||||
[(1,4),(2,5),(3,6)]
|
||||
[(1,4),(2,5),(3,6)]
|
||||
[(1,4),(2,5),(3,6)]
|
||||
[(1,4),(2,5),(3,6)]
|
||||
|
@ -1,3 +1,4 @@
|
||||
-- Tags: shard
|
||||
|
||||
SELECT arrayMap((x, y) -> (x, y), [1, 2, 3], [4, 5, 6]) FROM remote('127.0.0.{2,3}', system.one) ORDER BY rand();
|
||||
SELECT arrayMap((x, y) -> (x, y), [1, 2, 3], [4, 5, 6]) FROM remote('127.0.0.{2,3}') ORDER BY rand();
|
||||
|
@ -1,3 +1,6 @@
|
||||
1
|
||||
|
||||
1
|
||||
1
|
||||
|
||||
1
|
||||
|
@ -1,3 +1,4 @@
|
||||
-- Tags: shard
|
||||
|
||||
SELECT x FROM (SELECT count() AS x FROM remote('127.0.0.2', system.one) WITH TOTALS) LIMIT 1;
|
||||
SELECT x FROM (SELECT count() AS x FROM remote('127.0.0.2') WITH TOTALS) LIMIT 1;
|
||||
|
@ -1,2 +1,4 @@
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
|
@ -1 +1,2 @@
|
||||
SELECT (SELECT 1) FROM remote('127.0.0.{1,2}', system.one);
|
||||
SELECT (SELECT 1) FROM remote('127.0.0.{1,2}');
|
||||
|
@ -1,7 +1,7 @@
|
||||
[[[(1,2.9),(1,1),(2.9,1),(3,0),(0,0),(0,3),(1,2.9)]],[[(1,2.9),(1,4),(4,4),(4,1),(2.9,1),(2.6,2),(2,2.6),(1,2.9)]]]
|
||||
-------- MultiPolygon with Polygon
|
||||
MULTIPOLYGON(((-20 -10.3067,-20 -20,-10 -20.8791,-10 -40,-40 -40,-40 -10,-20 -10.3067)),((20 10.3067,20 -20,-10 -20.8791,-10 -10,-20 -10.3067,-20 20,10 20.8791,10 10,20 10.3067)),((20 10.3067,20 20,10 20.8791,10 40,40 40,40 10,20 10.3067)))
|
||||
[(-40,-40),(-40,-10),(-20,-20),(-20,-10.307),(-20,20),(-10,-40),(-10,-20.879),(-10,-10),(10,10),(10,20.879),(10,40),(20,-20),(20,10.307),(20,20),(40,10),(40,40)]
|
||||
-------- MultiPolygon with Polygon with Holes
|
||||
MULTIPOLYGON(((-10 -20.8791,-20 -20,-20 -10.3067,-10 -10,-10 -20.8791)),((10 20.8791,20 20,20 10.3067,10 10,10 20.8791)),((50 50,50 -50,-50 -50,-50 50,50 50),(20 10.3067,40 10,40 40,10 40,10 20.8791,-20 20,-20 -10.3067,-40 -10,-40 -40,-10 -40,-10 -20.8791,20 -20,20 10.3067)))
|
||||
[(-50,-50),(-50,50),(-40,-40),(-40,-10),(-20,-20),(-20,-10.307),(-20,20),(-10,-40),(-10,-20.879),(-10,-10),(10,10),(10,20.879),(10,40),(20,-20),(20,10.307),(20,20),(40,10),(40,40),(50,-50),(50,50)]
|
||||
-------- Polygon with Polygon with Holes
|
||||
MULTIPOLYGON(((-20 -10.3067,-10 -10,-10 -20.8791,-20 -20,-20 -10.3067)),((10 20.8791,20 20,20 10.3067,10 10,10 20.8791)),((50 50,50 -50,-50 -50,-50 50,50 50),(20 10.3067,40 10,40 40,10 40,10 20.8791,-20 20,-20 -10.3067,-40 -10,-40 -40,-10 -40,-10 -20.8791,20 -20,20 10.3067)))
|
||||
[(-50,-50),(-50,50),(-40,-40),(-40,-10),(-20,-20),(-20,-10.307),(-20,20),(-10,-40),(-10,-20.879),(-10,-10),(10,10),(10,20.879),(10,40),(20,-20),(20,10.307),(20,20),(40,10),(40,40),(50,-50),(50,50)]
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,9 +1,18 @@
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
1
|
||||
2
|
||||
1
|
||||
2
|
||||
1
|
||||
2
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
1
|
||||
2
|
||||
|
@ -1,10 +1,16 @@
|
||||
-- Tags: replica, shard
|
||||
|
||||
SELECT _shard_num FROM cluster('test_shard_localhost', system.one);
|
||||
SELECT _shard_num FROM cluster('test_shard_localhost');
|
||||
SELECT _shard_num FROM clusterAllReplicas('test_shard_localhost', system.one);
|
||||
SELECT _shard_num FROM clusterAllReplicas('test_shard_localhost');
|
||||
|
||||
SELECT _shard_num FROM cluster('test_cluster_two_shards', system.one) ORDER BY _shard_num;
|
||||
SELECT _shard_num FROM cluster('test_cluster_two_shards') ORDER BY _shard_num;
|
||||
SELECT _shard_num FROM clusterAllReplicas('test_cluster_two_shards', system.one) ORDER BY _shard_num;
|
||||
SELECT _shard_num FROM clusterAllReplicas('test_cluster_two_shards') ORDER BY _shard_num;
|
||||
|
||||
SELECT _shard_num FROM cluster('test_cluster_one_shard_two_replicas', system.one) ORDER BY _shard_num;
|
||||
SELECT _shard_num FROM cluster('test_cluster_one_shard_two_replicas') ORDER BY _shard_num;
|
||||
SELECT _shard_num FROM clusterAllReplicas('test_cluster_one_shard_two_replicas', system.one) ORDER BY _shard_num;
|
||||
SELECT _shard_num FROM clusterAllReplicas('test_cluster_one_shard_two_replicas') ORDER BY _shard_num;
|
||||
|
@ -1,2 +1,4 @@
|
||||
{'a':1,'b':2}
|
||||
{'a':1,'b':2}
|
||||
{'a':1,'b':2}
|
||||
{'a':1,'b':2}
|
||||
|
@ -1 +1,2 @@
|
||||
SELECT map('a', 1, 'b', 2) FROM remote('127.0.0.{1,2}', system, one);
|
||||
SELECT map('a', 1, 'b', 2) FROM remote('127.0.0.{1,2}');
|
||||
|
@ -10,3 +10,14 @@ SELECT * FROM remote('::1', system.one) FORMAT Null; -- { serverError 36 }
|
||||
SELECT * FROM remote('[::1][::1]', system.one) FORMAT Null; -- { serverError 36 }
|
||||
SELECT * FROM remote('[::1][::1', system.one) FORMAT Null; -- { serverError 36 }
|
||||
SELECT * FROM remote('[::1]::1]', system.one) FORMAT Null; -- { serverError 36 }
|
||||
|
||||
SELECT * FROM remote('[::1]') FORMAT Null;
|
||||
SELECT * FROM remote('[::1]:9000') FORMAT Null;
|
||||
|
||||
SELECT * FROM remote('[::1') FORMAT Null; -- { serverError 36 }
|
||||
SELECT * FROM remote('::1]') FORMAT Null; -- { serverError 36 }
|
||||
SELECT * FROM remote('::1') FORMAT Null; -- { serverError 36 }
|
||||
|
||||
SELECT * FROM remote('[::1][::1]') FORMAT Null; -- { serverError 36 }
|
||||
SELECT * FROM remote('[::1][::1') FORMAT Null; -- { serverError 36 }
|
||||
SELECT * FROM remote('[::1]::1]') FORMAT Null; -- { serverError 36 }
|
||||
|
@ -1,2 +1,4 @@
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
|
@ -1,2 +1,4 @@
|
||||
SELECT _shard_num FROM cluster("{default_cluster_macro}", system.one);
|
||||
SELECT _shard_num FROM cluster("{default_cluster_macro}");
|
||||
SELECT _shard_num FROM clusterAllReplicas("{default_cluster_macro}", system.one);
|
||||
SELECT _shard_num FROM clusterAllReplicas("{default_cluster_macro}");
|
||||
|
@ -1,2 +1,4 @@
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
|
@ -4,3 +4,7 @@ SET optimize_monotonous_functions_in_order_by = 1;
|
||||
SELECT *
|
||||
FROM cluster(test_cluster_two_shards_localhost, system, one)
|
||||
ORDER BY toDateTime(dummy);
|
||||
|
||||
SELECT *
|
||||
FROM cluster(test_cluster_two_shards_localhost)
|
||||
ORDER BY toDateTime(dummy)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tags: no-random-settings
|
||||
# Tags: no-random-settings, no-asan, no-msan, no-tsan, no-debug
|
||||
# shellcheck disable=SC2009
|
||||
|
||||
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
|
@ -4,16 +4,32 @@ SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM system.one;
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}', system.one);
|
||||
1
|
||||
1
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}');
|
||||
1
|
||||
1
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}', system.one) GROUP BY NULL;
|
||||
1
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}') GROUP BY NULL;
|
||||
1
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}', system.one) GROUP BY 1;
|
||||
1
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}') GROUP BY 1;
|
||||
1
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}', system.one) GROUP BY 'A';
|
||||
1
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}') GROUP BY 'A';
|
||||
1
|
||||
SELECT 1 IN ( SELECT 1 ) FROM remote('127.0.0.{1,2}', system.one) GROUP BY dummy;
|
||||
1
|
||||
SELECT 1 IN ( SELECT 1 ) FROM remote('127.0.0.{1,2}') GROUP BY dummy;
|
||||
1
|
||||
SELECT 1000.0001, toUInt64(arrayJoin([NULL, 257, 65536, NULL])), arrayExists(x -> (x IN (SELECT '2.55')), [-9223372036854775808]) FROM remote('127.0.0.{1,2}', system.one) GROUP BY NULL, NULL, NULL, NULL;
|
||||
1000.0001 \N 0
|
||||
1000.0001 257 0
|
||||
1000.0001 65536 0
|
||||
1000.0001 \N 0
|
||||
SELECT 1000.0001, toUInt64(arrayJoin([NULL, 257, 65536, NULL])), arrayExists(x -> (x IN (SELECT '2.55')), [-9223372036854775808]) FROM remote('127.0.0.{1,2}') GROUP BY NULL, NULL, NULL, NULL;
|
||||
1000.0001 \N 0
|
||||
1000.0001 257 0
|
||||
1000.0001 65536 0
|
||||
1000.0001 \N 0
|
||||
|
@ -2,13 +2,19 @@
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM system.one;
|
||||
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}', system.one);
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}');
|
||||
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}', system.one) GROUP BY NULL;
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}') GROUP BY NULL;
|
||||
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}', system.one) GROUP BY 1;
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}') GROUP BY 1;
|
||||
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}', system.one) GROUP BY 'A';
|
||||
SELECT arrayExists(x -> (x IN (SELECT '2')), [2]) FROM remote('127.0.0.{2,3}') GROUP BY 'A';
|
||||
|
||||
SELECT 1 IN ( SELECT 1 ) FROM remote('127.0.0.{1,2}', system.one) GROUP BY dummy;
|
||||
SELECT 1 IN ( SELECT 1 ) FROM remote('127.0.0.{1,2}') GROUP BY dummy;
|
||||
|
||||
SELECT 1000.0001, toUInt64(arrayJoin([NULL, 257, 65536, NULL])), arrayExists(x -> (x IN (SELECT '2.55')), [-9223372036854775808]) FROM remote('127.0.0.{1,2}', system.one) GROUP BY NULL, NULL, NULL, NULL;
|
||||
SELECT 1000.0001, toUInt64(arrayJoin([NULL, 257, 65536, NULL])), arrayExists(x -> (x IN (SELECT '2.55')), [-9223372036854775808]) FROM remote('127.0.0.{1,2}') GROUP BY NULL, NULL, NULL, NULL;
|
||||
|
@ -40,32 +40,31 @@ ${CLICKHOUSE_LOCAL} -q "SELECT COUNT(*) FROM \"${tmp_dir}/tmp.csv\""
|
||||
#################
|
||||
echo "Test 2: check DatabaseFilesystem access rights and errors handling on server"
|
||||
# DATABASE_ACCESS_DENIED: Allows list files only inside user_files
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT COUNT(*) FROM test1.\`../tmp.csv\`;" 2>&1| grep -F "Code: 481" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT COUNT(*) FROM test1.\`/tmp/tmp.csv\`;" 2>&1| grep -F "Code: 481" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT COUNT(*) FROM test1.\`../tmp.csv\`;" 2>&1 | tr '\n' ' ' | grep -oF "PATH_ACCESS_DENIED" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT COUNT(*) FROM test1.\`/tmp/tmp.csv\`;" 2>&1 | tr '\n' ' ' | grep -oF "PATH_ACCESS_DENIED" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
${CLICKHOUSE_CLIENT} --multiline --multiquery --query """
|
||||
USE test1;
|
||||
SELECT COUNT(*) FROM \"../${tmp_dir}/tmp.csv\";
|
||||
""" 2>&1| grep -F "Code: 481" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT COUNT(*) FROM test1.\`../../../../../../tmp.csv\`;" 2>&1| grep -F "Code: 481" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
""" 2>&1 | tr '\n' ' ' | grep -oF "PATH_ACCESS_DENIED" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT COUNT(*) FROM test1.\`../../../../../../tmp.csv\`;" 2>&1 | tr '\n' ' ' | grep -oF "PATH_ACCESS_DENIED" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
|
||||
# BAD_ARGUMENTS: path should be inside user_files
|
||||
${CLICKHOUSE_CLIENT} --multiline --multiquery -q """
|
||||
DROP DATABASE IF EXISTS test2;
|
||||
CREATE DATABASE test2 ENGINE = Filesystem('/tmp');
|
||||
""" 2>&1| grep -F "Code: 36" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
""" 2>&1 | tr '\n' ' ' | grep -oF -e "UNKNOWN_TABLE" -e "BAD_ARGUMENTS" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
|
||||
# BAD_ARGUMENTS: .../user_files/relative_unknown_dir does not exists
|
||||
${CLICKHOUSE_CLIENT} --multiline --multiquery -q """
|
||||
DROP DATABASE IF EXISTS test2;
|
||||
CREATE DATABASE test2 ENGINE = Filesystem('relative_unknown_dir');
|
||||
""" 2>&1| grep -F "Code: 36" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
""" 2>&1 | tr '\n' ' ' | grep -oF -e "UNKNOWN_TABLE" -e "BAD_ARGUMENTS" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
|
||||
# FILE_DOESNT_EXIST: unknown file
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT COUNT(*) FROM test1.\`tmp2.csv\`;" 2>&1| grep -F "Code: 60" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT COUNT(*) FROM test1.\`tmp2.csv\`;" 2>&1 | tr '\n' ' ' | grep -oF -e "UNKNOWN_TABLE" -e "FILE_DOESNT_EXIST" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
|
||||
# BAD_ARGUMENTS: Cannot determine the file format by it's extension
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT COUNT(*) FROM test1.\`${unique_name}/tmp.myext\`;" 2>&1| grep -F "Code: 36" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT COUNT(*) FROM test1.\`${unique_name}/tmp.myext\`;" 2>&1 | tr '\n' ' ' | grep -oF -e "UNKNOWN_TABLE" -e "BAD_ARGUMENTS" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
# Clean
|
||||
${CLICKHOUSE_CLIENT} --query "DROP DATABASE test1;"
|
||||
rm -rd $tmp_dir
|
||||
|
@ -46,12 +46,12 @@ DROP DATABASE IF EXISTS test3;
|
||||
CREATE DATABASE test3 ENGINE = S3;
|
||||
USE test3;
|
||||
SELECT * FROM \"http://localhost:11111/test/a.myext\"
|
||||
""" 2>&1| grep -F "UNKNOWN_TABLE" > /dev/null && echo "OK"
|
||||
""" 2>&1 | tr '\n' ' ' | grep -oF -e "UNKNOWN_TABLE" -e "BAD_ARGUMENTS" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
|
||||
${CLICKHOUSE_CLIENT} --multiline --multiquery -q """
|
||||
USE test3;
|
||||
SELECT * FROM \"abacaba\"
|
||||
""" 2>&1| grep -F "UNKNOWN_TABLE" > /dev/null && echo "OK"
|
||||
""" 2>&1 | tr '\n' ' ' | grep -oF -e "UNKNOWN_TABLE" -e "BAD_ARGUMENTS" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
|
||||
# Cleanup
|
||||
${CLICKHOUSE_CLIENT} --multiline --multiquery -q """
|
||||
|
@ -4,9 +4,8 @@ test1
|
||||
1 2 3
|
||||
test2
|
||||
Test 2: check exceptions
|
||||
OK0
|
||||
OK1
|
||||
OK2
|
||||
OK3
|
||||
OK4
|
||||
OK5
|
||||
BAD_ARGUMENTS
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
|
@ -1,6 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tags: no-fasttest, use-hdfs, no-parallel
|
||||
|
||||
CLICKHOUSE_CLIENT_SERVER_LOGS_LEVEL=none
|
||||
|
||||
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
# shellcheck source=../shell_config.sh
|
||||
. "$CURDIR"/../shell_config.sh
|
||||
@ -36,19 +38,20 @@ echo "Test 2: check exceptions"
|
||||
${CLICKHOUSE_CLIENT} --multiline --multiquery -q """
|
||||
DROP DATABASE IF EXISTS test3;
|
||||
CREATE DATABASE test3 ENGINE = HDFS('abacaba');
|
||||
""" 2>&1| grep -F "BAD_ARGUMENTS" > /dev/null && echo "OK0"
|
||||
""" 2>&1 | tr '\n' ' ' | grep -oF "BAD_ARGUMENTS"
|
||||
|
||||
${CLICKHOUSE_CLIENT} --multiline --multiquery -q """
|
||||
DROP DATABASE IF EXISTS test4;
|
||||
CREATE DATABASE test4 ENGINE = HDFS;
|
||||
USE test4;
|
||||
SELECT * FROM \"abacaba/file.tsv\"
|
||||
""" 2>&1| grep -F "UNKNOWN_TABLE" > /dev/null && echo "OK1"
|
||||
""" 2>&1 | tr '\n' ' ' | grep -oF "CANNOT_EXTRACT_TABLE_STRUCTURE"
|
||||
|
||||
${CLICKHOUSE_CLIENT} -q "SELECT * FROM test4.\`http://localhost:11111/test/a.tsv\`" 2>&1| grep -F "UNKNOWN_TABLE" > /dev/null && echo "OK2"
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT * FROM test4.\`hdfs://localhost:12222/file.myext\`" 2>&1| grep -F "UNKNOWN_TABLE" > /dev/null && echo "OK3"
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT * FROM test4.\`hdfs://localhost:12222/test_02725_3.tsv\`" 2>&1| grep -F "UNKNOWN_TABLE" > /dev/null && echo "OK4"
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT * FROM test4.\`hdfs://localhost:12222\`" 2>&1| grep -F "UNKNOWN_TABLE" > /dev/null && echo "OK5"
|
||||
${CLICKHOUSE_CLIENT} -q "SELECT * FROM test4.\`http://localhost:11111/test/a.tsv\`" 2>&1 | tr '\n' ' ' | grep -oF -e "UNKNOWN_TABLE" -e "BAD_ARGUMENTS" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT * FROM test4.\`hdfs://localhost:12222/file.myext\`" 2>&1 | tr '\n' ' ' | grep -oF -e "UNKNOWN_TABLE" -e "BAD_ARGUMENTS" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT * FROM test4.\`hdfs://localhost:12222/test_02725_3.tsv\`" 2>&1 | tr '\n' ' ' | grep -oF -e "UNKNOWN_TABLE" -e "CANNOT_EXTRACT_TABLE_STRUCTURE" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
|
||||
${CLICKHOUSE_CLIENT} --query "SELECT * FROM test4.\`hdfs://localhost:12222\`" 2>&1 | tr '\n' ' ' | grep -oF -e "UNKNOWN_TABLE" -e "BAD_ARGUMENTS" > /dev/null && echo "OK" || echo 'FAIL' ||:
|
||||
|
||||
|
||||
# Cleanup
|
||||
|
@ -43,6 +43,7 @@ ipv6 Nullable(FixedString(16))
|
||||
[(2,0,NULL,'','[]')]
|
||||
1 1
|
||||
0 1
|
||||
5090915589685802007
|
||||
16159458007063698496
|
||||
16159458007063698496
|
||||
BYTE_ARRAY String
|
||||
|
@ -147,6 +147,8 @@ insert into function file(compressed_02735.parquet) select concat('aaaaaaaaaaaaa
|
||||
select total_compressed_size < 10000, total_uncompressed_size > 15000 from file(compressed_02735.parquet, ParquetMetadata);
|
||||
insert into function file(compressed_02735.parquet) select concat('aaaaaaaaaaaaaaaa', toString(number)) as s from numbers(1000) settings output_format_parquet_row_group_size = 10000, output_format_parquet_compression_method='none';
|
||||
select total_compressed_size < 10000, total_uncompressed_size > 15000 from file(compressed_02735.parquet, ParquetMetadata);
|
||||
insert into function file(compressed_02735.parquet) select if(number%3==1, NULL, 42) as x from numbers(70) settings output_format_parquet_compression_method='zstd';
|
||||
select sum(cityHash64(*)) from file(compressed_02735.parquet);
|
||||
|
||||
-- Single-threaded encoding and Arrow encoder.
|
||||
drop table if exists other_encoders_02735;
|
||||
|
@ -21,18 +21,18 @@ INSERT INTO aboba (user_id, message, creation_date, metric) VALUES (101, 'Hello,
|
||||
SET dialect = 'prql';
|
||||
|
||||
from aboba
|
||||
derive [
|
||||
derive {
|
||||
a = 2,
|
||||
b = s\"LEFT(message, 2)\"
|
||||
]
|
||||
select [ user_id, message, a, b ];
|
||||
}
|
||||
select { user_id, message, a, b };
|
||||
|
||||
from aboba
|
||||
filter user_id > 101
|
||||
group user_id (
|
||||
aggregate [
|
||||
aggregate {
|
||||
metrics = sum metric
|
||||
]
|
||||
}
|
||||
);
|
||||
|
||||
SET dialect = 'clickhouse';
|
||||
@ -49,10 +49,10 @@ SELECT '---';
|
||||
SET dialect = 'prql';
|
||||
|
||||
from aboba
|
||||
select [ user_id, message, metric ]
|
||||
select { user_id, message, metric }
|
||||
derive creation_date = s\"toTimeZone(creation_date, 'Europe/Amsterdam')\"
|
||||
select [ user_id, message, creation_date, metric];
|
||||
select { user_id, message, creation_date, metric};
|
||||
|
||||
from s\"SELECT * FROM system.users\" | select non_existent_column; # {serverError UNKNOWN_IDENTIFIER}
|
||||
from non_existent_table; # {serverError UNKNOWN_TABLE}
|
||||
"
|
||||
"
|
||||
|
@ -0,0 +1,3 @@
|
||||
SET allow_create_index_without_type=1;
|
||||
SET create_index_ignore_unique=1;
|
||||
CREATE UNIQUE INDEX idx_tab2_0 ON tab2 (col1);
|
@ -0,0 +1,5 @@
|
||||
Aborted
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
56
tests/queries/0_stateless/02815_no_throw_in_simple_queries.sh
Executable file
56
tests/queries/0_stateless/02815_no_throw_in_simple_queries.sh
Executable file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
# shellcheck source=../shell_config.sh
|
||||
. "$CURDIR"/../shell_config.sh
|
||||
|
||||
export CLICKHOUSE_TERMINATE_ON_ANY_EXCEPTION=1
|
||||
|
||||
# The environment variable works as expected:
|
||||
bash -c "
|
||||
abort_handler()
|
||||
{
|
||||
exit 0
|
||||
}
|
||||
trap 'abort_handler' ABRT
|
||||
$CLICKHOUSE_LOCAL --query 'this is wrong'
|
||||
" 2>&1 | grep -o 'Aborted'
|
||||
|
||||
# No exceptions are thrown in simple cases:
|
||||
$CLICKHOUSE_LOCAL --query "SELECT 1"
|
||||
$CLICKHOUSE_LOCAL --query "SHOW TABLES"
|
||||
$CLICKHOUSE_LOCAL --query "SELECT * FROM system.tables WHERE database = currentDatabase() FORMAT Null"
|
||||
|
||||
# The same for the client app:
|
||||
$CLICKHOUSE_CLIENT --query "SELECT 1"
|
||||
$CLICKHOUSE_CLIENT --query "SHOW TABLES"
|
||||
$CLICKHOUSE_CLIENT --query "SELECT * FROM system.tables WHERE database = currentDatabase() FORMAT Null"
|
||||
|
||||
# Multi queries are ok:
|
||||
$CLICKHOUSE_LOCAL --multiquery "SELECT 1; SELECT 2;"
|
||||
|
||||
# It can run in interactive mode:
|
||||
function run()
|
||||
{
|
||||
command=$1
|
||||
expect << EOF
|
||||
|
||||
log_user 0
|
||||
set timeout 60
|
||||
match_max 100000
|
||||
|
||||
spawn bash -c "$command"
|
||||
|
||||
expect ":) "
|
||||
|
||||
send -- "SELECT 1\r"
|
||||
expect "1"
|
||||
expect ":) "
|
||||
|
||||
send -- "exit\r"
|
||||
expect eof
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
run "$CLICKHOUSE_LOCAL"
|
@ -0,0 +1,3 @@
|
||||
\N
|
||||
|
||||
\N
|
@ -0,0 +1,5 @@
|
||||
DROP TABLE IF EXISTS numbers500k;
|
||||
CREATE TABLE numbers500k (`number` UInt32) ENGINE = MergeTree() ORDER BY tuple();
|
||||
INSERT INTO numbers500k SELECT number FROM system.numbers LIMIT 500000;
|
||||
SELECT intDiv(number, NULL) AS k FROM (SELECT * FROM remote('127.0.0.{2,3}', currentDatabase(), numbers500k) PREWHERE 31 WHERE 65537 > 0 ORDER BY number DESC NULLS FIRST) GROUP BY GROUPING SETS ((k)) WITH TOTALS ORDER BY k ASC NULLS LAST LIMIT 2147483648;
|
||||
DROP TABLE IF EXISTS numbers500k;
|
@ -62,7 +62,8 @@ def default_clickhouse_odbc_conn_str():
|
||||
return str(
|
||||
OdbcConnectingArgs.create_from_kw(
|
||||
dsn="ClickHouse DSN (ANSI)",
|
||||
Url="http://localhost:8123/query?default_format=ODBCDriver2&default_table_engine=MergeTree&union_default_mode=DISTINCT&group_by_use_nulls=1&join_use_nulls=1&allow_create_index_without_type=1",
|
||||
Timeout="300",
|
||||
Url="http://localhost:8123/query?default_format=ODBCDriver2&default_table_engine=MergeTree&union_default_mode=DISTINCT&group_by_use_nulls=1&join_use_nulls=1&allow_create_index_without_type=1&create_index_ignore_unique=1",
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -186,10 +186,10 @@ def mode_check_statements(parser):
|
||||
|
||||
out_stages_dir = os.path.join(out_dir, f"{args.mode}-stages")
|
||||
|
||||
complete_sqlite_dir = os.path.join(out_stages_dir, "complete-sqlite")
|
||||
complete_sqlite_dir = os.path.join(out_stages_dir, "statements-sqlite")
|
||||
os.makedirs(complete_sqlite_dir, exist_ok=True)
|
||||
|
||||
reports["complete-sqlite"] = run_all_tests_in_parallel(
|
||||
reports["statements-sqlite"] = run_all_tests_in_parallel(
|
||||
setup_kwargs=as_kwargs(
|
||||
engine=Engines.SQLITE,
|
||||
),
|
||||
@ -224,6 +224,64 @@ def mode_check_statements(parser):
|
||||
parser.set_defaults(func=calle)
|
||||
|
||||
|
||||
def mode_check_complete(parser):
|
||||
parser.add_argument("--input-dir", metavar="DIR", required=True)
|
||||
parser.add_argument("--out-dir", metavar="DIR", required=True)
|
||||
|
||||
def calle(args):
|
||||
input_dir = os.path.realpath(args.input_dir)
|
||||
out_dir = os.path.realpath(args.out_dir)
|
||||
|
||||
if not os.path.exists(input_dir):
|
||||
raise FileNotFoundError(
|
||||
input_dir, f"check statements: no such file or directory {input_dir}"
|
||||
)
|
||||
|
||||
if not os.path.isdir(input_dir):
|
||||
raise NotADirectoryError(
|
||||
input_dir, f"check statements:: not a dir {input_dir}"
|
||||
)
|
||||
|
||||
reports = dict()
|
||||
|
||||
out_stages_dir = os.path.join(out_dir, f"{args.mode}-stages")
|
||||
|
||||
complete_sqlite_dir = os.path.join(out_stages_dir, "complete-sqlite")
|
||||
os.makedirs(complete_sqlite_dir, exist_ok=True)
|
||||
|
||||
reports["complete-sqlite"] = run_all_tests_in_parallel(
|
||||
setup_kwargs=as_kwargs(
|
||||
engine=Engines.SQLITE,
|
||||
),
|
||||
runner_kwargs=as_kwargs(
|
||||
verify_mode=False,
|
||||
stop_at_statement_error=True,
|
||||
),
|
||||
input_dir=input_dir,
|
||||
output_dir=complete_sqlite_dir,
|
||||
)
|
||||
|
||||
verify_clickhouse_dir = os.path.join(out_stages_dir, "complete-clickhouse")
|
||||
os.makedirs(verify_clickhouse_dir, exist_ok=True)
|
||||
|
||||
reports["complete-clickhouse"] = run_all_tests_in_parallel(
|
||||
setup_kwargs=as_kwargs(
|
||||
engine=Engines.ODBC,
|
||||
conn_str=default_clickhouse_odbc_conn_str(),
|
||||
),
|
||||
runner_kwargs=as_kwargs(
|
||||
verify_mode=True,
|
||||
stop_at_statement_error=True,
|
||||
),
|
||||
input_dir=complete_sqlite_dir,
|
||||
output_dir=verify_clickhouse_dir,
|
||||
)
|
||||
|
||||
statements_report(reports, out_dir, args.mode)
|
||||
|
||||
parser.set_defaults(func=calle)
|
||||
|
||||
|
||||
def make_actual_report(reports):
|
||||
return {stage: report.get_map() for stage, report in reports.items()}
|
||||
|
||||
@ -399,16 +457,22 @@ def parse_args():
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(dest="mode")
|
||||
mode_check_complete(
|
||||
subparsers.add_parser(
|
||||
"complete-test",
|
||||
help="Run all tests. Check that all statements and queries are passed",
|
||||
)
|
||||
)
|
||||
mode_check_statements(
|
||||
subparsers.add_parser(
|
||||
"statements-test",
|
||||
help="Run all test. Check that all statements are passed",
|
||||
help="Run all tests. Check that all statements are passed",
|
||||
)
|
||||
)
|
||||
mode_self_test(
|
||||
subparsers.add_parser(
|
||||
"self-test",
|
||||
help="Run all test. Check that all statements are passed",
|
||||
help="Run all tests. Check that all statements are passed",
|
||||
)
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
File diff suppressed because one or more lines are too long
@ -142,4 +142,13 @@ SELECT number+1 from system.numbers LIMIT 20
|
||||
----
|
||||
20 values hashing to 52c46dff81346ead02fcf6245c762b1a
|
||||
|
||||
# Debug how incorrect result type parses
|
||||
statement ok
|
||||
CREATE TABLE tab0(pk INTEGER PRIMARY KEY, col0 INTEGER, col1 FLOAT, col2 TEXT, col3 INTEGER, col4 FLOAT, col5 TEXT)
|
||||
|
||||
statement ok
|
||||
INSERT INTO tab0 VALUES(0,535,860.48,'uxbns',253,640.58,'jvqkl')
|
||||
|
||||
skipif ClickHouse
|
||||
query I rowsort label-20
|
||||
SELECT + col2 AS col5 FROM tab0 WHERE NOT ( col0 ) * - - col4 IS NULL
|
||||
|
@ -9,7 +9,13 @@ from enum import Enum
|
||||
from hashlib import md5
|
||||
from functools import reduce
|
||||
|
||||
from exceptions import Error, ProgramError, ErrorWithParent, DataResultDiffer
|
||||
from exceptions import (
|
||||
Error,
|
||||
ProgramError,
|
||||
ErrorWithParent,
|
||||
DataResultDiffer,
|
||||
QueryExecutionError,
|
||||
)
|
||||
|
||||
|
||||
logger = logging.getLogger("parser")
|
||||
@ -480,6 +486,7 @@ class QueryResult:
|
||||
for row in rows:
|
||||
res_row = []
|
||||
for c, t in zip(row, types):
|
||||
logger.debug(f"Builging row. c:{c} t:{t}")
|
||||
if c is None:
|
||||
res_row.append("NULL")
|
||||
continue
|
||||
@ -490,7 +497,12 @@ class QueryResult:
|
||||
else:
|
||||
res_row.append(str(c))
|
||||
elif t == "I":
|
||||
res_row.append(str(int(c)))
|
||||
try:
|
||||
res_row.append(str(int(c)))
|
||||
except ValueError as ex:
|
||||
raise QueryExecutionError(
|
||||
f"Got non-integer result '{c}' for I type."
|
||||
)
|
||||
elif t == "R":
|
||||
res_row.append(f"{c:.3f}")
|
||||
|
||||
|
@ -361,7 +361,7 @@ class TestRunner:
|
||||
continue
|
||||
|
||||
if block.get_block_type() == test_parser.BlockType.control:
|
||||
clogger.debug("Skip control block", name_pos)
|
||||
clogger.debug("Skip control block %s", name_pos)
|
||||
block.dump_to(out_stream)
|
||||
continue
|
||||
|
||||
@ -374,13 +374,14 @@ class TestRunner:
|
||||
continue
|
||||
|
||||
request = block.get_request()
|
||||
exec_res = execute_request(request, self.connection)
|
||||
|
||||
if block.get_block_type() in self.skip_request_types:
|
||||
clogger.debug("Runtime skip block for %s", self.dbms_name)
|
||||
block.dump_to(out_stream)
|
||||
continue
|
||||
|
||||
exec_res = execute_request(request, self.connection)
|
||||
|
||||
if block.get_block_type() == test_parser.BlockType.statement:
|
||||
try:
|
||||
clogger.debug("this is statement")
|
||||
|
Loading…
Reference in New Issue
Block a user