mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 08:40:50 +00:00
Merge branch 'master' of github.com:ClickHouse/ClickHouse into benchmark-connect-in-parallel
This commit is contained in:
commit
435cbb44a5
@ -3,6 +3,7 @@
|
||||
#include <magic_enum.hpp>
|
||||
#include <fmt/format.h>
|
||||
|
||||
|
||||
template <class T> concept is_enum = std::is_enum_v<T>;
|
||||
|
||||
namespace detail
|
||||
|
@ -97,7 +97,7 @@ namespace Data
|
||||
///
|
||||
/// static void extract(std::size_t pos, Person& obj, const Person& defVal, AbstractExtractor::Ptr pExt)
|
||||
/// {
|
||||
/// // defVal is the default person we should use if we encunter NULL entries, so we take the individual fields
|
||||
/// // defVal is the default person we should use if we encounter NULL entries, so we take the individual fields
|
||||
/// // as defaults. You can do more complex checking, ie return defVal if only one single entry of the fields is null etc...
|
||||
/// poco_assert_dbg (!pExt.isNull());
|
||||
/// std::string lastName;
|
||||
|
@ -146,7 +146,7 @@ namespace Net
|
||||
|
||||
std::string cipherList;
|
||||
/// Specifies the supported ciphers in OpenSSL notation.
|
||||
/// Defaults to "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH".
|
||||
/// Defaults to "ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH".
|
||||
|
||||
std::string dhParamsFile;
|
||||
/// Specifies a file containing Diffie-Hellman parameters.
|
||||
@ -172,7 +172,7 @@ namespace Net
|
||||
VerificationMode verificationMode = VERIFY_RELAXED,
|
||||
int verificationDepth = 9,
|
||||
bool loadDefaultCAs = false,
|
||||
const std::string & cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
|
||||
const std::string & cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH");
|
||||
/// Creates a Context.
|
||||
///
|
||||
/// * usage specifies whether the context is used by a client or server.
|
||||
@ -200,7 +200,7 @@ namespace Net
|
||||
VerificationMode verificationMode = VERIFY_RELAXED,
|
||||
int verificationDepth = 9,
|
||||
bool loadDefaultCAs = false,
|
||||
const std::string & cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
|
||||
const std::string & cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH");
|
||||
/// Creates a Context.
|
||||
///
|
||||
/// * usage specifies whether the context is used by a client or server.
|
||||
|
@ -76,7 +76,7 @@ namespace Net
|
||||
/// <verificationMode>none|relaxed|strict|once</verificationMode>
|
||||
/// <verificationDepth>1..9</verificationDepth>
|
||||
/// <loadDefaultCAFile>true|false</loadDefaultCAFile>
|
||||
/// <cipherList>ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH</cipherList>
|
||||
/// <cipherList>ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH</cipherList>
|
||||
/// <preferServerCiphers>true|false</preferServerCiphers>
|
||||
/// <privateKeyPassphraseHandler>
|
||||
/// <name>KeyFileHandler</name>
|
||||
|
@ -41,7 +41,7 @@ Context::Params::Params():
|
||||
verificationMode(VERIFY_RELAXED),
|
||||
verificationDepth(9),
|
||||
loadDefaultCAs(false),
|
||||
cipherList("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH")
|
||||
cipherList("ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH")
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -58,33 +58,6 @@ RUN curl https://sh.rustup.rs -sSf | bash -s -- -y && \
|
||||
rustup target add aarch64-apple-darwin && \
|
||||
rustup target add powerpc64le-unknown-linux-gnu
|
||||
|
||||
# Create vendor cache for cargo.
|
||||
#
|
||||
# Note, that the config.toml for the root is used, you will not be able to
|
||||
# install any other crates, except those which had been vendored (since if
|
||||
# there is "replace-with" for some source, then cargo will not look to other
|
||||
# remotes except this).
|
||||
#
|
||||
# Notes for the command itself:
|
||||
# - --chown is required to preserve the rights
|
||||
# - unstable-options for -C
|
||||
# - chmod is required to fix the permissions, since builds are running from a different user
|
||||
# - copy of the Cargo.lock is required for proper dependencies versions
|
||||
# - cargo vendor --sync is requried to overcome [1] bug.
|
||||
#
|
||||
# [1]: https://github.com/rust-lang/wg-cargo-std-aware/issues/23
|
||||
COPY --chown=root:root /rust /rust/packages
|
||||
RUN cargo -Z unstable-options -C /rust/packages vendor > $CARGO_HOME/config.toml && \
|
||||
cp "$(rustc --print=sysroot)"/lib/rustlib/src/rust/Cargo.lock "$(rustc --print=sysroot)"/lib/rustlib/src/rust/library/test/ && \
|
||||
cargo -Z unstable-options -C /rust/packages vendor --sync "$(rustc --print=sysroot)"/lib/rustlib/src/rust/library/test/Cargo.toml && \
|
||||
rm "$(rustc --print=sysroot)"/lib/rustlib/src/rust/library/test/Cargo.lock && \
|
||||
sed -i "s#\"vendor\"#\"/rust/vendor\"#" $CARGO_HOME/config.toml && \
|
||||
cat $CARGO_HOME/config.toml && \
|
||||
mv /rust/packages/vendor /rust/vendor && \
|
||||
chmod -R o=r+X /rust/vendor && \
|
||||
ls -R -l /rust/packages && \
|
||||
rm -r /rust/packages
|
||||
|
||||
# NOTE: Seems like gcc-11 is too new for ubuntu20 repository
|
||||
# A cross-linker for RISC-V 64 (we need it, because LLVM's LLD does not work):
|
||||
RUN add-apt-repository ppa:ubuntu-toolchain-r/test --yes \
|
||||
|
@ -1 +0,0 @@
|
||||
../../../rust
|
@ -80,9 +80,11 @@ def run_docker_image_with_env(
|
||||
output_dir: Path,
|
||||
env_variables: List[str],
|
||||
ch_root: Path,
|
||||
cargo_cache_dir: Path,
|
||||
ccache_dir: Optional[Path],
|
||||
) -> None:
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
cargo_cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
env_part = " -e ".join(env_variables)
|
||||
if env_part:
|
||||
@ -105,7 +107,7 @@ def run_docker_image_with_env(
|
||||
cmd = (
|
||||
f"docker run --network=host --user={user} --rm {ccache_mount}"
|
||||
f"--volume={output_dir}:/output --volume={ch_root}:/build {env_part} "
|
||||
f"{interactive} {image_name}"
|
||||
f"--volume={cargo_cache_dir}:/rust/cargo/registry {interactive} {image_name}"
|
||||
)
|
||||
|
||||
logging.info("Will build ClickHouse pkg with cmd: '%s'", cmd)
|
||||
@ -417,6 +419,13 @@ def parse_args() -> argparse.Namespace:
|
||||
action="store_true",
|
||||
help="if set, the build fails on errors writing cache to S3",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--cargo-cache-dir",
|
||||
default=Path(os.getenv("CARGO_HOME", "") or Path.home() / ".cargo")
|
||||
/ "registry",
|
||||
type=dir_name,
|
||||
help="a directory to preserve the rust cargo crates",
|
||||
)
|
||||
parser.add_argument("--force-build-image", action="store_true")
|
||||
parser.add_argument("--version")
|
||||
parser.add_argument("--official", action="store_true")
|
||||
@ -497,6 +506,7 @@ def main() -> None:
|
||||
args.output_dir,
|
||||
env_prepared,
|
||||
ch_root,
|
||||
args.cargo_cache_dir,
|
||||
args.ccache_dir,
|
||||
)
|
||||
logging.info("Output placed into %s", args.output_dir)
|
||||
|
@ -148,6 +148,7 @@ function clone_submodules
|
||||
contrib/liburing
|
||||
contrib/libfiu
|
||||
contrib/incbin
|
||||
contrib/yaml-cpp
|
||||
)
|
||||
|
||||
git submodule sync
|
||||
@ -170,6 +171,7 @@ function run_cmake
|
||||
"-DENABLE_SIMDJSON=1"
|
||||
"-DENABLE_JEMALLOC=1"
|
||||
"-DENABLE_LIBURING=1"
|
||||
"-DENABLE_YAML_CPP=1"
|
||||
)
|
||||
|
||||
export CCACHE_DIR="$FASTTEST_WORKSPACE/ccache"
|
||||
|
@ -323,9 +323,9 @@ clickhouse-client clickhouse://192.168.1.15,192.168.1.25
|
||||
`clickhouse-client` uses the first existing file of the following:
|
||||
|
||||
- Defined in the `--config-file` parameter.
|
||||
- `./clickhouse-client.xml`
|
||||
- `~/.clickhouse-client/config.xml`
|
||||
- `/etc/clickhouse-client/config.xml`
|
||||
- `./clickhouse-client.xml`, `.yaml`, `.yml`
|
||||
- `~/.clickhouse-client/config.xml`, `.yaml`, `.yml`
|
||||
- `/etc/clickhouse-client/config.xml`, `.yaml`, `.yml`
|
||||
|
||||
Example of a config file:
|
||||
|
||||
@ -342,6 +342,17 @@ Example of a config file:
|
||||
</config>
|
||||
```
|
||||
|
||||
Or the same config in a YAML format:
|
||||
|
||||
```yaml
|
||||
user: username
|
||||
password: 'password'
|
||||
secure: true
|
||||
openSSL:
|
||||
client:
|
||||
caConfig: '/etc/ssl/cert.pem'
|
||||
```
|
||||
|
||||
### Query ID Format {#query-id-format}
|
||||
|
||||
In interactive mode `clickhouse-client` shows query ID for every query. By default, the ID is formatted like this:
|
||||
|
@ -169,7 +169,6 @@ host = '127.0.0.1',
|
||||
port = 3306,
|
||||
database = 'test',
|
||||
connection_pool_size = 8,
|
||||
on_duplicate_clause = 1,
|
||||
replace_query = 1
|
||||
```
|
||||
|
||||
@ -185,7 +184,6 @@ replace_query = 1
|
||||
<port>3306</port>
|
||||
<database>test</database>
|
||||
<connection_pool_size>8</connection_pool_size>
|
||||
<on_duplicate_clause>1</on_duplicate_clause>
|
||||
<replace_query>1</replace_query>
|
||||
</mymysql>
|
||||
</named_collections>
|
||||
|
@ -1640,7 +1640,7 @@ Keys for server/client settings:
|
||||
- verificationMode (default: relaxed) – The method for checking the node’s certificates. Details are in the description of the [Context](https://github.com/ClickHouse-Extras/poco/blob/master/NetSSL_OpenSSL/include/Poco/Net/Context.h) class. Possible values: `none`, `relaxed`, `strict`, `once`.
|
||||
- verificationDepth (default: 9) – The maximum length of the verification chain. Verification will fail if the certificate chain length exceeds the set value.
|
||||
- loadDefaultCAFile (default: true) – Wether built-in CA certificates for OpenSSL will be used. ClickHouse assumes that builtin CA certificates are in the file `/etc/ssl/cert.pem` (resp. the directory `/etc/ssl/certs`) or in file (resp. directory) specified by the environment variable `SSL_CERT_FILE` (resp. `SSL_CERT_DIR`).
|
||||
- cipherList (default: `ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH`) - Supported OpenSSL encryptions.
|
||||
- cipherList (default: `ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH`) - Supported OpenSSL encryptions.
|
||||
- cacheSessions (default: false) – Enables or disables caching sessions. Must be used in combination with `sessionIdContext`. Acceptable values: `true`, `false`.
|
||||
- sessionIdContext (default: `${application.name}`) – A unique set of random characters that the server appends to each generated identifier. The length of the string must not exceed `SSL_MAX_SSL_SESSION_ID_LENGTH`. This parameter is always recommended since it helps avoid problems both if the server caches the session and if the client requested caching. Default value: `${application.name}`.
|
||||
- sessionCacheSize (default: [1024\*20](https://github.com/ClickHouse/boringssl/blob/master/include/openssl/ssl.h#L1978)) – The maximum number of sessions that the server caches. A value of 0 means unlimited sessions.
|
||||
|
@ -4,7 +4,7 @@ sidebar_position: 54
|
||||
sidebar_label: Tuple(T1, T2, ...)
|
||||
---
|
||||
|
||||
# Tuple(t1, T2, …)
|
||||
# Tuple(T1, T2, …)
|
||||
|
||||
A tuple of elements, each having an individual [type](../../sql-reference/data-types/index.md#data_types). Tuple must contain at least one element.
|
||||
|
||||
|
@ -183,9 +183,8 @@ arrayConcat(arrays)
|
||||
**Arguments**
|
||||
|
||||
- `arrays` – Arbitrary number of arguments of [Array](../../sql-reference/data-types/array.md) type.
|
||||
**Example**
|
||||
|
||||
<!-- -->
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
SELECT arrayConcat([1, 2], [3, 4], [5, 6]) AS res
|
||||
|
@ -559,6 +559,29 @@ Result:
|
||||
└────────────────────────────┘
|
||||
```
|
||||
|
||||
## tupleConcat
|
||||
|
||||
Combines tuples passed as arguments.
|
||||
|
||||
``` sql
|
||||
tupleConcat(tuples)
|
||||
```
|
||||
|
||||
**Arguments**
|
||||
|
||||
- `tuples` – Arbitrary number of arguments of [Tuple](../../sql-reference/data-types/tuple.md) type.
|
||||
|
||||
**Example**
|
||||
|
||||
``` sql
|
||||
SELECT tupleConcat((1, 2), (3, 4), (true, false)) AS res
|
||||
```
|
||||
|
||||
``` text
|
||||
┌─res──────────────────┐
|
||||
│ (1,2,3,4,true,false) │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
## Distance functions
|
||||
|
||||
|
@ -88,7 +88,6 @@ SELECT * FROM s3_engine_table LIMIT 3;
|
||||
<port>3306</port>
|
||||
<database>test</database>
|
||||
<connection_pool_size>8</connection_pool_size>
|
||||
<on_duplicate_clause>1</on_duplicate_clause>
|
||||
<replace_query>1</replace_query>
|
||||
</mymysql>
|
||||
</named_collections>
|
||||
|
@ -1106,7 +1106,7 @@ ClickHouse использует потоки из глобального пул
|
||||
- verificationMode - Способ проверки сертификатов узла. Подробности находятся в описании класса [Context](https://github.com/ClickHouse-Extras/poco/blob/master/NetSSL_OpenSSL/include/Poco/Net/Context.h). Допустимые значения: `none`, `relaxed`, `strict`, `once`.
|
||||
- verificationDepth - Максимальная длина верификационной цепи. Верификация завершится ошибкой, если длина цепи сертификатов превысит установленное значение.
|
||||
- loadDefaultCAFile - Признак того, что будут использоваться встроенные CA-сертификаты для OpenSSL. Допустимые значения: `true`, `false`. \|
|
||||
- cipherList - Поддерживаемые OpenSSL-шифры. Например, `ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH`.
|
||||
- cipherList - Поддерживаемые OpenSSL-шифры. Например, `ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH`.
|
||||
- cacheSessions - Включение/выключение кеширования сессии. Использовать обязательно вместе с `sessionIdContext`. Допустимые значения: `true`, `false`.
|
||||
- sessionIdContext - Уникальный набор произвольных символов, которые сервер добавляет к каждому сгенерированному идентификатору. Длина строки не должна превышать `SSL_MAX_SSL_SESSION_ID_LENGTH`. Рекомендуется к использованию всегда, поскольку позволяет избежать проблем как в случае, если сервер кеширует сессию, так и если клиент затребовал кеширование. По умолчанию `${application.name}`.
|
||||
- sessionCacheSize - Максимальное количество сессий, которые кэширует сервер. По умолчанию - 1024\*20. 0 - неограниченное количество сессий.
|
||||
|
@ -455,7 +455,7 @@ SSL客户端/服务器配置。
|
||||
- verificationMode – The method for checking the node’s certificates. Details are in the description of the [A.背景](https://github.com/ClickHouse-Extras/poco/blob/master/NetSSL_OpenSSL/include/Poco/Net/Context.h) 同学们 可能的值: `none`, `relaxed`, `strict`, `once`.
|
||||
- verificationDepth – The maximum length of the verification chain. Verification will fail if the certificate chain length exceeds the set value.
|
||||
- loadDefaultCAFile – Indicates that built-in CA certificates for OpenSSL will be used. Acceptable values: `true`, `false`. \|
|
||||
- cipherList – Supported OpenSSL encryptions. For example: `ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH`.
|
||||
- cipherList – Supported OpenSSL encryptions. For example: `ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH`.
|
||||
- cacheSessions – Enables or disables caching sessions. Must be used in combination with `sessionIdContext`. 可接受的值: `true`, `false`.
|
||||
- sessionIdContext – A unique set of random characters that the server appends to each generated identifier. The length of the string must not exceed `SSL_MAX_SSL_SESSION_ID_LENGTH`. 始终建议使用此参数,因为如果服务器缓存会话,以及客户端请求缓存,它有助于避免出现问题。 默认值: `${application.name}`.
|
||||
- sessionCacheSize – The maximum number of sessions that the server caches. Default value: 1024\*20. 0 – Unlimited sessions.
|
||||
|
@ -608,6 +608,8 @@ TaskStatus ClusterCopier::tryMoveAllPiecesToDestinationTable(const TaskTable & t
|
||||
ss << "ALTER TABLE " << getQuotedTable(original_table) << ((partition_name == "'all'") ? " DROP PARTITION ID " : " DROP PARTITION ") << partition_name;
|
||||
|
||||
UInt64 num_shards_drop_partition = executeQueryOnCluster(task_table.cluster_push, ss.str(), task_cluster->settings_push, ClusterExecutionMode::ON_EACH_SHARD);
|
||||
if (num_shards_drop_partition != task_table.cluster_push->getShardCount())
|
||||
return TaskStatus::Error;
|
||||
|
||||
LOG_INFO(log, "Drop partition {} in original table {} have been executed successfully on {} shards of {}",
|
||||
partition_name, getQuotedTable(original_table), num_shards_drop_partition, task_table.cluster_push->getShardCount());
|
||||
|
@ -163,13 +163,15 @@ int mainEntryClickHouseFormat(int argc, char ** argv)
|
||||
{
|
||||
ASTPtr res = parseQueryAndMovePosition(
|
||||
parser, pos, end, "query", multiple, cmd_settings.max_query_size, cmd_settings.max_parser_depth);
|
||||
/// For insert query with data(INSERT INTO ... VALUES ...), will lead to format fail,
|
||||
/// should throw exception early and make exception message more readable.
|
||||
|
||||
/// For insert query with data(INSERT INTO ... VALUES ...), that will lead to the formatting failure,
|
||||
/// we should throw an exception early, and make exception message more readable.
|
||||
if (const auto * insert_query = res->as<ASTInsertQuery>(); insert_query && insert_query->data)
|
||||
{
|
||||
throw Exception(DB::ErrorCodes::INVALID_FORMAT_INSERT_QUERY_WITH_DATA,
|
||||
"Can't format ASTInsertQuery with data, since data will be lost");
|
||||
}
|
||||
|
||||
if (!quiet)
|
||||
{
|
||||
if (!backslash)
|
||||
|
@ -57,6 +57,7 @@ if (BUILD_STANDALONE_KEEPER)
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/IO/ReadBuffer.cpp
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/Server/HTTPPathHints.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/Server/KeeperTCPHandler.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/Server/TCPServer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/Server/NotFoundHandler.cpp
|
||||
|
@ -150,7 +150,7 @@ int Keeper::run()
|
||||
}
|
||||
if (config().hasOption("version"))
|
||||
{
|
||||
std::cout << DBMS_NAME << " keeper version " << VERSION_STRING << VERSION_OFFICIAL << "." << std::endl;
|
||||
std::cout << VERSION_NAME << " keeper version " << VERSION_STRING << VERSION_OFFICIAL << "." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -389,7 +389,7 @@ int Server::run()
|
||||
}
|
||||
if (config().hasOption("version"))
|
||||
{
|
||||
std::cout << DBMS_NAME << " server version " << VERSION_STRING << VERSION_OFFICIAL << "." << std::endl;
|
||||
std::cout << VERSION_NAME << " server version " << VERSION_STRING << VERSION_OFFICIAL << "." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
return Application::run(); // NOLINT
|
||||
@ -1650,6 +1650,9 @@ try
|
||||
database_catalog.initializeAndLoadTemporaryDatabase();
|
||||
loadMetadataSystem(global_context);
|
||||
maybeConvertSystemDatabase(global_context);
|
||||
/// This has to be done before the initialization of system logs,
|
||||
/// otherwise there is a race condition between the system database initialization
|
||||
/// and creation of new tables in the database.
|
||||
startupSystemTables();
|
||||
/// After attaching system databases we can initialize system log.
|
||||
global_context->initializeSystemLogs();
|
||||
|
@ -317,7 +317,7 @@
|
||||
<concurrent_threads_soft_limit_ratio_to_cores>0</concurrent_threads_soft_limit_ratio_to_cores>
|
||||
|
||||
<!-- Maximum number of concurrent queries. -->
|
||||
<max_concurrent_queries>100</max_concurrent_queries>
|
||||
<max_concurrent_queries>1000</max_concurrent_queries>
|
||||
|
||||
<!-- Maximum memory usage (resident set size) for server process.
|
||||
Zero value or unset means default. Default is "max_server_memory_usage_to_ram_ratio" of available physical RAM.
|
||||
|
@ -5,6 +5,7 @@ CXXFLAGS = "@RUST_CXXFLAGS@"
|
||||
[build]
|
||||
rustflags = @RUSTFLAGS@
|
||||
rustdocflags = @RUSTFLAGS@
|
||||
@RUSTCWRAPPER@
|
||||
|
||||
[unstable]
|
||||
@RUST_CARGO_BUILD_STD@
|
||||
|
@ -1,4 +0,0 @@
|
||||
# Just in case ignore any cargo stuff (and just in case someone will run this
|
||||
# docker build locally with build context using folder root):
|
||||
target
|
||||
vendor
|
4
rust/.gitignore
vendored
4
rust/.gitignore
vendored
@ -1,4 +0,0 @@
|
||||
# This is for tar --exclude-vcs-ignores (and just in case someone will run
|
||||
# docker build locally with build context created via tar):
|
||||
target
|
||||
vendor
|
@ -14,6 +14,13 @@ macro(configure_rustc)
|
||||
set(RUST_CFLAGS "${RUST_CFLAGS} --sysroot ${CMAKE_SYSROOT}")
|
||||
endif()
|
||||
|
||||
if(CCACHE_EXECUTABLE MATCHES "/sccache$")
|
||||
message(STATUS "Using RUSTC_WRAPPER: ${CCACHE_EXECUTABLE}")
|
||||
set(RUSTCWRAPPER "rustc-wrapper = \"${CCACHE_EXECUTABLE}\"")
|
||||
else()
|
||||
set(RUSTCWRAPPER "")
|
||||
endif()
|
||||
|
||||
set(RUSTFLAGS "[]")
|
||||
set(RUST_CARGO_BUILD_STD "")
|
||||
# For more info: https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#memorysanitizer
|
||||
|
@ -550,12 +550,12 @@ bool ContextAccess::checkAccessImplHelper(AccessFlags flags, const Args &... arg
|
||||
return access_denied(ErrorCodes::ACCESS_DENIED,
|
||||
"{}: Not enough privileges. "
|
||||
"The required privileges have been granted, but without grant option. "
|
||||
"To execute this query it's necessary to have grant {} WITH GRANT OPTION",
|
||||
"To execute this query, it's necessary to have the grant {} WITH GRANT OPTION",
|
||||
AccessRightsElement{flags, args...}.toStringWithoutOptions());
|
||||
}
|
||||
|
||||
return access_denied(ErrorCodes::ACCESS_DENIED,
|
||||
"{}: Not enough privileges. To execute this query it's necessary to have grant {}",
|
||||
"{}: Not enough privileges. To execute this query, it's necessary to have the grant {}",
|
||||
AccessRightsElement{flags, args...}.toStringWithoutOptions() + (grant_option ? " WITH GRANT OPTION" : ""));
|
||||
}
|
||||
|
||||
@ -756,11 +756,11 @@ bool ContextAccess::checkAdminOptionImplHelper(const Container & role_ids, const
|
||||
show_error(ErrorCodes::ACCESS_DENIED,
|
||||
"Not enough privileges. "
|
||||
"Role {} is granted, but without ADMIN option. "
|
||||
"To execute this query it's necessary to have the role {} granted with ADMIN option.",
|
||||
"To execute this query, it's necessary to have the role {} granted with ADMIN option.",
|
||||
backQuote(*role_name), backQuoteIfNeed(*role_name));
|
||||
else
|
||||
show_error(ErrorCodes::ACCESS_DENIED, "Not enough privileges. "
|
||||
"To execute this query it's necessary to have the role {} granted with ADMIN option.",
|
||||
"To execute this query, it's necessary to have the role {} granted with ADMIN option.",
|
||||
backQuoteIfNeed(*role_name));
|
||||
}
|
||||
|
||||
|
@ -240,7 +240,7 @@ public:
|
||||
void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf, std::optional<size_t> /* version */) const override
|
||||
{
|
||||
const AggregateFunctionForEachData & state = data(place);
|
||||
writeBinary(state.dynamic_array_size, buf);
|
||||
writeBinaryLittleEndian(state.dynamic_array_size, buf);
|
||||
|
||||
const char * nested_state = state.array_of_aggregate_datas;
|
||||
for (size_t i = 0; i < state.dynamic_array_size; ++i)
|
||||
@ -255,7 +255,7 @@ public:
|
||||
AggregateFunctionForEachData & state = data(place);
|
||||
|
||||
size_t new_size = 0;
|
||||
readBinary(new_size, buf);
|
||||
readBinaryLittleEndian(new_size, buf);
|
||||
|
||||
ensureAggregateData(place, new_size, *arena);
|
||||
|
||||
|
@ -19,6 +19,7 @@ message (STATUS "Will build ${VERSION_FULL} revision ${VERSION_REVISION} ${VERSI
|
||||
include (configure_config.cmake)
|
||||
configure_file (Common/config.h.in ${CONFIG_INCLUDE_PATH}/config.h)
|
||||
configure_file (Common/config_version.h.in ${CONFIG_INCLUDE_PATH}/config_version.h)
|
||||
configure_file (Common/config_version.cpp.in ${CONFIG_INCLUDE_PATH}/config_version.cpp)
|
||||
|
||||
if (USE_DEBUG_HELPERS)
|
||||
get_target_property(MAGIC_ENUM_INCLUDE_DIR ch_contrib::magic_enum INTERFACE_INCLUDE_DIRECTORIES)
|
||||
@ -150,7 +151,7 @@ else()
|
||||
message(STATUS "StorageFileLog is only supported on Linux")
|
||||
endif ()
|
||||
|
||||
list (APPEND clickhouse_common_io_sources ${CONFIG_BUILD})
|
||||
list (APPEND clickhouse_common_io_sources ${CONFIG_INCLUDE_PATH}/config_version.cpp)
|
||||
|
||||
list (APPEND dbms_sources Functions/IFunction.cpp Functions/FunctionFactory.cpp Functions/FunctionHelpers.cpp Functions/extractTimeZoneFromFunctionArguments.cpp Functions/FunctionsLogical.cpp Functions/indexHint.cpp)
|
||||
list (APPEND dbms_headers Functions/IFunction.h Functions/FunctionFactory.h Functions/FunctionHelpers.h Functions/extractTimeZoneFromFunctionArguments.h Functions/FunctionsLogical.h Functions/indexHint.h)
|
||||
|
@ -2505,7 +2505,7 @@ void ClientBase::clearTerminal()
|
||||
|
||||
void ClientBase::showClientVersion()
|
||||
{
|
||||
std::cout << DBMS_NAME << " " + getName() + " version " << VERSION_STRING << VERSION_OFFICIAL << "." << std::endl;
|
||||
std::cout << VERSION_NAME << " " + getName() + " version " << VERSION_STRING << VERSION_OFFICIAL << "." << std::endl;
|
||||
}
|
||||
|
||||
namespace
|
||||
|
@ -280,9 +280,9 @@ void Connection::sendHello()
|
||||
"Parameters 'default_database', 'user' and 'password' must not contain ASCII control characters");
|
||||
|
||||
writeVarUInt(Protocol::Client::Hello, *out);
|
||||
writeStringBinary((DBMS_NAME " ") + client_name, *out);
|
||||
writeVarUInt(DBMS_VERSION_MAJOR, *out);
|
||||
writeVarUInt(DBMS_VERSION_MINOR, *out);
|
||||
writeStringBinary((VERSION_NAME " ") + client_name, *out);
|
||||
writeVarUInt(VERSION_MAJOR, *out);
|
||||
writeVarUInt(VERSION_MINOR, *out);
|
||||
// NOTE For backward compatibility of the protocol, client cannot send its version_patch.
|
||||
writeVarUInt(DBMS_TCP_PROTOCOL_VERSION, *out);
|
||||
writeStringBinary(default_database, *out);
|
||||
|
@ -5,36 +5,57 @@
|
||||
#include <filesystem>
|
||||
#include <base/types.h>
|
||||
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
bool safeFsExists(const String & path)
|
||||
{
|
||||
std::error_code ec;
|
||||
return fs::exists(path, ec);
|
||||
}
|
||||
|
||||
bool configReadClient(Poco::Util::LayeredConfiguration & config, const std::string & home_path)
|
||||
{
|
||||
std::string config_path;
|
||||
if (config.has("config-file"))
|
||||
config_path = config.getString("config-file");
|
||||
else if (safeFsExists("./clickhouse-client.xml"))
|
||||
config_path = "./clickhouse-client.xml";
|
||||
else if (!home_path.empty() && safeFsExists(home_path + "/.clickhouse-client/config.xml"))
|
||||
config_path = home_path + "/.clickhouse-client/config.xml";
|
||||
else if (safeFsExists("/etc/clickhouse-client/config.xml"))
|
||||
config_path = "/etc/clickhouse-client/config.xml";
|
||||
|
||||
if (!config_path.empty())
|
||||
bool found = false;
|
||||
if (config.has("config-file"))
|
||||
{
|
||||
found = true;
|
||||
config_path = config.getString("config-file");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
names.emplace_back("./clickhouse-client");
|
||||
if (!home_path.empty())
|
||||
names.emplace_back(home_path + "/.clickhouse-client/config");
|
||||
names.emplace_back("/etc/clickhouse-client/config");
|
||||
|
||||
for (const auto & name : names)
|
||||
{
|
||||
for (const auto & extension : {".xml", ".yaml", ".yml"})
|
||||
{
|
||||
config_path = name + extension;
|
||||
|
||||
std::error_code ec;
|
||||
if (fs::exists(config_path, ec))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
ConfigProcessor config_processor(config_path);
|
||||
auto loaded_config = config_processor.loadConfig();
|
||||
config.add(loaded_config.configuration);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <base/defines.h>
|
||||
#include <base/types.h>
|
||||
#include <fmt/format.h>
|
||||
@ -6,6 +7,8 @@
|
||||
#include <unordered_map>
|
||||
#include <Poco/Logger.h>
|
||||
#include <Poco/Message.h>
|
||||
#include <base/EnumReflection.h>
|
||||
|
||||
|
||||
struct PreformattedMessage;
|
||||
consteval void formatStringCheckArgsNumImpl(std::string_view str, size_t nargs);
|
||||
|
@ -106,6 +106,11 @@ public:
|
||||
return prompter.getHints(name, getAllRegisteredNames());
|
||||
}
|
||||
|
||||
std::vector<String> getHints(const String & name, const std::vector<String> & prompting_strings) const
|
||||
{
|
||||
return prompter.getHints(name, prompting_strings);
|
||||
}
|
||||
|
||||
void appendHintsMessage(String & error_message, const String & name) const
|
||||
{
|
||||
auto hints = getHints(name);
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/SettingsChanges.h>
|
||||
#include <Common/FieldVisitorToString.h>
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -33,13 +33,17 @@
|
||||
|
||||
namespace Poco
|
||||
{
|
||||
|
||||
class Logger;
|
||||
|
||||
namespace Util
|
||||
{
|
||||
class AbstractConfiguration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
3
src/Common/config_version.cpp.in
Normal file
3
src/Common/config_version.cpp.in
Normal file
@ -0,0 +1,3 @@
|
||||
/// This file was autogenerated by CMake
|
||||
|
||||
const char * VERSION_GITHASH = "@VERSION_GITHASH@";
|
@ -6,7 +6,6 @@
|
||||
// only DBMS_TCP_PROTOCOL_VERSION should be incremented on protocol changes.
|
||||
#cmakedefine VERSION_REVISION @VERSION_REVISION@
|
||||
#cmakedefine VERSION_NAME "@VERSION_NAME@"
|
||||
#define DBMS_NAME VERSION_NAME
|
||||
#cmakedefine VERSION_MAJOR @VERSION_MAJOR@
|
||||
#cmakedefine VERSION_MINOR @VERSION_MINOR@
|
||||
#cmakedefine VERSION_PATCH @VERSION_PATCH@
|
||||
@ -15,27 +14,10 @@
|
||||
#cmakedefine VERSION_OFFICIAL "@VERSION_OFFICIAL@"
|
||||
#cmakedefine VERSION_FULL "@VERSION_FULL@"
|
||||
#cmakedefine VERSION_DESCRIBE "@VERSION_DESCRIBE@"
|
||||
#cmakedefine VERSION_GITHASH "@VERSION_GITHASH@"
|
||||
#cmakedefine VERSION_INTEGER @VERSION_INTEGER@
|
||||
#cmakedefine VERSION_DATE @VERSION_DATE@
|
||||
|
||||
#if defined(VERSION_MAJOR)
|
||||
#define DBMS_VERSION_MAJOR VERSION_MAJOR
|
||||
#else
|
||||
#define DBMS_VERSION_MAJOR 0
|
||||
#endif
|
||||
|
||||
#if defined(VERSION_MINOR)
|
||||
#define DBMS_VERSION_MINOR VERSION_MINOR
|
||||
#else
|
||||
#define DBMS_VERSION_MINOR 0
|
||||
#endif
|
||||
|
||||
#if defined(VERSION_PATCH)
|
||||
#define DBMS_VERSION_PATCH VERSION_PATCH
|
||||
#else
|
||||
#define DBMS_VERSION_PATCH 0
|
||||
#endif
|
||||
/// These fields are frequently changing and we don't want to have them in the header file to allow caching.
|
||||
extern const char * VERSION_GITHASH;
|
||||
|
||||
#if !defined(VERSION_OFFICIAL)
|
||||
# define VERSION_OFFICIAL ""
|
||||
|
@ -466,7 +466,7 @@ String EnviCommand::run()
|
||||
|
||||
StringBuffer buf;
|
||||
buf << "Environment:\n";
|
||||
buf << "clickhouse.keeper.version=" << (String(VERSION_DESCRIBE) + "-" + VERSION_GITHASH) << '\n';
|
||||
buf << "clickhouse.keeper.version=" << VERSION_DESCRIBE << '-' << VERSION_GITHASH << '\n';
|
||||
|
||||
buf << "host.name=" << Environment::nodeName() << '\n';
|
||||
buf << "os.name=" << Environment::osDisplayName() << '\n';
|
||||
|
@ -9,8 +9,10 @@
|
||||
|
||||
#include "config_version.h"
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
struct IFourLetterCommand;
|
||||
using FourLetterCommandPtr = std::shared_ptr<DB::IFourLetterCommand>;
|
||||
|
||||
@ -43,7 +45,7 @@ public:
|
||||
using Commands = std::unordered_map<int32_t, FourLetterCommandPtr>;
|
||||
using AllowList = std::vector<int32_t>;
|
||||
|
||||
///represent '*' which is used in allow list
|
||||
/// Represents '*' which is used in allow list.
|
||||
static constexpr int32_t ALLOW_LIST_ALL = 0;
|
||||
|
||||
bool isKnown(int32_t code);
|
||||
|
@ -11,8 +11,11 @@
|
||||
#include <Common/FieldVisitorWriteBinary.h>
|
||||
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int CANNOT_RESTORE_FROM_FIELD_DUMP;
|
||||
@ -582,34 +585,41 @@ String toString(const Field & x)
|
||||
x);
|
||||
}
|
||||
|
||||
String fieldTypeToString(Field::Types::Which type)
|
||||
std::string_view fieldTypeToString(Field::Types::Which type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Field::Types::Which::Null: return "Null";
|
||||
case Field::Types::Which::Array: return "Array";
|
||||
case Field::Types::Which::Tuple: return "Tuple";
|
||||
case Field::Types::Which::Map: return "Map";
|
||||
case Field::Types::Which::Object: return "Object";
|
||||
case Field::Types::Which::AggregateFunctionState: return "AggregateFunctionState";
|
||||
case Field::Types::Which::Bool: return "Bool";
|
||||
case Field::Types::Which::String: return "String";
|
||||
case Field::Types::Which::Decimal32: return "Decimal32";
|
||||
case Field::Types::Which::Decimal64: return "Decimal64";
|
||||
case Field::Types::Which::Decimal128: return "Decimal128";
|
||||
case Field::Types::Which::Decimal256: return "Decimal256";
|
||||
case Field::Types::Which::Float64: return "Float64";
|
||||
case Field::Types::Which::Int64: return "Int64";
|
||||
case Field::Types::Which::Int128: return "Int128";
|
||||
case Field::Types::Which::Int256: return "Int256";
|
||||
case Field::Types::Which::UInt64: return "UInt64";
|
||||
case Field::Types::Which::UInt128: return "UInt128";
|
||||
case Field::Types::Which::UInt256: return "UInt256";
|
||||
case Field::Types::Which::UUID: return "UUID";
|
||||
case Field::Types::Which::IPv4: return "IPv4";
|
||||
case Field::Types::Which::IPv6: return "IPv6";
|
||||
case Field::Types::Which::CustomType: return "CustomType";
|
||||
case Field::Types::Which::Null: return "Null"sv;
|
||||
case Field::Types::Which::Array: return "Array"sv;
|
||||
case Field::Types::Which::Tuple: return "Tuple"sv;
|
||||
case Field::Types::Which::Map: return "Map"sv;
|
||||
case Field::Types::Which::Object: return "Object"sv;
|
||||
case Field::Types::Which::AggregateFunctionState: return "AggregateFunctionState"sv;
|
||||
case Field::Types::Which::Bool: return "Bool"sv;
|
||||
case Field::Types::Which::String: return "String"sv;
|
||||
case Field::Types::Which::Decimal32: return "Decimal32"sv;
|
||||
case Field::Types::Which::Decimal64: return "Decimal64"sv;
|
||||
case Field::Types::Which::Decimal128: return "Decimal128"sv;
|
||||
case Field::Types::Which::Decimal256: return "Decimal256"sv;
|
||||
case Field::Types::Which::Float64: return "Float64"sv;
|
||||
case Field::Types::Which::Int64: return "Int64"sv;
|
||||
case Field::Types::Which::Int128: return "Int128"sv;
|
||||
case Field::Types::Which::Int256: return "Int256"sv;
|
||||
case Field::Types::Which::UInt64: return "UInt64"sv;
|
||||
case Field::Types::Which::UInt128: return "UInt128"sv;
|
||||
case Field::Types::Which::UInt256: return "UInt256"sv;
|
||||
case Field::Types::Which::UUID: return "UUID"sv;
|
||||
case Field::Types::Which::IPv4: return "IPv4"sv;
|
||||
case Field::Types::Which::IPv6: return "IPv6"sv;
|
||||
case Field::Types::Which::CustomType: return "CustomType"sv;
|
||||
}
|
||||
}
|
||||
|
||||
/// Keep in mind, that "magic_enum" is very expensive for compiler, that's why we don't use it.
|
||||
std::string_view Field::getTypeName() const
|
||||
{
|
||||
return fieldTypeToString(which);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -15,8 +15,7 @@
|
||||
#include <Core/UUID.h>
|
||||
#include <base/IPv4andIPv6.h>
|
||||
#include <base/DayNum.h>
|
||||
#include <base/strong_typedef.h>
|
||||
#include <base/EnumReflection.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -449,7 +448,7 @@ public:
|
||||
|
||||
Types::Which getType() const { return which; }
|
||||
|
||||
constexpr std::string_view getTypeName() const { return magic_enum::enum_name(which); }
|
||||
std::string_view getTypeName() const;
|
||||
|
||||
bool isNull() const { return which == Types::Null; }
|
||||
template <typename T>
|
||||
@ -1005,7 +1004,7 @@ void writeFieldText(const Field & x, WriteBuffer & buf);
|
||||
|
||||
String toString(const Field & x);
|
||||
|
||||
String fieldTypeToString(Field::Types::Which type);
|
||||
std::string_view fieldTypeToString(Field::Types::Which type);
|
||||
|
||||
}
|
||||
|
||||
|
@ -816,7 +816,6 @@ class IColumn;
|
||||
MAKE_OBSOLETE(M, UInt64, merge_tree_clear_old_parts_interval_seconds, 1) \
|
||||
MAKE_OBSOLETE(M, UInt64, partial_merge_join_optimizations, 0) \
|
||||
MAKE_OBSOLETE(M, MaxThreads, max_alter_threads, 0) \
|
||||
MAKE_OBSOLETE(M, Bool, allow_experimental_query_cache, true) \
|
||||
/* moved to config.xml: see also src/Core/ServerSettings.h */ \
|
||||
MAKE_DEPRECATED_BY_SERVER_CONFIG(M, UInt64, background_buffer_flush_schedule_pool_size, 16) \
|
||||
MAKE_DEPRECATED_BY_SERVER_CONFIG(M, UInt64, background_pool_size, 16) \
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <chrono>
|
||||
#include <unordered_map>
|
||||
#include <string_view>
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -72,12 +72,6 @@ void applySettingsQuirks(Settings & settings, Poco::Logger * log)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(THREAD_SANITIZER)
|
||||
settings.use_hedged_requests.value = false;
|
||||
if (log)
|
||||
LOG_WARNING(log, "use_hedged_requests has been disabled for the build with Thread Sanitizer, because they are using fibers, leading to a failed assertion inside TSan");
|
||||
#endif
|
||||
|
||||
if (!queryProfilerWorks())
|
||||
{
|
||||
if (settings.query_profiler_real_time_period_ns)
|
||||
|
@ -9,6 +9,3 @@ target_link_libraries (string_ref_hash PRIVATE clickhouse_common_io)
|
||||
|
||||
clickhouse_add_executable (mysql_protocol mysql_protocol.cpp)
|
||||
target_link_libraries (mysql_protocol PRIVATE dbms)
|
||||
|
||||
clickhouse_add_executable (coro coro.cpp)
|
||||
target_link_libraries (coro PRIVATE clickhouse_common_io)
|
||||
|
@ -1,194 +0,0 @@
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/logger_useful.h>
|
||||
#include <Poco/ConsoleChannel.h>
|
||||
#include <Poco/Logger.h>
|
||||
#include <Poco/AutoPtr.h>
|
||||
|
||||
#if defined(__clang__)
|
||||
#include <experimental/coroutine>
|
||||
|
||||
namespace std // NOLINT(cert-dcl58-cpp)
|
||||
{
|
||||
using namespace experimental::coroutines_v1; // NOLINT(cert-dcl58-cpp)
|
||||
}
|
||||
|
||||
#if __has_warning("-Wdeprecated-experimental-coroutine")
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-experimental-coroutine"
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include <coroutine>
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
|
||||
#endif
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct suspend_value // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
constexpr bool await_ready() const noexcept { return true; } // NOLINT(readability-identifier-naming)
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {} // NOLINT(readability-identifier-naming)
|
||||
constexpr T await_resume() const noexcept // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
std::cout << " ret " << val << std::endl;
|
||||
return val;
|
||||
}
|
||||
|
||||
T val;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Task
|
||||
{
|
||||
struct promise_type // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
using coro_handle = std::coroutine_handle<promise_type>;
|
||||
auto get_return_object() { return coro_handle::from_promise(*this); } // NOLINT(readability-identifier-naming)
|
||||
auto initial_suspend() { return std::suspend_never(); } // NOLINT(readability-identifier-naming)
|
||||
auto final_suspend() noexcept { return suspend_value<T>{*r->value}; } // NOLINT(readability-identifier-naming)
|
||||
//void return_void() {}
|
||||
void return_value(T value_) { r->value = value_; } // NOLINT(readability-identifier-naming)
|
||||
void unhandled_exception() // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
DB::tryLogCurrentException("Logger");
|
||||
r->exception = std::current_exception(); // NOLINT(bugprone-throw-keyword-missing)
|
||||
}
|
||||
|
||||
explicit promise_type(std::string tag_) : tag(tag_) {}
|
||||
~promise_type() { std::cout << "~promise_type " << tag << std::endl; }
|
||||
std::string tag;
|
||||
coro_handle next;
|
||||
Task * r = nullptr;
|
||||
};
|
||||
|
||||
using coro_handle = std::coroutine_handle<promise_type>;
|
||||
|
||||
bool await_ready() const noexcept { return false; } // NOLINT(readability-identifier-naming)
|
||||
void await_suspend(coro_handle g) noexcept // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
std::cout << " await_suspend " << my.promise().tag << std::endl;
|
||||
std::cout << " g tag " << g.promise().tag << std::endl;
|
||||
g.promise().next = my;
|
||||
}
|
||||
T await_resume() noexcept // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
std::cout << " await_res " << my.promise().tag << std::endl;
|
||||
return *value;
|
||||
}
|
||||
|
||||
Task(coro_handle handle) : my(handle), tag(handle.promise().tag) // NOLINT(google-explicit-constructor)
|
||||
{
|
||||
assert(handle);
|
||||
my.promise().r = this;
|
||||
std::cout << " Task " << tag << std::endl;
|
||||
}
|
||||
Task(Task &) = delete;
|
||||
Task(Task &&rhs) noexcept : my(rhs.my), tag(rhs.tag)
|
||||
{
|
||||
rhs.my = {};
|
||||
std::cout << " Task&& " << tag << std::endl;
|
||||
}
|
||||
static bool resumeImpl(Task *r)
|
||||
{
|
||||
if (r->value)
|
||||
return false;
|
||||
|
||||
auto & next = r->my.promise().next;
|
||||
|
||||
if (next)
|
||||
{
|
||||
if (resumeImpl(next.promise().r))
|
||||
return true;
|
||||
next = {};
|
||||
}
|
||||
|
||||
if (!r->value)
|
||||
{
|
||||
r->my.resume();
|
||||
if (r->exception)
|
||||
std::rethrow_exception(r->exception);
|
||||
}
|
||||
return !r->value;
|
||||
}
|
||||
|
||||
bool resume()
|
||||
{
|
||||
return resumeImpl(this);
|
||||
}
|
||||
|
||||
T res()
|
||||
{
|
||||
return *value;
|
||||
}
|
||||
|
||||
~Task()
|
||||
{
|
||||
std::cout << " ~Task " << tag << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
coro_handle my;
|
||||
std::string tag;
|
||||
std::optional<T> value;
|
||||
std::exception_ptr exception;
|
||||
};
|
||||
|
||||
Task<int> boo([[maybe_unused]] std::string tag)
|
||||
{
|
||||
std::cout << "x" << std::endl;
|
||||
co_await std::suspend_always();
|
||||
std::cout << StackTrace().toString();
|
||||
std::cout << "y" << std::endl;
|
||||
co_return 1;
|
||||
}
|
||||
|
||||
Task<int> bar([[maybe_unused]] std::string tag)
|
||||
{
|
||||
std::cout << "a" << std::endl;
|
||||
int res1 = co_await boo("boo1");
|
||||
std::cout << "b " << res1 << std::endl;
|
||||
int res2 = co_await boo("boo2");
|
||||
if (res2 == 1)
|
||||
throw DB::Exception(1, "hello");
|
||||
std::cout << "c " << res2 << std::endl;
|
||||
co_return res1 + res2; // 1 + 1 = 2
|
||||
}
|
||||
|
||||
Task<int> foo([[maybe_unused]] std::string tag)
|
||||
{
|
||||
std::cout << "Hello" << std::endl;
|
||||
auto res1 = co_await bar("bar1");
|
||||
std::cout << "Coro " << res1 << std::endl;
|
||||
auto res2 = co_await bar("bar2");
|
||||
std::cout << "World " << res2 << std::endl;
|
||||
co_return res1 * res2; // 2 * 2 = 4
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Poco::AutoPtr<Poco::ConsoleChannel> app_channel(new Poco::ConsoleChannel(std::cerr));
|
||||
Poco::Logger::root().setChannel(app_channel);
|
||||
Poco::Logger::root().setLevel("trace");
|
||||
|
||||
LOG_INFO(&Poco::Logger::get(""), "Starting");
|
||||
|
||||
try
|
||||
{
|
||||
auto t = foo("foo");
|
||||
std::cout << ".. started" << std::endl;
|
||||
while (t.resume())
|
||||
std::cout << ".. yielded" << std::endl;
|
||||
std::cout << ".. done: " << t.res() << std::endl;
|
||||
}
|
||||
catch (DB::Exception & e)
|
||||
{
|
||||
std::cout << "Got exception " << e.what() << std::endl;
|
||||
std::cout << e.getStackTraceString() << std::endl;
|
||||
}
|
||||
}
|
@ -129,7 +129,7 @@ namespace
|
||||
for (size_t i = offset; i < end; ++i)
|
||||
{
|
||||
ColumnArray::Offset current_offset = offset_values[i];
|
||||
writeIntBinary(current_offset - prev_offset, ostr);
|
||||
writeBinaryLittleEndian(current_offset - prev_offset, ostr);
|
||||
prev_offset = current_offset;
|
||||
}
|
||||
}
|
||||
@ -145,7 +145,7 @@ namespace
|
||||
while (i < initial_size + limit && !istr.eof())
|
||||
{
|
||||
ColumnArray::Offset current_size = 0;
|
||||
readIntBinary(current_size, istr);
|
||||
readBinaryLittleEndian(current_size, istr);
|
||||
|
||||
if (unlikely(current_size > MAX_ARRAY_SIZE))
|
||||
throw Exception(ErrorCodes::TOO_LARGE_ARRAY_SIZE, "Array size is too large: {}", current_size);
|
||||
|
@ -106,28 +106,28 @@ void SerializationNumber<T>::serializeBinary(const Field & field, WriteBuffer &
|
||||
{
|
||||
/// ColumnVector<T>::ValueType is a narrower type. For example, UInt8, when the Field type is UInt64
|
||||
typename ColumnVector<T>::ValueType x = static_cast<typename ColumnVector<T>::ValueType>(field.get<FieldType>());
|
||||
writeBinary(x, ostr);
|
||||
writeBinaryLittleEndian(x, ostr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SerializationNumber<T>::deserializeBinary(Field & field, ReadBuffer & istr, const FormatSettings &) const
|
||||
{
|
||||
typename ColumnVector<T>::ValueType x;
|
||||
readBinary(x, istr);
|
||||
readBinaryLittleEndian(x, istr);
|
||||
field = NearestFieldType<FieldType>(x);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SerializationNumber<T>::serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const
|
||||
{
|
||||
writeBinary(assert_cast<const ColumnVector<T> &>(column).getData()[row_num], ostr);
|
||||
writeBinaryLittleEndian(assert_cast<const ColumnVector<T> &>(column).getData()[row_num], ostr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SerializationNumber<T>::deserializeBinary(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
|
||||
{
|
||||
typename ColumnVector<T>::ValueType x;
|
||||
readBinary(x, istr);
|
||||
readBinaryLittleEndian(x, istr);
|
||||
assert_cast<ColumnVector<T> &>(column).getData().push_back(x);
|
||||
}
|
||||
|
||||
|
@ -471,7 +471,15 @@ void DatabaseAtomic::tryCreateSymlink(const String & table_name, const String &
|
||||
{
|
||||
String link = path_to_table_symlinks + escapeForFileName(table_name);
|
||||
fs::path data = fs::canonical(getContext()->getPath()) / actual_data_path;
|
||||
if (!if_data_path_exist || fs::exists(data))
|
||||
|
||||
/// If it already points where needed.
|
||||
std::error_code ec;
|
||||
if (fs::equivalent(data, link, ec))
|
||||
return;
|
||||
|
||||
if (if_data_path_exist && !fs::exists(data))
|
||||
return;
|
||||
|
||||
fs::create_directory_symlink(data, link);
|
||||
}
|
||||
catch (...)
|
||||
|
@ -1,7 +1,10 @@
|
||||
#include <memory>
|
||||
#include <Databases/IDatabase.h>
|
||||
#include <Storages/IStorage.h>
|
||||
#include <Parsers/ASTCreateQuery.h>
|
||||
#include <Common/quoteString.h>
|
||||
#include <Interpreters/DatabaseCatalog.h>
|
||||
#include <Common/NamePrompter.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -18,7 +21,13 @@ StoragePtr IDatabase::getTable(const String & name, ContextPtr context) const
|
||||
{
|
||||
if (auto storage = tryGetTable(name, context))
|
||||
return storage;
|
||||
throw Exception(ErrorCodes::UNKNOWN_TABLE, "Table {}.{} doesn't exist", backQuoteIfNeed(getDatabaseName()), backQuoteIfNeed(name));
|
||||
TableNameHints hints(this->shared_from_this(), context);
|
||||
std::vector<String> names = hints.getHints(name);
|
||||
if (!names.empty())
|
||||
{
|
||||
throw Exception(ErrorCodes::UNKNOWN_TABLE, "Table {}.{} does not exist. Maybe you meant {}?", backQuoteIfNeed(getDatabaseName()), backQuoteIfNeed(name), backQuoteIfNeed(names[0]));
|
||||
}
|
||||
else throw Exception(ErrorCodes::UNKNOWN_TABLE, "Table {}.{} does not exist", backQuoteIfNeed(getDatabaseName()), backQuoteIfNeed(name));
|
||||
}
|
||||
|
||||
std::vector<std::pair<ASTPtr, StoragePtr>> IDatabase::getTablesForBackup(const FilterByNameFunction &, const ContextPtr &) const
|
||||
|
@ -372,6 +372,7 @@ protected:
|
||||
};
|
||||
|
||||
using DatabasePtr = std::shared_ptr<IDatabase>;
|
||||
using ConstDatabasePtr = std::shared_ptr<const IDatabase>;
|
||||
using Databases = std::map<String, DatabasePtr>;
|
||||
|
||||
}
|
||||
|
@ -755,6 +755,9 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
static constexpr bool is_multiply = IsOperation<Op>::multiply;
|
||||
static constexpr bool is_division = IsOperation<Op>::division;
|
||||
static constexpr bool is_bit_hamming_distance = IsOperation<Op>::bit_hamming_distance;
|
||||
static constexpr bool is_modulo = IsOperation<Op>::modulo;
|
||||
static constexpr bool is_div_int = IsOperation<Op>::div_int;
|
||||
static constexpr bool is_div_int_or_zero = IsOperation<Op>::div_int_or_zero;
|
||||
|
||||
ContextPtr context;
|
||||
bool check_decimal_overflow = true;
|
||||
@ -964,14 +967,29 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
"argument of numeric type cannot be first", name);
|
||||
|
||||
std::string function_name;
|
||||
if (is_multiply)
|
||||
if constexpr (is_multiply)
|
||||
{
|
||||
function_name = "tupleMultiplyByNumber";
|
||||
}
|
||||
else // is_division
|
||||
{
|
||||
if constexpr (is_modulo)
|
||||
{
|
||||
function_name = "tupleModuloByNumber";
|
||||
}
|
||||
else if constexpr (is_div_int)
|
||||
{
|
||||
function_name = "tupleIntDivByNumber";
|
||||
}
|
||||
else if constexpr (is_div_int_or_zero)
|
||||
{
|
||||
function_name = "tupleIntDivOrZeroByNumber";
|
||||
}
|
||||
else
|
||||
{
|
||||
function_name = "tupleDivideByNumber";
|
||||
}
|
||||
}
|
||||
|
||||
return FunctionFactory::instance().get(function_name, context);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace ErrorCodes
|
||||
extern const int BAD_ARGUMENTS;
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
/** Token search the string, means that needle must be surrounded by some separator chars, like whitespace or puctuation.
|
||||
@ -39,9 +40,6 @@ struct HasTokenImpl
|
||||
if (start_pos != nullptr)
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Function '{}' does not support start_pos argument", name);
|
||||
|
||||
if (pattern.empty())
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Needle cannot be empty, because empty string isn't a token");
|
||||
|
||||
if (haystack_offsets.empty())
|
||||
return;
|
||||
|
||||
@ -49,7 +47,7 @@ struct HasTokenImpl
|
||||
const UInt8 * const end = haystack_data.data() + haystack_data.size();
|
||||
const UInt8 * pos = begin;
|
||||
|
||||
if (!std::none_of(pattern.begin(), pattern.end(), isTokenSeparator))
|
||||
if (const auto has_separator = std::any_of(pattern.cbegin(), pattern.cend(), isTokenSeparator); has_separator || pattern.empty())
|
||||
{
|
||||
if (res_null)
|
||||
{
|
||||
@ -57,8 +55,12 @@ struct HasTokenImpl
|
||||
std::ranges::fill(res_null->getData(), true);
|
||||
return;
|
||||
}
|
||||
else
|
||||
else if (has_separator)
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Needle must not contain whitespace or separator characters");
|
||||
else if (pattern.empty())
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Needle cannot be empty, because empty string isn't a token");
|
||||
else
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unexpected internal state");
|
||||
}
|
||||
|
||||
size_t pattern_size = pattern.size();
|
||||
|
@ -60,7 +60,7 @@ struct IsOperation
|
||||
|
||||
static constexpr bool bit_hamming_distance = IsSameOperation<Op, BitHammingDistanceImpl>::value;
|
||||
|
||||
static constexpr bool division = div_floating || div_int || div_int_or_zero;
|
||||
static constexpr bool division = div_floating || div_int || div_int_or_zero || modulo;
|
||||
|
||||
static constexpr bool allow_decimal = plus || minus || multiply || division || least || greatest;
|
||||
};
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include <algorithm>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <DataTypes/DataTypeArray.h>
|
||||
#include <Columns/ColumnVector.h>
|
||||
#include <Columns/ColumnArray.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include "arrayScalarProduct.h"
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -10,6 +12,8 @@ namespace DB
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
|
||||
@ -70,44 +74,32 @@ namespace ErrorCodes
|
||||
* The "curve" will be present by a line that moves one step either towards right or top on each threshold change.
|
||||
*/
|
||||
|
||||
|
||||
struct NameArrayAUC
|
||||
{
|
||||
static constexpr auto name = "arrayAUC";
|
||||
};
|
||||
|
||||
|
||||
class ArrayAUCImpl
|
||||
class FunctionArrayAUC : public IFunction
|
||||
{
|
||||
public:
|
||||
using ResultType = Float64;
|
||||
static constexpr auto name = "arrayAUC";
|
||||
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionArrayAUC>(); }
|
||||
|
||||
static DataTypePtr getReturnType(const DataTypePtr & /* score_type */, const DataTypePtr & label_type)
|
||||
{
|
||||
if (!(isNumber(label_type) || isEnum(label_type)))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "{} label must have numeric type.", std::string(NameArrayAUC::name));
|
||||
|
||||
return std::make_shared<DataTypeNumber<ResultType>>();
|
||||
}
|
||||
|
||||
template <typename ResultType, typename T, typename U>
|
||||
static ResultType apply(
|
||||
const T * scores,
|
||||
const U * labels,
|
||||
size_t size)
|
||||
private:
|
||||
static Float64 apply(
|
||||
const IColumn & scores,
|
||||
const IColumn & labels,
|
||||
ColumnArray::Offset current_offset,
|
||||
ColumnArray::Offset next_offset)
|
||||
{
|
||||
struct ScoreLabel
|
||||
{
|
||||
T score;
|
||||
Float64 score;
|
||||
bool label;
|
||||
};
|
||||
|
||||
size_t size = next_offset - current_offset;
|
||||
PODArrayWithStackMemory<ScoreLabel, 1024> sorted_labels(size);
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
bool label = labels[i] > 0;
|
||||
sorted_labels[i].score = scores[i];
|
||||
bool label = labels.getFloat64(current_offset + i) > 0;
|
||||
sorted_labels[i].score = scores.getFloat64(current_offset + i);
|
||||
sorted_labels[i].label = label;
|
||||
}
|
||||
|
||||
@ -129,18 +121,85 @@ public:
|
||||
/// Then divide the area to the area of rectangle.
|
||||
|
||||
if (count_positive == 0 || count_positive == size)
|
||||
return std::numeric_limits<ResultType>::quiet_NaN();
|
||||
return std::numeric_limits<Float64>::quiet_NaN();
|
||||
|
||||
return static_cast<ResultType>(area) / count_positive / (size - count_positive);
|
||||
return static_cast<Float64>(area) / count_positive / (size - count_positive);
|
||||
}
|
||||
|
||||
static void vector(
|
||||
const IColumn & scores,
|
||||
const IColumn & labels,
|
||||
const ColumnArray::Offsets & offsets,
|
||||
PaddedPODArray<Float64> & result)
|
||||
{
|
||||
size_t size = offsets.size();
|
||||
result.resize(size);
|
||||
|
||||
ColumnArray::Offset current_offset = 0;
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
auto next_offset = offsets[i];
|
||||
result[i] = apply(scores, labels, current_offset, next_offset);
|
||||
current_offset = next_offset;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
String getName() const override { return name; }
|
||||
size_t getNumberOfArguments() const override { return 2; }
|
||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo &) const override { return false; }
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
for (size_t i = 0; i < getNumberOfArguments(); ++i)
|
||||
{
|
||||
const DataTypeArray * array_type = checkAndGetDataType<DataTypeArray>(arguments[i].get());
|
||||
if (!array_type)
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "All arguments for function {} must be an array.", getName());
|
||||
|
||||
const auto & nested_type = array_type->getNestedType();
|
||||
if (!isNativeNumber(nested_type) && !isEnum(nested_type))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "{} cannot process values of type {}",
|
||||
getName(), nested_type->getName());
|
||||
}
|
||||
|
||||
return std::make_shared<DataTypeFloat64>();
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t) const override
|
||||
{
|
||||
ColumnPtr col1 = arguments[0].column->convertToFullColumnIfConst();
|
||||
ColumnPtr col2 = arguments[1].column->convertToFullColumnIfConst();
|
||||
|
||||
const ColumnArray * col_array1 = checkAndGetColumn<ColumnArray>(col1.get());
|
||||
if (!col_array1)
|
||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN,
|
||||
"Illegal column {} of first argument of function {}", arguments[0].column->getName(), getName());
|
||||
|
||||
const ColumnArray * col_array2 = checkAndGetColumn<ColumnArray>(col2.get());
|
||||
if (!col_array2)
|
||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN,
|
||||
"Illegal column {} of second argument of function {}", arguments[1].column->getName(), getName());
|
||||
|
||||
if (!col_array1->hasEqualOffsets(*col_array2))
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Array arguments for function {} must have equal sizes", getName());
|
||||
|
||||
auto col_res = ColumnVector<Float64>::create();
|
||||
|
||||
vector(
|
||||
col_array1->getData(),
|
||||
col_array2->getData(),
|
||||
col_array1->getOffsets(),
|
||||
col_res->getData());
|
||||
|
||||
return col_res;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// auc(array_score, array_label) - Calculate AUC with array of score and label
|
||||
using FunctionArrayAUC = FunctionArrayScalarProduct<ArrayAUCImpl, NameArrayAUC>;
|
||||
|
||||
REGISTER_FUNCTION(ArrayAUC)
|
||||
{
|
||||
factory.registerFunction<FunctionArrayAUC>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -208,6 +208,10 @@ public:
|
||||
{
|
||||
return FunctionFactory::instance().getImpl("mapConcat", context)->build(arguments);
|
||||
}
|
||||
else if (isTuple(arguments.at(0).type))
|
||||
{
|
||||
return FunctionFactory::instance().getImpl("tupleConcat", context)->build(arguments);
|
||||
}
|
||||
else
|
||||
return std::make_unique<FunctionToFunctionBaseAdaptor>(
|
||||
FunctionConcat::create(context), collections::map<DataTypes>(arguments, [](const auto & elem) { return elem.type; }), return_type);
|
||||
|
@ -764,9 +764,8 @@ namespace
|
||||
}
|
||||
|
||||
/// Note: Doesn't check the duplicates in the `from` array.
|
||||
|
||||
WhichDataType which(from_type);
|
||||
if (isNativeNumber(which) || which.isDecimal32() || which.isDecimal64())
|
||||
/// Field may be of Float type, but for the purpose of bitwise equality we can treat them as UInt64
|
||||
if (WhichDataType which(from_type); isNativeNumber(which) || which.isDecimal32() || which.isDecimal64())
|
||||
{
|
||||
cache.table_num_to_idx = std::make_unique<Cache::NumToIdx>();
|
||||
auto & table = *cache.table_num_to_idx;
|
||||
@ -774,10 +773,13 @@ namespace
|
||||
{
|
||||
if (applyVisitor(FieldVisitorAccurateEquals(), (*cache.from_column)[i], (*from_column_uncasted)[i]))
|
||||
{
|
||||
/// Field may be of Float type, but for the purpose of bitwise equality we can treat them as UInt64
|
||||
StringRef ref = cache.from_column->getDataAt(i);
|
||||
UInt64 key = 0;
|
||||
memcpy(&key, ref.data, ref.size);
|
||||
auto * dst = reinterpret_cast<char *>(&key);
|
||||
const auto ref = cache.from_column->getDataAt(i);
|
||||
if constexpr (std::endian::native == std::endian::big)
|
||||
dst += sizeof(key) - ref.size;
|
||||
|
||||
memcpy(dst, ref.data, ref.size);
|
||||
table[key] = i;
|
||||
}
|
||||
}
|
||||
|
102
src/Functions/tupleConcat.cpp
Normal file
102
src/Functions/tupleConcat.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include <Columns/ColumnTuple.h>
|
||||
#include <DataTypes/DataTypeTuple.h>
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
#include <Functions/IFunction.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
}
|
||||
|
||||
/// tupleConcat(tup1, ...) - concatenate tuples.
|
||||
class FunctionTupleConcat : public IFunction
|
||||
{
|
||||
public:
|
||||
static constexpr auto name = "tupleConcat";
|
||||
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionTupleConcat>(); }
|
||||
|
||||
String getName() const override { return name; }
|
||||
|
||||
bool isVariadic() const override { return true; }
|
||||
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.empty())
|
||||
throw Exception(
|
||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH,
|
||||
"Function {} requires at least one argument.",
|
||||
getName());
|
||||
|
||||
DataTypes tuple_arg_types;
|
||||
|
||||
for (const auto arg_idx : collections::range(0, arguments.size()))
|
||||
{
|
||||
const auto * arg = arguments[arg_idx].get();
|
||||
if (!isTuple(arg))
|
||||
throw Exception(
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of argument {} of function {}",
|
||||
arg->getName(),
|
||||
arg_idx + 1,
|
||||
getName());
|
||||
|
||||
const auto * type = checkAndGetDataType<DataTypeTuple>(arg);
|
||||
for (const auto & elem : type->getElements())
|
||||
tuple_arg_types.push_back(elem);
|
||||
}
|
||||
|
||||
return std::make_shared<DataTypeTuple>(tuple_arg_types);
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t) const override
|
||||
{
|
||||
const size_t num_arguments = arguments.size();
|
||||
Columns columns;
|
||||
|
||||
for (size_t i = 0; i < num_arguments; i++)
|
||||
{
|
||||
const DataTypeTuple * arg_type = checkAndGetDataType<DataTypeTuple>(arguments[i].type.get());
|
||||
|
||||
if (!arg_type)
|
||||
throw Exception(
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||
"Illegal type {} of argument {} of function {}",
|
||||
arguments[i].type->getName(),
|
||||
i + 1,
|
||||
getName());
|
||||
|
||||
ColumnPtr arg_col = arguments[i].column->convertToFullColumnIfConst();
|
||||
const ColumnTuple * tuple_col = checkAndGetColumn<ColumnTuple>(arg_col.get());
|
||||
|
||||
if (!tuple_col)
|
||||
throw Exception(
|
||||
ErrorCodes::ILLEGAL_COLUMN,
|
||||
"Illegal column {} of argument of function {}",
|
||||
arguments[i].column->getName(),
|
||||
getName());
|
||||
|
||||
for (const auto & inner_col : tuple_col->getColumns())
|
||||
columns.push_back(inner_col);
|
||||
}
|
||||
|
||||
return ColumnTuple::create(columns);
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_FUNCTION(TupleConcat)
|
||||
{
|
||||
factory.registerFunction<FunctionTupleConcat>();
|
||||
}
|
||||
|
||||
}
|
@ -23,6 +23,9 @@ struct PlusName { static constexpr auto name = "plus"; };
|
||||
struct MinusName { static constexpr auto name = "minus"; };
|
||||
struct MultiplyName { static constexpr auto name = "multiply"; };
|
||||
struct DivideName { static constexpr auto name = "divide"; };
|
||||
struct ModuloName { static constexpr auto name = "modulo"; };
|
||||
struct IntDivName { static constexpr auto name = "intDiv"; };
|
||||
struct IntDivOrZeroName { static constexpr auto name = "intDivOrZero"; };
|
||||
|
||||
struct L1Label { static constexpr auto name = "1"; };
|
||||
struct L2Label { static constexpr auto name = "2"; };
|
||||
@ -141,6 +144,12 @@ using FunctionTupleMultiply = FunctionTupleOperator<MultiplyName>;
|
||||
|
||||
using FunctionTupleDivide = FunctionTupleOperator<DivideName>;
|
||||
|
||||
using FunctionTupleModulo = FunctionTupleOperator<ModuloName>;
|
||||
|
||||
using FunctionTupleIntDiv = FunctionTupleOperator<IntDivName>;
|
||||
|
||||
using FunctionTupleIntDivOrZero = FunctionTupleOperator<IntDivOrZeroName>;
|
||||
|
||||
class FunctionTupleNegate : public ITupleFunction
|
||||
{
|
||||
public:
|
||||
@ -297,6 +306,12 @@ using FunctionTupleMultiplyByNumber = FunctionTupleOperatorByNumber<MultiplyName
|
||||
|
||||
using FunctionTupleDivideByNumber = FunctionTupleOperatorByNumber<DivideName>;
|
||||
|
||||
using FunctionTupleModuloByNumber = FunctionTupleOperatorByNumber<ModuloName>;
|
||||
|
||||
using FunctionTupleIntDivByNumber = FunctionTupleOperatorByNumber<IntDivName>;
|
||||
|
||||
using FunctionTupleIntDivOrZeroByNumber = FunctionTupleOperatorByNumber<IntDivOrZeroName>;
|
||||
|
||||
class FunctionDotProduct : public ITupleFunction
|
||||
{
|
||||
public:
|
||||
@ -1563,6 +1578,9 @@ REGISTER_FUNCTION(VectorFunctions)
|
||||
factory.registerAlias("vectorDifference", FunctionTupleMinus::name, FunctionFactory::CaseInsensitive);
|
||||
factory.registerFunction<FunctionTupleMultiply>();
|
||||
factory.registerFunction<FunctionTupleDivide>();
|
||||
factory.registerFunction<FunctionTupleModulo>();
|
||||
factory.registerFunction<FunctionTupleIntDiv>();
|
||||
factory.registerFunction<FunctionTupleIntDivOrZero>();
|
||||
factory.registerFunction<FunctionTupleNegate>();
|
||||
|
||||
factory.registerFunction<FunctionAddTupleOfIntervals>(FunctionDocumentation
|
||||
@ -1626,6 +1644,9 @@ If the types of the first interval (or the interval in the tuple) and the second
|
||||
|
||||
factory.registerFunction<FunctionTupleMultiplyByNumber>();
|
||||
factory.registerFunction<FunctionTupleDivideByNumber>();
|
||||
factory.registerFunction<FunctionTupleModuloByNumber>();
|
||||
factory.registerFunction<FunctionTupleIntDivByNumber>();
|
||||
factory.registerFunction<FunctionTupleIntDivOrZeroByNumber>();
|
||||
|
||||
factory.registerFunction<TupleOrArrayFunctionDotProduct>();
|
||||
factory.registerAlias("scalarProduct", TupleOrArrayFunctionDotProduct::name, FunctionFactory::CaseInsensitive);
|
||||
|
@ -14,26 +14,26 @@
|
||||
# include <Common/logger_useful.h>
|
||||
|
||||
# include <IO/S3/PocoHTTPClient.h>
|
||||
# include <IO/S3/PocoHTTPClientFactory.h>
|
||||
# include <IO/S3/Client.h>
|
||||
# include <IO/S3Common.h>
|
||||
|
||||
# include <fstream>
|
||||
# include <base/EnumReflection.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int AWS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
namespace DB::S3
|
||||
namespace S3
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool areCredentialsEmptyOrExpired(const Aws::Auth::AWSCredentials & credentials, uint64_t expiration_window_seconds)
|
||||
{
|
||||
if (credentials.IsEmpty())
|
||||
@ -569,4 +569,6 @@ S3CredentialsProviderChain::S3CredentialsProviderChain(
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -139,7 +139,7 @@ namespace
|
||||
/// For example, to execute
|
||||
/// GRANT ALL ON mydb.* TO role1
|
||||
/// REVOKE ALL ON *.* FROM role1
|
||||
/// the current user needs to have grants only on the 'mydb' database.
|
||||
/// the current user needs to have the grants only on the 'mydb' database.
|
||||
AccessRights all_granted_access;
|
||||
for (const auto & id : grantees_from_query)
|
||||
{
|
||||
|
@ -1005,7 +1005,7 @@ void FileCache::loadMetadata()
|
||||
log,
|
||||
"Cache capacity changed (max size: {}, used: {}), "
|
||||
"cached file `{}` does not fit in cache anymore (size: {})",
|
||||
main_priority->getSizeLimit(), main_priority->getSize(lock), key_directory.string(), size);
|
||||
main_priority->getSizeLimit(), main_priority->getSize(lock), offset_it->path().string(), size);
|
||||
|
||||
fs::remove(offset_it->path());
|
||||
}
|
||||
|
@ -194,9 +194,9 @@ void ClientInfo::setInitialQuery()
|
||||
query_kind = QueryKind::INITIAL_QUERY;
|
||||
fillOSUserHostNameAndVersionInfo();
|
||||
if (client_name.empty())
|
||||
client_name = DBMS_NAME;
|
||||
client_name = VERSION_NAME;
|
||||
else
|
||||
client_name = (DBMS_NAME " ") + client_name;
|
||||
client_name = (VERSION_NAME " ") + client_name;
|
||||
}
|
||||
|
||||
|
||||
@ -210,9 +210,9 @@ void ClientInfo::fillOSUserHostNameAndVersionInfo()
|
||||
|
||||
client_hostname = getFQDNOrHostName();
|
||||
|
||||
client_version_major = DBMS_VERSION_MAJOR;
|
||||
client_version_minor = DBMS_VERSION_MINOR;
|
||||
client_version_patch = DBMS_VERSION_PATCH;
|
||||
client_version_major = VERSION_MAJOR;
|
||||
client_version_minor = VERSION_MINOR;
|
||||
client_version_patch = VERSION_PATCH;
|
||||
client_tcp_protocol_version = DBMS_TCP_PROTOCOL_VERSION;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
explicit ConcurrentHashJoin(ContextPtr context_, std::shared_ptr<TableJoin> table_join_, size_t slots_, const Block & right_sample_block, bool any_take_last_row_ = false);
|
||||
~ConcurrentHashJoin() override = default;
|
||||
|
||||
std::string getName() const override { return "ConcurrentHashJoin"; }
|
||||
const TableJoin & getTableJoin() const override { return *table_join; }
|
||||
bool addBlockToJoin(const Block & block, bool check_limits) override;
|
||||
void checkTypesOfKeys(const Block & block) const override;
|
||||
|
@ -3163,7 +3163,12 @@ void Context::setCluster(const String & cluster_name, const std::shared_ptr<Clus
|
||||
|
||||
void Context::initializeSystemLogs()
|
||||
{
|
||||
/// It is required, because the initialization of system logs can be also
|
||||
/// triggered from another thread, that is launched while initializing the system logs,
|
||||
/// for example, system.filesystem_cache_log will be triggered by parts loading
|
||||
/// of any other table if it is stored on a disk with cache.
|
||||
auto lock = getLock();
|
||||
|
||||
shared->system_logs = std::make_unique<SystemLogs>(getGlobalContext(), getConfigRef());
|
||||
}
|
||||
|
||||
@ -3364,6 +3369,16 @@ std::shared_ptr<AsynchronousInsertLog> Context::getAsynchronousInsertLog() const
|
||||
return shared->system_logs->asynchronous_insert_log;
|
||||
}
|
||||
|
||||
std::vector<ISystemLog *> Context::getSystemLogs() const
|
||||
{
|
||||
auto lock = getLock();
|
||||
|
||||
if (!shared->system_logs)
|
||||
return {};
|
||||
|
||||
return shared->system_logs->logs;
|
||||
}
|
||||
|
||||
CompressionCodecPtr Context::chooseCompressionCodec(size_t part_size, double part_size_ratio) const
|
||||
{
|
||||
auto lock = getLock();
|
||||
|
@ -86,6 +86,7 @@ struct Progress;
|
||||
struct FileProgress;
|
||||
class Clusters;
|
||||
class QueryCache;
|
||||
class ISystemLog;
|
||||
class QueryLog;
|
||||
class QueryThreadLog;
|
||||
class QueryViewsLog;
|
||||
@ -1020,6 +1021,8 @@ public:
|
||||
std::shared_ptr<FilesystemReadPrefetchesLog> getFilesystemReadPrefetchesLog() const;
|
||||
std::shared_ptr<AsynchronousInsertLog> getAsynchronousInsertLog() const;
|
||||
|
||||
std::vector<ISystemLog *> getSystemLogs() const;
|
||||
|
||||
/// Returns an object used to log operations with parts if it possible.
|
||||
/// Provide table name to make required checks.
|
||||
std::shared_ptr<PartLog> getPartLog(const String & part_database) const;
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <string>
|
||||
#include <Interpreters/DatabaseCatalog.h>
|
||||
#include <Interpreters/Context.h>
|
||||
#include <Interpreters/loadMetadata.h>
|
||||
@ -14,6 +15,7 @@
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <Poco/DirectoryIterator.h>
|
||||
#include <Poco/Util/AbstractConfiguration.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/quoteString.h>
|
||||
#include <Common/atomicRename.h>
|
||||
#include <Common/CurrentMetrics.h>
|
||||
@ -23,6 +25,7 @@
|
||||
#include <Common/noexcept_scope.h>
|
||||
#include <Common/checkStackSize.h>
|
||||
|
||||
#include "Interpreters/Context_fwd.h"
|
||||
#include "config.h"
|
||||
|
||||
#if USE_MYSQL
|
||||
@ -35,7 +38,6 @@
|
||||
# include <Storages/PostgreSQL/StorageMaterializedPostgreSQL.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace CurrentMetrics
|
||||
{
|
||||
extern const Metric TablesToDropQueueSize;
|
||||
@ -59,6 +61,29 @@ namespace ErrorCodes
|
||||
extern const int UNFINISHED;
|
||||
}
|
||||
|
||||
class DatabaseNameHints : public IHints<1, DatabaseNameHints>
|
||||
{
|
||||
public:
|
||||
explicit DatabaseNameHints(const DatabaseCatalog & database_catalog_)
|
||||
: database_catalog(database_catalog_)
|
||||
{
|
||||
}
|
||||
Names getAllRegisteredNames() const override
|
||||
{
|
||||
Names result;
|
||||
auto databases_list = database_catalog.getDatabases();
|
||||
for (const auto & database_name : databases_list | boost::adaptors::map_keys)
|
||||
{
|
||||
if (database_name == DatabaseCatalog::TEMPORARY_DATABASE)
|
||||
continue;
|
||||
result.emplace_back(database_name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
const DatabaseCatalog & database_catalog;
|
||||
};
|
||||
|
||||
TemporaryTableHolder::TemporaryTableHolder(ContextPtr context_, const TemporaryTableHolder::Creator & creator, const ASTPtr & query)
|
||||
: WithContext(context_->getGlobalContext())
|
||||
, temporary_tables(DatabaseCatalog::instance().getDatabaseForTemporaryTables().get())
|
||||
@ -313,7 +338,18 @@ DatabaseAndTable DatabaseCatalog::getTableImpl(
|
||||
{
|
||||
assert(!db_and_table.first && !db_and_table.second);
|
||||
if (exception)
|
||||
exception->emplace(Exception(ErrorCodes::UNKNOWN_TABLE, "Table {} doesn't exist", table_id.getNameForLogs()));
|
||||
{
|
||||
TableNameHints hints(this->tryGetDatabase(table_id.getDatabaseName()), getContext());
|
||||
std::vector<String> names = hints.getHints(table_id.getTableName());
|
||||
if (!names.empty())
|
||||
{
|
||||
/// There is two options: first is to print just the name of the table
|
||||
/// and the second is to print the result in format: db_name.table_name. I'll comment out the second option below
|
||||
/// I also leave possibility to print several suggestions
|
||||
exception->emplace(Exception(ErrorCodes::UNKNOWN_TABLE, "Table {} does not exist. Maybe you meant {}?", table_id.getNameForLogs(), backQuoteIfNeed(names[0])));
|
||||
}
|
||||
else exception->emplace(Exception(ErrorCodes::UNKNOWN_TABLE, "Table {} does not exist", table_id.getNameForLogs()));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -359,13 +395,26 @@ DatabaseAndTable DatabaseCatalog::getTableImpl(
|
||||
|
||||
std::lock_guard lock{databases_mutex};
|
||||
auto it = databases.find(table_id.getDatabaseName());
|
||||
if (databases.end() == it)
|
||||
if (databases.end() != it)
|
||||
database = it->second;
|
||||
}
|
||||
|
||||
if (!database)
|
||||
{
|
||||
if (exception)
|
||||
exception->emplace(Exception(ErrorCodes::UNKNOWN_DATABASE, "Database {} doesn't exist", backQuoteIfNeed(table_id.getDatabaseName())));
|
||||
return {};
|
||||
{
|
||||
DatabaseNameHints hints(*this);
|
||||
std::vector<String> names = hints.getHints(table_id.getDatabaseName());
|
||||
if (names.empty())
|
||||
{
|
||||
exception->emplace(Exception(ErrorCodes::UNKNOWN_DATABASE, "Database {} does not exist", backQuoteIfNeed(table_id.getDatabaseName())));
|
||||
}
|
||||
database = it->second;
|
||||
else
|
||||
{
|
||||
exception->emplace(Exception(ErrorCodes::UNKNOWN_DATABASE, "Database {} does not exist. Maybe you meant {}?", backQuoteIfNeed(table_id.getDatabaseName()), backQuoteIfNeed(names[0])));
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
StoragePtr table;
|
||||
@ -386,8 +435,18 @@ DatabaseAndTable DatabaseCatalog::getTableImpl(
|
||||
}
|
||||
|
||||
if (!table && exception && !exception->has_value())
|
||||
exception->emplace(Exception(ErrorCodes::UNKNOWN_TABLE, "Table {} doesn't exist", table_id.getNameForLogs()));
|
||||
|
||||
{
|
||||
TableNameHints hints(this->tryGetDatabase(table_id.getDatabaseName()), getContext());
|
||||
std::vector<String> names = hints.getHints(table_id.getTableName());
|
||||
if (names.empty())
|
||||
{
|
||||
exception->emplace(Exception(ErrorCodes::UNKNOWN_TABLE, "Table {} does not exist", table_id.getNameForLogs()));
|
||||
}
|
||||
else
|
||||
{
|
||||
exception->emplace(Exception(ErrorCodes::UNKNOWN_TABLE, "Table {} does not exist. Maybe you meant {}?", table_id.getNameForLogs(), backQuoteIfNeed(names[0])));
|
||||
}
|
||||
}
|
||||
if (!table)
|
||||
database = nullptr;
|
||||
|
||||
@ -438,8 +497,26 @@ bool DatabaseCatalog::isPredefinedTable(const StorageID & table_id) const
|
||||
|
||||
void DatabaseCatalog::assertDatabaseExists(const String & database_name) const
|
||||
{
|
||||
DatabasePtr db;
|
||||
{
|
||||
std::lock_guard lock{databases_mutex};
|
||||
assertDatabaseExistsUnlocked(database_name);
|
||||
assert(!database_name.empty());
|
||||
if (auto it = databases.find(database_name); it != databases.end())
|
||||
db = it->second;
|
||||
}
|
||||
if (!db)
|
||||
{
|
||||
DatabaseNameHints hints(*this);
|
||||
std::vector<String> names = hints.getHints(database_name);
|
||||
if (names.empty())
|
||||
{
|
||||
throw Exception(ErrorCodes::UNKNOWN_DATABASE, "Database {} does not exist", backQuoteIfNeed(database_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception(ErrorCodes::UNKNOWN_DATABASE, "Database {} does not exist. Maybe you meant {}?", backQuoteIfNeed(database_name), backQuoteIfNeed(names[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseCatalog::assertDatabaseDoesntExist(const String & database_name) const
|
||||
@ -448,19 +525,11 @@ void DatabaseCatalog::assertDatabaseDoesntExist(const String & database_name) co
|
||||
assertDatabaseDoesntExistUnlocked(database_name);
|
||||
}
|
||||
|
||||
void DatabaseCatalog::assertDatabaseExistsUnlocked(const String & database_name) const
|
||||
{
|
||||
assert(!database_name.empty());
|
||||
if (databases.end() == databases.find(database_name))
|
||||
throw Exception(ErrorCodes::UNKNOWN_DATABASE, "Database {} doesn't exist", backQuoteIfNeed(database_name));
|
||||
}
|
||||
|
||||
|
||||
void DatabaseCatalog::assertDatabaseDoesntExistUnlocked(const String & database_name) const
|
||||
{
|
||||
assert(!database_name.empty());
|
||||
if (databases.end() != databases.find(database_name))
|
||||
throw Exception(ErrorCodes::DATABASE_ALREADY_EXISTS, "Database {} already exists.", backQuoteIfNeed(database_name));
|
||||
throw Exception(ErrorCodes::DATABASE_ALREADY_EXISTS, "Database {} already exists", backQuoteIfNeed(database_name));
|
||||
}
|
||||
|
||||
void DatabaseCatalog::attachDatabase(const String & database_name, const DatabasePtr & database)
|
||||
@ -480,18 +549,34 @@ DatabasePtr DatabaseCatalog::detachDatabase(ContextPtr local_context, const Stri
|
||||
{
|
||||
if (database_name == TEMPORARY_DATABASE)
|
||||
throw Exception(ErrorCodes::DATABASE_ACCESS_DENIED, "Cannot detach database with temporary tables.");
|
||||
|
||||
assert(!database_name.empty());
|
||||
DatabasePtr db;
|
||||
{
|
||||
std::lock_guard lock{databases_mutex};
|
||||
assertDatabaseExistsUnlocked(database_name);
|
||||
db = databases.find(database_name)->second;
|
||||
if (auto it = databases.find(database_name); it != databases.end())
|
||||
{
|
||||
db = it->second;
|
||||
|
||||
UUID db_uuid = db->getUUID();
|
||||
if (db_uuid != UUIDHelpers::Nil)
|
||||
removeUUIDMapping(db_uuid);
|
||||
databases.erase(database_name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (!db)
|
||||
{
|
||||
DatabaseNameHints hints(*this);
|
||||
std::vector<String> names = hints.getHints(database_name);
|
||||
if (names.empty())
|
||||
{
|
||||
throw Exception(ErrorCodes::UNKNOWN_DATABASE, "Database {} does not exist", backQuoteIfNeed(database_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception(ErrorCodes::UNKNOWN_DATABASE, "Database {} does not exist. Maybe you meant {}?", backQuoteIfNeed(database_name), backQuoteIfNeed(names[0]));
|
||||
}
|
||||
}
|
||||
if (check_empty)
|
||||
{
|
||||
try
|
||||
@ -527,7 +612,6 @@ DatabasePtr DatabaseCatalog::detachDatabase(ContextPtr local_context, const Stri
|
||||
if (db_uuid != UUIDHelpers::Nil)
|
||||
removeUUIDMappingFinally(db_uuid);
|
||||
}
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
@ -553,9 +637,28 @@ void DatabaseCatalog::updateDatabaseName(const String & old_name, const String &
|
||||
|
||||
DatabasePtr DatabaseCatalog::getDatabase(const String & database_name) const
|
||||
{
|
||||
assert(!database_name.empty());
|
||||
DatabasePtr db;
|
||||
{
|
||||
std::lock_guard lock{databases_mutex};
|
||||
assertDatabaseExistsUnlocked(database_name);
|
||||
return databases.find(database_name)->second;
|
||||
if (auto it = databases.find(database_name); it != databases.end())
|
||||
db = it->second;
|
||||
}
|
||||
|
||||
if (!db)
|
||||
{
|
||||
DatabaseNameHints hints(*this);
|
||||
std::vector<String> names = hints.getHints(database_name);
|
||||
if (names.empty())
|
||||
{
|
||||
throw Exception(ErrorCodes::UNKNOWN_DATABASE, "Database {} does not exist", backQuoteIfNeed(database_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception(ErrorCodes::UNKNOWN_DATABASE, "Database {} does not exist. Maybe you meant {}?", backQuoteIfNeed(database_name), backQuoteIfNeed(names[0]));
|
||||
}
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
DatabasePtr DatabaseCatalog::tryGetDatabase(const String & database_name) const
|
||||
|
@ -6,7 +6,10 @@
|
||||
#include <Databases/TablesDependencyGraph.h>
|
||||
#include <Parsers/IAST_fwd.h>
|
||||
#include <Storages/IStorage_fwd.h>
|
||||
#include "Common/NamePrompter.h"
|
||||
#include <Common/SharedMutex.h>
|
||||
#include "Storages/IStorage.h"
|
||||
#include "Databases/IDatabase.h"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <Poco/Logger.h>
|
||||
@ -27,6 +30,32 @@ namespace fs = std::filesystem;
|
||||
namespace DB
|
||||
{
|
||||
|
||||
class TableNameHints : public IHints<1, TableNameHints>
|
||||
{
|
||||
public:
|
||||
TableNameHints(ConstDatabasePtr database_, ContextPtr context_)
|
||||
: context(context_),
|
||||
database(database_)
|
||||
{
|
||||
}
|
||||
Names getAllRegisteredNames() const override
|
||||
{
|
||||
Names result;
|
||||
if (database)
|
||||
{
|
||||
for (auto table_it = database->getTablesIterator(context); table_it->isValid(); table_it->next())
|
||||
{
|
||||
const auto & storage_id = table_it->table()->getStorageID();
|
||||
result.emplace_back(storage_id.getTableName());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
ContextPtr context;
|
||||
ConstDatabasePtr database;
|
||||
};
|
||||
|
||||
class IDatabase;
|
||||
class Exception;
|
||||
class ColumnsDescription;
|
||||
@ -262,7 +291,6 @@ private:
|
||||
static std::unique_ptr<DatabaseCatalog> database_catalog;
|
||||
|
||||
explicit DatabaseCatalog(ContextMutablePtr global_context_);
|
||||
void assertDatabaseExistsUnlocked(const String & database_name) const TSA_REQUIRES(databases_mutex);
|
||||
void assertDatabaseDoesntExistUnlocked(const String & database_name) const TSA_REQUIRES(databases_mutex);
|
||||
|
||||
void shutdownImpl();
|
||||
|
@ -30,6 +30,7 @@ public:
|
||||
std::shared_ptr<const IKeyValueEntity> storage_,
|
||||
const Block & right_sample_block_with_storage_column_names_);
|
||||
|
||||
std::string getName() const override { return "DirectKeyValueJoin"; }
|
||||
virtual const TableJoin & getTableJoin() const override { return *table_join; }
|
||||
|
||||
virtual bool addBlockToJoin(const Block &, bool) override;
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
LOG_TRACE(&Poco::Logger::get("FullSortingMergeJoin"), "Will use full sorting merge join");
|
||||
}
|
||||
|
||||
std::string getName() const override { return "FullSortingMergeJoin"; }
|
||||
const TableJoin & getTableJoin() const override { return *table_join; }
|
||||
|
||||
bool addBlockToJoin(const Block & /* block */, bool /* check_limits */) override
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
|
||||
~GraceHashJoin() override;
|
||||
|
||||
std::string getName() const override { return "GraceHashJoin"; }
|
||||
const TableJoin & getTableJoin() const override { return *table_join; }
|
||||
|
||||
void initialize(const Block & sample_block) override;
|
||||
|
@ -151,6 +151,7 @@ public:
|
||||
|
||||
~HashJoin() override;
|
||||
|
||||
std::string getName() const override { return "HashJoin"; }
|
||||
const TableJoin & getTableJoin() const override { return *table_join; }
|
||||
|
||||
/** Add block of data from right hand of JOIN to the map.
|
||||
|
@ -48,6 +48,8 @@ class IJoin
|
||||
public:
|
||||
virtual ~IJoin() = default;
|
||||
|
||||
virtual std::string getName() const = 0;
|
||||
|
||||
virtual const TableJoin & getTableJoin() const = 0;
|
||||
|
||||
/// Add block of data from right hand of JOIN.
|
||||
|
@ -295,7 +295,7 @@ BlockIO InterpreterKillQueryQuery::execute()
|
||||
|
||||
if (res_columns[0]->empty() && access_denied)
|
||||
throw Exception(ErrorCodes::ACCESS_DENIED, "Not allowed to kill mutation. "
|
||||
"To execute this query it's necessary to have the grant {}", required_access_rights.toString());
|
||||
"To execute this query, it's necessary to have the grant {}", required_access_rights.toString());
|
||||
|
||||
res_io.pipeline = QueryPipeline(Pipe(std::make_shared<SourceFromSingleChunk>(header.cloneWithColumns(std::move(res_columns)))));
|
||||
|
||||
@ -359,7 +359,7 @@ BlockIO InterpreterKillQueryQuery::execute()
|
||||
|
||||
if (res_columns[0]->empty() && access_denied)
|
||||
throw Exception(ErrorCodes::ACCESS_DENIED, "Not allowed to kill move partition. "
|
||||
"To execute this query it's necessary to have the grant {}", required_access_rights.toString());
|
||||
"To execute this query, it's necessary to have the grant {}", required_access_rights.toString());
|
||||
|
||||
res_io.pipeline = QueryPipeline(Pipe(std::make_shared<SourceFromSingleChunk>(header.cloneWithColumns(std::move(res_columns)))));
|
||||
|
||||
|
@ -10,7 +10,7 @@ namespace DB
|
||||
class AccessRightsElements;
|
||||
class DDLGuard;
|
||||
|
||||
/// To avoid deadlocks, we must acquire locks for tables in same order in any different RENAMES.
|
||||
/// To avoid deadlocks, we must acquire locks for tables in same order in any different RENAMEs.
|
||||
struct UniqueTableName
|
||||
{
|
||||
String database_name;
|
||||
|
@ -299,7 +299,7 @@ void checkAccessRightsForSelect(
|
||||
}
|
||||
throw Exception(
|
||||
ErrorCodes::ACCESS_DENIED,
|
||||
"{}: Not enough privileges. To execute this query it's necessary to have grant SELECT for at least one column on {}",
|
||||
"{}: Not enough privileges. To execute this query, it's necessary to have the grant SELECT for at least one column on {}",
|
||||
context->getUserName(),
|
||||
table_id.getFullTableName());
|
||||
}
|
||||
|
@ -103,40 +103,34 @@ namespace ActionLocks
|
||||
namespace
|
||||
{
|
||||
|
||||
ExecutionStatus getOverallExecutionStatusOfCommands()
|
||||
/// Sequentially tries to execute all commands and throws exception with info about failed commands
|
||||
void executeCommandsAndThrowIfError(std::vector<std::function<void()>> commands)
|
||||
{
|
||||
return ExecutionStatus(0);
|
||||
}
|
||||
|
||||
/// Consequently tries to execute all commands and generates final exception message for failed commands
|
||||
template <typename Callable, typename ... Callables>
|
||||
ExecutionStatus getOverallExecutionStatusOfCommands(Callable && command, Callables && ... commands)
|
||||
{
|
||||
ExecutionStatus status_head(0);
|
||||
ExecutionStatus result(0);
|
||||
for (auto & command : commands)
|
||||
{
|
||||
try
|
||||
{
|
||||
command();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
status_head = ExecutionStatus::fromCurrentException();
|
||||
ExecutionStatus current_result = ExecutionStatus::fromCurrentException();
|
||||
|
||||
if (result.code == 0)
|
||||
result.code = current_result.code;
|
||||
|
||||
if (!current_result.message.empty())
|
||||
{
|
||||
if (!result.message.empty())
|
||||
result.message += '\n';
|
||||
result.message += current_result.message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExecutionStatus status_tail = getOverallExecutionStatusOfCommands(std::forward<Callables>(commands)...);
|
||||
|
||||
auto res_status = status_head.code != 0 ? status_head.code : status_tail.code;
|
||||
auto res_message = status_head.message + (status_tail.message.empty() ? "" : ("\n" + status_tail.message));
|
||||
|
||||
return ExecutionStatus(res_status, res_message);
|
||||
}
|
||||
|
||||
/// Consequently tries to execute all commands and throws exception with info about failed commands
|
||||
template <typename ... Callables>
|
||||
void executeCommandsAndThrowIfError(Callables && ... commands)
|
||||
{
|
||||
auto status = getOverallExecutionStatusOfCommands(std::forward<Callables>(commands)...);
|
||||
if (status.code != 0)
|
||||
throw Exception::createDeprecated(status.message, status.code);
|
||||
if (result.code != 0)
|
||||
throw Exception::createDeprecated(result.message, result.code);
|
||||
}
|
||||
|
||||
|
||||
@ -425,10 +419,10 @@ BlockIO InterpreterSystemQuery::execute()
|
||||
case Type::RELOAD_DICTIONARIES:
|
||||
{
|
||||
getContext()->checkAccess(AccessType::SYSTEM_RELOAD_DICTIONARY);
|
||||
executeCommandsAndThrowIfError(
|
||||
executeCommandsAndThrowIfError({
|
||||
[&] { system_context->getExternalDictionariesLoader().reloadAllTriedToLoad(); },
|
||||
[&] { system_context->getEmbeddedDictionaries().reload(); }
|
||||
);
|
||||
});
|
||||
ExternalDictionariesLoader::resetAll();
|
||||
break;
|
||||
}
|
||||
@ -557,23 +551,14 @@ BlockIO InterpreterSystemQuery::execute()
|
||||
case Type::FLUSH_LOGS:
|
||||
{
|
||||
getContext()->checkAccess(AccessType::SYSTEM_FLUSH_LOGS);
|
||||
executeCommandsAndThrowIfError(
|
||||
[&] { if (auto query_log = getContext()->getQueryLog()) query_log->flush(true); },
|
||||
[&] { if (auto part_log = getContext()->getPartLog("")) part_log->flush(true); },
|
||||
[&] { if (auto query_thread_log = getContext()->getQueryThreadLog()) query_thread_log->flush(true); },
|
||||
[&] { if (auto trace_log = getContext()->getTraceLog()) trace_log->flush(true); },
|
||||
[&] { if (auto text_log = getContext()->getTextLog()) text_log->flush(true); },
|
||||
[&] { if (auto metric_log = getContext()->getMetricLog()) metric_log->flush(true); },
|
||||
[&] { if (auto asynchronous_metric_log = getContext()->getAsynchronousMetricLog()) asynchronous_metric_log->flush(true); },
|
||||
[&] { if (auto opentelemetry_span_log = getContext()->getOpenTelemetrySpanLog()) opentelemetry_span_log->flush(true); },
|
||||
[&] { if (auto query_views_log = getContext()->getQueryViewsLog()) query_views_log->flush(true); },
|
||||
[&] { if (auto zookeeper_log = getContext()->getZooKeeperLog()) zookeeper_log->flush(true); },
|
||||
[&] { if (auto session_log = getContext()->getSessionLog()) session_log->flush(true); },
|
||||
[&] { if (auto transactions_info_log = getContext()->getTransactionsInfoLog()) transactions_info_log->flush(true); },
|
||||
[&] { if (auto processors_profile_log = getContext()->getProcessorsProfileLog()) processors_profile_log->flush(true); },
|
||||
[&] { if (auto cache_log = getContext()->getFilesystemCacheLog()) cache_log->flush(true); },
|
||||
[&] { if (auto asynchronous_insert_log = getContext()->getAsynchronousInsertLog()) asynchronous_insert_log->flush(true); }
|
||||
);
|
||||
|
||||
auto logs = getContext()->getSystemLogs();
|
||||
std::vector<std::function<void()>> commands;
|
||||
commands.reserve(logs.size());
|
||||
for (auto * system_log : logs)
|
||||
commands.emplace_back([system_log] { system_log->flush(true); });
|
||||
|
||||
executeCommandsAndThrowIfError(commands);
|
||||
break;
|
||||
}
|
||||
case Type::STOP_LISTEN:
|
||||
|
@ -18,6 +18,7 @@ class JoinSwitcher : public IJoin
|
||||
public:
|
||||
JoinSwitcher(std::shared_ptr<TableJoin> table_join_, const Block & right_sample_block_);
|
||||
|
||||
std::string getName() const override { return "JoinSwitcher"; }
|
||||
const TableJoin & getTableJoin() const override { return *table_join; }
|
||||
|
||||
/// Add block of data from right hand of JOIN into current join object.
|
||||
|
@ -22,6 +22,7 @@ class MergeJoin : public IJoin
|
||||
public:
|
||||
MergeJoin(std::shared_ptr<TableJoin> table_join_, const Block & right_sample_block);
|
||||
|
||||
std::string getName() const override { return "PartialMergeJoin"; }
|
||||
const TableJoin & getTableJoin() const override { return *table_join; }
|
||||
bool addBlockToJoin(const Block & block, bool check_limits) override;
|
||||
void checkTypesOfKeys(const Block & block) const override;
|
||||
|
@ -113,13 +113,14 @@ QueryTreeNodePtr prepareQueryAffectedQueryTree(const std::vector<MutationCommand
|
||||
ColumnDependencies getAllColumnDependencies(
|
||||
const StorageMetadataPtr & metadata_snapshot,
|
||||
const NameSet & updated_columns,
|
||||
const std::function<bool(const String & file_name)> & has_index_or_projection)
|
||||
const StorageInMemoryMetadata::HasDependencyCallback & has_dependency)
|
||||
{
|
||||
NameSet new_updated_columns = updated_columns;
|
||||
ColumnDependencies dependencies;
|
||||
|
||||
while (!new_updated_columns.empty())
|
||||
{
|
||||
auto new_dependencies = metadata_snapshot->getColumnDependencies(new_updated_columns, true, has_index_or_projection);
|
||||
auto new_dependencies = metadata_snapshot->getColumnDependencies(new_updated_columns, true, has_dependency);
|
||||
new_updated_columns.clear();
|
||||
for (const auto & dependency : new_dependencies)
|
||||
{
|
||||
@ -292,9 +293,14 @@ bool MutationsInterpreter::Source::materializeTTLRecalculateOnly() const
|
||||
return data && data->getSettings()->materialize_ttl_recalculate_only;
|
||||
}
|
||||
|
||||
bool MutationsInterpreter::Source::hasIndexOrProjection(const String & file_name) const
|
||||
bool MutationsInterpreter::Source::hasSecondaryIndex(const String & name) const
|
||||
{
|
||||
return part && part->checksums.has(file_name);
|
||||
return part && part->hasSecondaryIndex(name);
|
||||
}
|
||||
|
||||
bool MutationsInterpreter::Source::hasProjection(const String & name) const
|
||||
{
|
||||
return part && part->hasProjection(name);
|
||||
}
|
||||
|
||||
static Names getAvailableColumnsWithVirtuals(StorageMetadataPtr metadata_snapshot, const IStorage & storage)
|
||||
@ -533,13 +539,24 @@ void MutationsInterpreter::prepare(bool dry_run)
|
||||
validateUpdateColumns(source, metadata_snapshot, updated_columns, column_to_affected_materialized);
|
||||
}
|
||||
|
||||
std::function<bool(const String & file_name)> has_index_or_projection
|
||||
= [&](const String & file_name) { return source.hasIndexOrProjection(file_name); };
|
||||
StorageInMemoryMetadata::HasDependencyCallback has_dependency =
|
||||
[&](const String & name, ColumnDependency::Kind kind)
|
||||
{
|
||||
if (kind == ColumnDependency::PROJECTION)
|
||||
return source.hasProjection(name);
|
||||
|
||||
if (kind == ColumnDependency::SKIP_INDEX)
|
||||
return source.hasSecondaryIndex(name);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
if (settings.recalculate_dependencies_of_updated_columns)
|
||||
dependencies = getAllColumnDependencies(metadata_snapshot, updated_columns, has_index_or_projection);
|
||||
dependencies = getAllColumnDependencies(metadata_snapshot, updated_columns, has_dependency);
|
||||
|
||||
bool has_alter_delete = false;
|
||||
std::vector<String> read_columns;
|
||||
|
||||
/// First, break a sequence of commands into stages.
|
||||
for (auto & command : commands)
|
||||
{
|
||||
@ -558,6 +575,7 @@ void MutationsInterpreter::prepare(bool dry_run)
|
||||
predicate = makeASTFunction("isZeroOrNull", predicate);
|
||||
|
||||
stages.back().filters.push_back(predicate);
|
||||
has_alter_delete = true;
|
||||
}
|
||||
else if (command.type == MutationCommand::UPDATE)
|
||||
{
|
||||
@ -692,8 +710,7 @@ void MutationsInterpreter::prepare(bool dry_run)
|
||||
if (it == std::cend(indices_desc))
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown index: {}", command.index_name);
|
||||
|
||||
if (!source.hasIndexOrProjection("skp_idx_" + it->name + ".idx")
|
||||
&& !source.hasIndexOrProjection("skp_idx_" + it->name + ".idx2"))
|
||||
if (!source.hasSecondaryIndex(it->name))
|
||||
{
|
||||
auto query = (*it).expression_list_ast->clone();
|
||||
auto syntax_result = TreeRewriter(context).analyze(query, all_columns);
|
||||
@ -707,7 +724,7 @@ void MutationsInterpreter::prepare(bool dry_run)
|
||||
{
|
||||
mutation_kind.set(MutationKind::MUTATE_INDEX_PROJECTION);
|
||||
const auto & projection = projections_desc.get(command.projection_name);
|
||||
if (!source.hasIndexOrProjection(projection.getDirectoryName()))
|
||||
if (!source.hasProjection(projection.name))
|
||||
{
|
||||
for (const auto & column : projection.required_columns)
|
||||
dependencies.emplace(column, ColumnDependency::PROJECTION);
|
||||
@ -731,8 +748,9 @@ void MutationsInterpreter::prepare(bool dry_run)
|
||||
{
|
||||
// just recalculate ttl_infos without remove expired data
|
||||
auto all_columns_vec = all_columns.getNames();
|
||||
auto new_dependencies = metadata_snapshot->getColumnDependencies(
|
||||
NameSet(all_columns_vec.begin(), all_columns_vec.end()), false, has_index_or_projection);
|
||||
auto all_columns_set = NameSet(all_columns_vec.begin(), all_columns_vec.end());
|
||||
auto new_dependencies = metadata_snapshot->getColumnDependencies(all_columns_set, false, has_dependency);
|
||||
|
||||
for (const auto & dependency : new_dependencies)
|
||||
{
|
||||
if (dependency.kind == ColumnDependency::TTL_EXPRESSION)
|
||||
@ -757,8 +775,8 @@ void MutationsInterpreter::prepare(bool dry_run)
|
||||
}
|
||||
|
||||
auto all_columns_vec = all_columns.getNames();
|
||||
auto all_dependencies = getAllColumnDependencies(
|
||||
metadata_snapshot, NameSet(all_columns_vec.begin(), all_columns_vec.end()), has_index_or_projection);
|
||||
auto all_columns_set = NameSet(all_columns_vec.begin(), all_columns_vec.end());
|
||||
auto all_dependencies = getAllColumnDependencies(metadata_snapshot, all_columns_set, has_dependency);
|
||||
|
||||
for (const auto & dependency : all_dependencies)
|
||||
{
|
||||
@ -767,7 +785,7 @@ void MutationsInterpreter::prepare(bool dry_run)
|
||||
}
|
||||
|
||||
/// Recalc only skip indices and projections of columns which could be updated by TTL.
|
||||
auto new_dependencies = metadata_snapshot->getColumnDependencies(new_updated_columns, true, has_index_or_projection);
|
||||
auto new_dependencies = metadata_snapshot->getColumnDependencies(new_updated_columns, true, has_dependency);
|
||||
for (const auto & dependency : new_dependencies)
|
||||
{
|
||||
if (dependency.kind == ColumnDependency::SKIP_INDEX || dependency.kind == ColumnDependency::PROJECTION)
|
||||
@ -861,31 +879,45 @@ void MutationsInterpreter::prepare(bool dry_run)
|
||||
|
||||
for (const auto & index : metadata_snapshot->getSecondaryIndices())
|
||||
{
|
||||
if (source.hasIndexOrProjection("skp_idx_" + index.name + ".idx") || source.hasIndexOrProjection("skp_idx_" + index.name + ".idx2"))
|
||||
if (!source.hasSecondaryIndex(index.name))
|
||||
continue;
|
||||
|
||||
if (has_alter_delete)
|
||||
{
|
||||
materialized_indices.insert(index.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto & index_cols = index.expression->getRequiredColumns();
|
||||
bool changed = std::any_of(
|
||||
index_cols.begin(),
|
||||
index_cols.end(),
|
||||
[&](const auto & col) { return updated_columns.contains(col) || changed_columns.contains(col); });
|
||||
|
||||
if (changed)
|
||||
materialized_indices.insert(index.name);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto & projection : metadata_snapshot->getProjections())
|
||||
{
|
||||
if (source.hasIndexOrProjection(projection.getDirectoryName()))
|
||||
if (!source.hasProjection(projection.name))
|
||||
continue;
|
||||
|
||||
if (has_alter_delete)
|
||||
{
|
||||
materialized_projections.insert(projection.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto & projection_cols = projection.required_columns;
|
||||
bool changed = std::any_of(
|
||||
projection_cols.begin(),
|
||||
projection_cols.end(),
|
||||
[&](const auto & col) { return updated_columns.contains(col) || changed_columns.contains(col); });
|
||||
|
||||
if (changed)
|
||||
materialized_projections.insert(projection.name);
|
||||
}
|
||||
}
|
||||
|
||||
/// Stages might be empty when we materialize skip indices or projections which don't add any
|
||||
/// column dependencies.
|
||||
|
@ -120,7 +120,8 @@ public:
|
||||
bool supportsLightweightDelete() const;
|
||||
bool hasLightweightDeleteMask() const;
|
||||
bool materializeTTLRecalculateOnly() const;
|
||||
bool hasIndexOrProjection(const String & file_name) const;
|
||||
bool hasSecondaryIndex(const String & name) const;
|
||||
bool hasProjection(const String & name) const;
|
||||
|
||||
void read(
|
||||
Stage & first_stage,
|
||||
|
@ -129,6 +129,7 @@ std::shared_ptr<TSystemLog> createSystemLog(
|
||||
"Creating {}.{} from {}", default_database_name, default_table_name, config_prefix);
|
||||
|
||||
SystemLogSettings log_settings;
|
||||
|
||||
log_settings.queue_settings.database = config.getString(config_prefix + ".database", default_database_name);
|
||||
log_settings.queue_settings.table = config.getString(config_prefix + ".table", default_table_name);
|
||||
|
||||
|
@ -330,7 +330,7 @@ public:
|
||||
const ColumnsWithTypeAndName & right_sample_columns);
|
||||
|
||||
void setAsofInequality(ASOFJoinInequality inequality) { asof_inequality = inequality; }
|
||||
ASOFJoinInequality getAsofInequality() { return asof_inequality; }
|
||||
ASOFJoinInequality getAsofInequality() const { return asof_inequality; }
|
||||
|
||||
ASTPtr leftKeysList() const;
|
||||
ASTPtr rightKeysList() const; /// For ON syntax only
|
||||
|
@ -4,7 +4,7 @@ clickhouse_add_executable(lexer lexer.cpp ${SRCS})
|
||||
target_link_libraries(lexer PRIVATE clickhouse_parsers)
|
||||
|
||||
clickhouse_add_executable(select_parser select_parser.cpp ${SRCS} "../../Server/ServerType.cpp")
|
||||
target_link_libraries(select_parser PRIVATE clickhouse_parsers)
|
||||
target_link_libraries(select_parser PRIVATE dbms)
|
||||
|
||||
clickhouse_add_executable(create_parser create_parser.cpp ${SRCS} "../../Server/ServerType.cpp")
|
||||
target_link_libraries(create_parser PRIVATE clickhouse_parsers)
|
||||
target_link_libraries(create_parser PRIVATE dbms)
|
||||
|
@ -101,7 +101,7 @@ void checkAccessRights(const TableNode & table_node, const Names & column_names,
|
||||
}
|
||||
|
||||
throw Exception(ErrorCodes::ACCESS_DENIED,
|
||||
"{}: Not enough privileges. To execute this query it's necessary to have grant SELECT for at least one column on {}",
|
||||
"{}: Not enough privileges. To execute this query, it's necessary to have the grant SELECT for at least one column on {}",
|
||||
query_context->getUserName(),
|
||||
storage_id.getFullTableName());
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ std::unique_ptr<QueryPlan> createLocalPlan(
|
||||
new_context->setClientInterface(ClientInfo::Interface::LOCAL);
|
||||
new_context->setQueryKind(ClientInfo::QueryKind::SECONDARY_QUERY);
|
||||
new_context->setReplicaInfo(true, replica_count, replica_num);
|
||||
new_context->setConnectionClientVersion(DBMS_VERSION_MAJOR, DBMS_VERSION_MINOR, DBMS_VERSION_PATCH, DBMS_TCP_PROTOCOL_VERSION);
|
||||
new_context->setConnectionClientVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, DBMS_TCP_PROTOCOL_VERSION);
|
||||
new_context->setParallelReplicasGroupUUID(group_uuid);
|
||||
new_context->setMergeTreeAllRangesCallback([coordinator](InitialAllRangesAnnouncement announcement)
|
||||
{
|
||||
|
@ -2,6 +2,9 @@
|
||||
#include <QueryPipeline/QueryPipelineBuilder.h>
|
||||
#include <Processors/Transforms/JoiningTransform.h>
|
||||
#include <Interpreters/IJoin.h>
|
||||
#include <Interpreters/TableJoin.h>
|
||||
#include <IO/Operators.h>
|
||||
#include <Common/JSONBuilder.h>
|
||||
#include <Common/typeid_cast.h>
|
||||
|
||||
namespace DB
|
||||
@ -62,6 +65,36 @@ void JoinStep::describePipeline(FormatSettings & settings) const
|
||||
IQueryPlanStep::describePipeline(processors, settings);
|
||||
}
|
||||
|
||||
void JoinStep::describeActions(FormatSettings & settings) const
|
||||
{
|
||||
String prefix(settings.offset, ' ');
|
||||
|
||||
const auto & table_join = join->getTableJoin();
|
||||
settings.out << prefix << "Type: " << toString(table_join.kind()) << '\n';
|
||||
settings.out << prefix << "Strictness: " << toString(table_join.strictness()) << '\n';
|
||||
settings.out << prefix << "Algorithm: " << join->getName() << '\n';
|
||||
|
||||
if (table_join.strictness() == JoinStrictness::Asof)
|
||||
settings.out << prefix << "ASOF inequality: " << toString(table_join.getAsofInequality()) << '\n';
|
||||
|
||||
if (!table_join.getClauses().empty())
|
||||
settings.out << prefix << "Clauses: " << table_join.formatClauses(table_join.getClauses(), true /*short_format*/) << '\n';
|
||||
}
|
||||
|
||||
void JoinStep::describeActions(JSONBuilder::JSONMap & map) const
|
||||
{
|
||||
const auto & table_join = join->getTableJoin();
|
||||
map.add("Type", toString(table_join.kind()));
|
||||
map.add("Strictness", toString(table_join.strictness()));
|
||||
map.add("Algorithm", join->getName());
|
||||
|
||||
if (table_join.strictness() == JoinStrictness::Asof)
|
||||
map.add("ASOF inequality", toString(table_join.getAsofInequality()));
|
||||
|
||||
if (!table_join.getClauses().empty())
|
||||
map.add("Clauses", table_join.formatClauses(table_join.getClauses(), true /*short_format*/));
|
||||
}
|
||||
|
||||
void JoinStep::updateInputStream(const DataStream & new_input_stream_, size_t idx)
|
||||
{
|
||||
if (idx == 0)
|
||||
|
@ -27,6 +27,9 @@ public:
|
||||
|
||||
void describePipeline(FormatSettings & settings) const override;
|
||||
|
||||
void describeActions(JSONBuilder::JSONMap & map) const override;
|
||||
void describeActions(FormatSettings & settings) const override;
|
||||
|
||||
const JoinPtr & getJoin() const { return join; }
|
||||
bool allowPushDownToRight() const;
|
||||
|
||||
|
@ -132,21 +132,25 @@ void addCommonDefaultHandlersFactory(HTTPRequestHandlerFactoryMain & factory, IS
|
||||
auto ping_handler = std::make_shared<HandlingRuleHTTPHandlerFactory<StaticRequestHandler>>(server, ping_response_expression);
|
||||
ping_handler->attachStrictPath("/ping");
|
||||
ping_handler->allowGetAndHeadRequest();
|
||||
factory.addPathToHints("/ping");
|
||||
factory.addHandler(ping_handler);
|
||||
|
||||
auto replicas_status_handler = std::make_shared<HandlingRuleHTTPHandlerFactory<ReplicasStatusHandler>>(server);
|
||||
replicas_status_handler->attachNonStrictPath("/replicas_status");
|
||||
replicas_status_handler->allowGetAndHeadRequest();
|
||||
factory.addPathToHints("/replicas_status");
|
||||
factory.addHandler(replicas_status_handler);
|
||||
|
||||
auto play_handler = std::make_shared<HandlingRuleHTTPHandlerFactory<WebUIRequestHandler>>(server);
|
||||
play_handler->attachNonStrictPath("/play");
|
||||
play_handler->allowGetAndHeadRequest();
|
||||
factory.addPathToHints("/play");
|
||||
factory.addHandler(play_handler);
|
||||
|
||||
auto dashboard_handler = std::make_shared<HandlingRuleHTTPHandlerFactory<WebUIRequestHandler>>(server);
|
||||
dashboard_handler->attachNonStrictPath("/dashboard");
|
||||
dashboard_handler->allowGetAndHeadRequest();
|
||||
factory.addPathToHints("/dashboard");
|
||||
factory.addHandler(dashboard_handler);
|
||||
|
||||
auto js_handler = std::make_shared<HandlingRuleHTTPHandlerFactory<WebUIRequestHandler>>(server);
|
||||
|
16
src/Server/HTTPPathHints.cpp
Normal file
16
src/Server/HTTPPathHints.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include <Server/HTTPPathHints.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
void HTTPPathHints::add(const String & http_path)
|
||||
{
|
||||
http_paths.push_back(http_path);
|
||||
}
|
||||
|
||||
std::vector<String> HTTPPathHints::getAllRegisteredNames() const
|
||||
{
|
||||
return http_paths;
|
||||
}
|
||||
|
||||
}
|
22
src/Server/HTTPPathHints.h
Normal file
22
src/Server/HTTPPathHints.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <base/types.h>
|
||||
|
||||
#include <Common/NamePrompter.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
class HTTPPathHints : public IHints<1, HTTPPathHints>
|
||||
{
|
||||
public:
|
||||
std::vector<String> getAllRegisteredNames() const override;
|
||||
void add(const String & http_path);
|
||||
|
||||
private:
|
||||
std::vector<String> http_paths;
|
||||
};
|
||||
|
||||
using HTTPPathHintsPtr = std::shared_ptr<HTTPPathHints>;
|
||||
|
||||
}
|
@ -29,7 +29,7 @@ std::unique_ptr<HTTPRequestHandler> HTTPRequestHandlerFactoryMain::createRequest
|
||||
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD
|
||||
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
|
||||
{
|
||||
return std::unique_ptr<HTTPRequestHandler>(new NotFoundHandler);
|
||||
return std::unique_ptr<HTTPRequestHandler>(new NotFoundHandler(hints.getHints(request.getURI())));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Server/HTTP/HTTPRequestHandlerFactory.h>
|
||||
#include <Server/HTTPPathHints.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -15,11 +16,14 @@ public:
|
||||
|
||||
void addHandler(HTTPRequestHandlerFactoryPtr child_factory) { child_factories.emplace_back(child_factory); }
|
||||
|
||||
void addPathToHints(const std::string & http_path) { hints.add(http_path); }
|
||||
|
||||
std::unique_ptr<HTTPRequestHandler> createRequestHandler(const HTTPServerRequest & request) override;
|
||||
|
||||
private:
|
||||
Poco::Logger * log;
|
||||
std::string name;
|
||||
HTTPPathHints hints;
|
||||
|
||||
std::vector<HTTPRequestHandlerFactoryPtr> child_factories;
|
||||
};
|
||||
|
@ -10,7 +10,8 @@ void NotFoundHandler::handleRequest(HTTPServerRequest & request, HTTPServerRespo
|
||||
try
|
||||
{
|
||||
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
|
||||
*response.send() << "There is no handle " << request.getURI() << "\n\n"
|
||||
*response.send() << "There is no handle " << request.getURI()
|
||||
<< (!hints.empty() ? fmt::format(". Maybe you meant {}.", hints.front()) : "") << "\n\n"
|
||||
<< "Use / or /ping for health checks.\n"
|
||||
<< "Or /replicas_status for more sophisticated health checks.\n\n"
|
||||
<< "Send queries from your program with POST method or GET /?query=...\n\n"
|
||||
|
@ -9,7 +9,10 @@ namespace DB
|
||||
class NotFoundHandler : public HTTPRequestHandler
|
||||
{
|
||||
public:
|
||||
NotFoundHandler(std::vector<std::string> hints_) : hints(std::move(hints_)) {}
|
||||
void handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) override;
|
||||
private:
|
||||
std::vector<std::string> hints;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -2,10 +2,10 @@
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <base/types.h>
|
||||
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <base/types.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
class ServerType
|
||||
{
|
||||
public:
|
||||
|
||||
enum Type
|
||||
{
|
||||
TCP,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user