mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-21 09:10:48 +00:00
Merge remote-tracking branch 'upstream/master' into fix8
This commit is contained in:
commit
e190cb383c
@ -123,15 +123,6 @@ if (ARCHNATIVE)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -march=native")
|
||||
endif ()
|
||||
|
||||
if (CMAKE_SYSTEM MATCHES "Linux" AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
option (USE_LIBCXX "Use libc++ and libc++abi instead of libstdc++ (only make sense on Linux with Clang)" ON)
|
||||
if (USE_LIBCXX)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -pthread") # NOTE: Why this is not the default and why this is needed only with libc++?
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_LIBCPP_DEBUG=1") # More checks in debug build.
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Special options for better optimized code with clang
|
||||
#if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
# set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -Wno-unused-command-line-argument -mllvm -inline-threshold=10000")
|
||||
@ -156,16 +147,23 @@ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILER_FLAGS} -fn
|
||||
set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3")
|
||||
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g3 -ggdb3 -fno-inline")
|
||||
|
||||
if (NOT APPLE AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_SYSTEM MATCHES "FreeBSD"))
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++")
|
||||
if (MAKE_STATIC_LIBRARIES AND NOT APPLE AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_SYSTEM MATCHES "FreeBSD"))
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||
endif ()
|
||||
|
||||
if (NOT APPLE)
|
||||
if (CMAKE_SYSTEM MATCHES "Linux" AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GLIBC_COMPATIBILITY_LINK_FLAGS} ${CXX11_ABI_FLAGS}")
|
||||
|
||||
if (USE_LIBCXX AND (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
|
||||
link_libraries (-Wl,-Bstatic -stdlib=libc++ c++ c++abi -Wl,-Bdynamic)
|
||||
option (USE_LIBCXX "Use libc++ and libc++abi instead of libstdc++ (only make sense on Linux with Clang)" ${HAVE_LIBCPP})
|
||||
if (USE_LIBCXX)
|
||||
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_LIBCPP_DEBUG=1") # More checks in debug build.
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if (MAKE_STATIC_LIBRARIES)
|
||||
link_libraries (-Wl,-Bstatic -stdlib=libc++ c++ c++abi -Wl,-Bdynamic)
|
||||
else ()
|
||||
link_libraries (-stdlib=libc++ c++ c++abi)
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
@ -278,9 +276,10 @@ include (libs/libdaemon/cmake/find_unwind.cmake)
|
||||
|
||||
set (FULL_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
|
||||
set (FULL_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
|
||||
message (STATUS "C_FLAGS = ${FULL_C_FLAGS}")
|
||||
message (STATUS "CXX_FLAGS = ${FULL_CXX_FLAGS}")
|
||||
message (STATUS "LINK_FLAGS = ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
set (FULL_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
|
||||
message (STATUS "C_FLAGS = ${FULL_C_FLAGS}")
|
||||
message (STATUS "CXX_FLAGS = ${FULL_CXX_FLAGS}")
|
||||
message (STATUS "LINKER_FLAGS = ${FULL_EXE_LINKER_FLAGS}")
|
||||
|
||||
# Directory for Yandex specific files
|
||||
set (CLICKHOUSE_PRIVATE_DIR ${ClickHouse_SOURCE_DIR}/private/)
|
||||
|
@ -1,9 +1,24 @@
|
||||
include (CheckCXXSourceCompiles)
|
||||
include (CMakePushCheckState)
|
||||
|
||||
cmake_push_check_state ()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
# clang4 : -no-pie cause error
|
||||
# clang6 : -no-pie cause warning
|
||||
|
||||
|
||||
set (TEST_FLAG "-lc++ -lc++abi")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG}")
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <iostream>
|
||||
int main() {
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_LIBCPP)
|
||||
|
||||
else ()
|
||||
|
||||
cmake_push_check_state ()
|
||||
@ -21,6 +36,7 @@ else ()
|
||||
set (FLAG_NO_PIE ${TEST_FLAG})
|
||||
endif ()
|
||||
|
||||
cmake_pop_check_state ()
|
||||
|
||||
endif ()
|
||||
|
||||
cmake_pop_check_state ()
|
||||
|
@ -35,8 +35,21 @@ static std::string numberFromHost(const std::string & s)
|
||||
return "";
|
||||
}
|
||||
|
||||
ConfigProcessor::ConfigProcessor(bool throw_on_bad_incl_, bool log_to_console, const Substitutions & substitutions_)
|
||||
: throw_on_bad_incl(throw_on_bad_incl_)
|
||||
static std::string preprocessedConfigPath(const std::string & path)
|
||||
{
|
||||
Poco::Path preprocessed_path(path);
|
||||
preprocessed_path.setBaseName(preprocessed_path.getBaseName() + "-preprocessed");
|
||||
return preprocessed_path.toString();
|
||||
}
|
||||
|
||||
ConfigProcessor::ConfigProcessor(
|
||||
const std::string & path_,
|
||||
bool throw_on_bad_incl_,
|
||||
bool log_to_console,
|
||||
const Substitutions & substitutions_)
|
||||
: path(path_)
|
||||
, preprocessed_path(preprocessedConfigPath(path))
|
||||
, throw_on_bad_incl(throw_on_bad_incl_)
|
||||
, substitutions(substitutions_)
|
||||
/// We need larger name pool to allow to support vast amount of users in users.xml files for ClickHouse.
|
||||
/// Size is prime because Poco::XML::NamePool uses bad (inefficient, low quality)
|
||||
@ -118,13 +131,6 @@ static bool allWhitespace(const std::string & s)
|
||||
return s.find_first_not_of(" \t\n\r") == std::string::npos;
|
||||
}
|
||||
|
||||
static std::string preprocessedConfigPath(const std::string & path)
|
||||
{
|
||||
Poco::Path preprocessed_path(path);
|
||||
preprocessed_path.setBaseName(preprocessed_path.getBaseName() + "-preprocessed");
|
||||
return preprocessed_path.toString();
|
||||
}
|
||||
|
||||
void ConfigProcessor::mergeRecursive(XMLDocumentPtr config, Node * config_root, Node * with_root)
|
||||
{
|
||||
NodeListPtr with_nodes = with_root->childNodes();
|
||||
@ -373,16 +379,15 @@ ConfigProcessor::Files ConfigProcessor::getConfigMergeFiles(const std::string &
|
||||
}
|
||||
|
||||
XMLDocumentPtr ConfigProcessor::processConfig(
|
||||
const std::string & path_str,
|
||||
bool * has_zk_includes,
|
||||
zkutil::ZooKeeperNodeCache * zk_node_cache)
|
||||
bool * has_zk_includes,
|
||||
zkutil::ZooKeeperNodeCache * zk_node_cache)
|
||||
{
|
||||
XMLDocumentPtr config = dom_parser.parse(path_str);
|
||||
XMLDocumentPtr config = dom_parser.parse(path);
|
||||
|
||||
std::vector<std::string> contributing_files;
|
||||
contributing_files.push_back(path_str);
|
||||
contributing_files.push_back(path);
|
||||
|
||||
for (auto & merge_file : getConfigMergeFiles(path_str))
|
||||
for (auto & merge_file : getConfigMergeFiles(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -392,7 +397,7 @@ XMLDocumentPtr ConfigProcessor::processConfig(
|
||||
}
|
||||
catch (Poco::Exception & e)
|
||||
{
|
||||
throw Poco::Exception("Failed to merge config with " + merge_file + ": " + e.displayText());
|
||||
throw Poco::Exception("Failed to merge config with '" + merge_file + "': " + e.displayText());
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,7 +427,7 @@ XMLDocumentPtr ConfigProcessor::processConfig(
|
||||
}
|
||||
catch (Poco::Exception & e)
|
||||
{
|
||||
throw Poco::Exception("Failed to preprocess config `" + path_str + "': " + e.displayText(), e);
|
||||
throw Poco::Exception("Failed to preprocess config '" + path + "': " + e.displayText(), e);
|
||||
}
|
||||
|
||||
if (has_zk_includes)
|
||||
@ -432,15 +437,15 @@ XMLDocumentPtr ConfigProcessor::processConfig(
|
||||
comment << " This file was generated automatically.\n";
|
||||
comment << " Do not edit it: it is likely to be discarded and generated again before it's read next time.\n";
|
||||
comment << " Files used to generate this file:";
|
||||
for (const std::string & path : contributing_files)
|
||||
for (const std::string & contributing_file : contributing_files)
|
||||
{
|
||||
comment << "\n " << path;
|
||||
comment << "\n " << contributing_file;
|
||||
}
|
||||
if (zk_node_cache && !contributing_zk_paths.empty())
|
||||
{
|
||||
comment << "\n ZooKeeper nodes used to generate this file:";
|
||||
for (const std::string & path : contributing_zk_paths)
|
||||
comment << "\n " << path;
|
||||
for (const std::string & contributing_zk_path : contributing_zk_paths)
|
||||
comment << "\n " << contributing_zk_path;
|
||||
}
|
||||
|
||||
comment << " ";
|
||||
@ -452,39 +457,29 @@ XMLDocumentPtr ConfigProcessor::processConfig(
|
||||
return config;
|
||||
}
|
||||
|
||||
ConfigProcessor::LoadedConfig ConfigProcessor::loadConfig(const std::string & path, bool allow_zk_includes)
|
||||
ConfigProcessor::LoadedConfig ConfigProcessor::loadConfig(bool allow_zk_includes)
|
||||
{
|
||||
bool has_zk_includes;
|
||||
XMLDocumentPtr config_xml = processConfig(path, &has_zk_includes);
|
||||
XMLDocumentPtr config_xml = processConfig(&has_zk_includes);
|
||||
|
||||
if (has_zk_includes && !allow_zk_includes)
|
||||
throw Poco::Exception("Error while loading config `" + path + "': from_zk includes are not allowed!");
|
||||
|
||||
bool preprocessed_written = false;
|
||||
if (!has_zk_includes)
|
||||
{
|
||||
savePreprocessedConfig(config_xml, preprocessedConfigPath(path));
|
||||
preprocessed_written = true;
|
||||
}
|
||||
|
||||
ConfigurationPtr configuration(new Poco::Util::XMLConfiguration(config_xml));
|
||||
|
||||
return LoadedConfig{configuration, has_zk_includes, /* loaded_from_preprocessed = */ false, preprocessed_written};
|
||||
return LoadedConfig{configuration, has_zk_includes, /* loaded_from_preprocessed = */ false, config_xml};
|
||||
}
|
||||
|
||||
ConfigProcessor::LoadedConfig ConfigProcessor::loadConfigWithZooKeeperIncludes(
|
||||
const std::string & path,
|
||||
zkutil::ZooKeeperNodeCache & zk_node_cache,
|
||||
bool fallback_to_preprocessed)
|
||||
{
|
||||
std::string preprocessed_path = preprocessedConfigPath(path);
|
||||
|
||||
XMLDocumentPtr config_xml;
|
||||
bool has_zk_includes;
|
||||
bool processed_successfully = false;
|
||||
try
|
||||
{
|
||||
config_xml = processConfig(path, &has_zk_includes, &zk_node_cache);
|
||||
config_xml = processConfig(&has_zk_includes, &zk_node_cache);
|
||||
processed_successfully = true;
|
||||
}
|
||||
catch (const Poco::Exception & ex)
|
||||
@ -504,19 +499,16 @@ ConfigProcessor::LoadedConfig ConfigProcessor::loadConfigWithZooKeeperIncludes(
|
||||
config_xml = dom_parser.parse(preprocessed_path);
|
||||
}
|
||||
|
||||
if (processed_successfully)
|
||||
savePreprocessedConfig(config_xml, preprocessed_path);
|
||||
|
||||
ConfigurationPtr configuration(new Poco::Util::XMLConfiguration(config_xml));
|
||||
|
||||
return LoadedConfig{configuration, has_zk_includes, !processed_successfully, processed_successfully};
|
||||
return LoadedConfig{configuration, has_zk_includes, !processed_successfully, config_xml};
|
||||
}
|
||||
|
||||
void ConfigProcessor::savePreprocessedConfig(const XMLDocumentPtr & config, const std::string & preprocessed_path)
|
||||
void ConfigProcessor::savePreprocessedConfig(const LoadedConfig & loaded_config)
|
||||
{
|
||||
try
|
||||
{
|
||||
DOMWriter().writeNode(preprocessed_path, config);
|
||||
DOMWriter().writeNode(preprocessed_path, loaded_config.preprocessed_xml);
|
||||
}
|
||||
catch (Poco::Exception & e)
|
||||
{
|
||||
|
@ -32,7 +32,11 @@ public:
|
||||
using Substitutions = std::vector<std::pair<std::string, std::string>>;
|
||||
|
||||
/// Set log_to_console to true if the logging subsystem is not initialized yet.
|
||||
ConfigProcessor(bool throw_on_bad_incl = false, bool log_to_console = false, const Substitutions & substitutions = Substitutions());
|
||||
explicit ConfigProcessor(
|
||||
const std::string & path,
|
||||
bool throw_on_bad_incl = false,
|
||||
bool log_to_console = false,
|
||||
const Substitutions & substitutions = Substitutions());
|
||||
|
||||
~ConfigProcessor();
|
||||
|
||||
@ -52,9 +56,8 @@ public:
|
||||
/// If has_zk_includes is non-NULL and there are such elements, set has_zk_includes to true.
|
||||
/// 5) (Yandex.Metrika-specific) Substitute "<layer/>" with "<layer>layer number from the hostname</layer>".
|
||||
XMLDocumentPtr processConfig(
|
||||
const std::string & path,
|
||||
bool * has_zk_includes = nullptr,
|
||||
zkutil::ZooKeeperNodeCache * zk_node_cache = nullptr);
|
||||
bool * has_zk_includes = nullptr,
|
||||
zkutil::ZooKeeperNodeCache * zk_node_cache = nullptr);
|
||||
|
||||
|
||||
/// loadConfig* functions apply processConfig and create Poco::Util::XMLConfiguration.
|
||||
@ -67,28 +70,31 @@ public:
|
||||
ConfigurationPtr configuration;
|
||||
bool has_zk_includes;
|
||||
bool loaded_from_preprocessed;
|
||||
bool preprocessed_written;
|
||||
XMLDocumentPtr preprocessed_xml;
|
||||
};
|
||||
|
||||
/// If allow_zk_includes is true, expect that the configuration XML can contain from_zk nodes.
|
||||
/// If it is the case, set has_zk_includes to true and don't write config-preprocessed.xml,
|
||||
/// expecting that config would be reloaded with zookeeper later.
|
||||
LoadedConfig loadConfig(const std::string & path, bool allow_zk_includes = false);
|
||||
LoadedConfig loadConfig(bool allow_zk_includes = false);
|
||||
|
||||
/// If fallback_to_preprocessed is true, then if KeeperException is thrown during config
|
||||
/// processing, load the configuration from the preprocessed file.
|
||||
LoadedConfig loadConfigWithZooKeeperIncludes(
|
||||
const std::string & path,
|
||||
zkutil::ZooKeeperNodeCache & zk_node_cache,
|
||||
bool fallback_to_preprocessed = false);
|
||||
zkutil::ZooKeeperNodeCache & zk_node_cache,
|
||||
bool fallback_to_preprocessed = false);
|
||||
|
||||
void savePreprocessedConfig(const LoadedConfig & loaded_config);
|
||||
|
||||
public:
|
||||
|
||||
using Files = std::list<std::string>;
|
||||
|
||||
static Files getConfigMergeFiles(const std::string & config_path);
|
||||
|
||||
private:
|
||||
const std::string path;
|
||||
const std::string preprocessed_path;
|
||||
|
||||
bool throw_on_bad_incl;
|
||||
|
||||
Logger * log;
|
||||
@ -114,6 +120,4 @@ private:
|
||||
Poco::XML::Node * node,
|
||||
zkutil::ZooKeeperNodeCache * zk_node_cache,
|
||||
std::unordered_set<std::string> & contributing_zk_paths);
|
||||
|
||||
void savePreprocessedConfig(const XMLDocumentPtr & config, const std::string & preprocessed_path);
|
||||
};
|
||||
|
@ -23,8 +23,8 @@ int main(int argc, char ** argv)
|
||||
return 3;
|
||||
}
|
||||
|
||||
ConfigProcessor processor(false, true);
|
||||
auto config = processor.loadConfig(argv[1]).configuration;
|
||||
ConfigProcessor processor(argv[1], false, true);
|
||||
auto config = processor.loadConfig().configuration;
|
||||
zkutil::ZooKeeper zk(*config, "zookeeper");
|
||||
zkutil::EventPtr watch = std::make_shared<Poco::Event>();
|
||||
|
||||
|
@ -210,9 +210,9 @@ struct ModuloImpl
|
||||
template <typename Result = ResultType>
|
||||
static inline Result apply(A a, B b)
|
||||
{
|
||||
throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger<A>::Type(a), typename NumberTraits::ToInteger<A>::Type(b));
|
||||
throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger<A>::Type(a), typename NumberTraits::ToInteger<B>::Type(b));
|
||||
return typename NumberTraits::ToInteger<A>::Type(a)
|
||||
% typename NumberTraits::ToInteger<A>::Type(b);
|
||||
% typename NumberTraits::ToInteger<B>::Type(b);
|
||||
}
|
||||
};
|
||||
|
||||
@ -434,7 +434,7 @@ struct AbsImpl
|
||||
template <typename A, typename B>
|
||||
struct GCDImpl
|
||||
{
|
||||
using ResultType = typename NumberTraits::ResultOfIntegerDivision<A, B>::Type;
|
||||
using ResultType = typename NumberTraits::ResultOfAdditionMultiplication<A, B>::Type;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static inline Result apply(A a, B b)
|
||||
|
@ -278,8 +278,9 @@ void ExternalLoader::reloadFromConfigFile(const std::string & config_path, const
|
||||
const auto last_modified = config_file.getLastModified();
|
||||
if (force_reload || last_modified > config_last_modified)
|
||||
{
|
||||
ConfigProcessor config_processor = ConfigProcessor();
|
||||
ConfigProcessor::LoadedConfig cfg = config_processor.loadConfig(config_path);
|
||||
ConfigProcessor config_processor = ConfigProcessor(config_path);
|
||||
ConfigProcessor::LoadedConfig cfg = config_processor.loadConfig();
|
||||
config_processor.savePreprocessedConfig(cfg);
|
||||
|
||||
Poco::AutoPtr<Poco::Util::AbstractConfiguration> config = cfg.configuration;
|
||||
|
||||
|
@ -195,7 +195,7 @@ void runOneTest(size_t test_num, const TestDescriptor & test_descriptor)
|
||||
|
||||
try
|
||||
{
|
||||
config = ConfigProcessor{}.loadConfig(path_name).configuration;
|
||||
config = ConfigProcessor(path_name).loadConfig().configuration;
|
||||
}
|
||||
catch (const Poco::Exception & ex)
|
||||
{
|
||||
|
@ -66,15 +66,16 @@ void ConfigReloader::reloadIfNewer(bool force, bool throw_on_error, bool fallbac
|
||||
FilesChangesTracker new_files = getNewFileList();
|
||||
if (force || new_files.isDifferOrNewerThan(files))
|
||||
{
|
||||
ConfigProcessor config_processor(path);
|
||||
ConfigProcessor::LoadedConfig loaded_config;
|
||||
try
|
||||
{
|
||||
LOG_DEBUG(log, "Loading config `" << path << "'");
|
||||
|
||||
loaded_config = ConfigProcessor().loadConfig(path, /* allow_zk_includes = */ true);
|
||||
loaded_config = config_processor.loadConfig(/* allow_zk_includes = */ true);
|
||||
if (loaded_config.has_zk_includes)
|
||||
loaded_config = ConfigProcessor().loadConfigWithZooKeeperIncludes(
|
||||
path, zk_node_cache, fallback_to_preprocessed);
|
||||
loaded_config = config_processor.loadConfigWithZooKeeperIncludes(
|
||||
zk_node_cache, fallback_to_preprocessed);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -84,6 +85,7 @@ void ConfigReloader::reloadIfNewer(bool force, bool throw_on_error, bool fallbac
|
||||
tryLogCurrentException(log, "Error loading config from `" + path + "'");
|
||||
return;
|
||||
}
|
||||
config_processor.savePreprocessedConfig(loaded_config);
|
||||
|
||||
/** We should remember last modification time if and only if config was sucessfully loaded
|
||||
* Otherwise a race condition could occur during config files update:
|
||||
|
@ -26,16 +26,16 @@ static void setupLogging(const std::string & log_level)
|
||||
static std::string extractFromConfig(
|
||||
const std::string & config_path, const std::string & key, bool process_zk_includes)
|
||||
{
|
||||
ConfigProcessor processor(/* throw_on_bad_incl = */ false, /* log_to_console = */ false);
|
||||
ConfigProcessor processor(config_path, /* throw_on_bad_incl = */ false, /* log_to_console = */ false);
|
||||
bool has_zk_includes;
|
||||
XMLDocumentPtr config_xml = processor.processConfig(config_path, &has_zk_includes);
|
||||
XMLDocumentPtr config_xml = processor.processConfig(&has_zk_includes);
|
||||
if (has_zk_includes && process_zk_includes)
|
||||
{
|
||||
ConfigurationPtr bootstrap_configuration(new Poco::Util::XMLConfiguration(config_xml));
|
||||
zkutil::ZooKeeperPtr zookeeper = std::make_shared<zkutil::ZooKeeper>(
|
||||
*bootstrap_configuration, "zookeeper");
|
||||
zkutil::ZooKeeperNodeCache zk_node_cache([&] { return zookeeper; });
|
||||
config_xml = processor.processConfig(config_path, &has_zk_includes, &zk_node_cache);
|
||||
config_xml = processor.processConfig(&has_zk_includes, &zk_node_cache);
|
||||
}
|
||||
ConfigurationPtr configuration(new Poco::Util::XMLConfiguration(config_xml));
|
||||
return configuration->getString(key);
|
||||
|
@ -247,10 +247,10 @@ try
|
||||
/// Load config files if exists
|
||||
if (config().has("config-file") || Poco::File("config.xml").exists())
|
||||
{
|
||||
ConfigurationPtr processed_config = ConfigProcessor(false, true)
|
||||
.loadConfig(config().getString("config-file", "config.xml"))
|
||||
.configuration;
|
||||
config().add(processed_config.duplicate(), PRIO_DEFAULT, false);
|
||||
ConfigProcessor config_processor(config().getString("config-file", "config.xml"), false, true);
|
||||
auto loaded_config = config_processor.loadConfig();
|
||||
config_processor.savePreprocessedConfig(loaded_config);
|
||||
config().add(loaded_config.configuration.duplicate(), PRIO_DEFAULT, false);
|
||||
}
|
||||
|
||||
context = std::make_unique<Context>(Context::createGlobal());
|
||||
@ -452,8 +452,11 @@ void LocalServer::setupUsers()
|
||||
|
||||
if (config().has("users_config") || config().has("config-file") || Poco::File("config.xml").exists())
|
||||
{
|
||||
auto users_config_path = config().getString("users_config", config().getString("config-file", "config.xml"));
|
||||
users_config = ConfigProcessor().loadConfig(users_config_path).configuration;
|
||||
const auto users_config_path = config().getString("users_config", config().getString("config-file", "config.xml"));
|
||||
ConfigProcessor config_processor(users_config_path);
|
||||
const auto loaded_config = config_processor.loadConfig();
|
||||
config_processor.savePreprocessedConfig(loaded_config);
|
||||
users_config = loaded_config.configuration;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -108,8 +108,10 @@ int Server::main(const std::vector<std::string> & args)
|
||||
if (loaded_config.has_zk_includes)
|
||||
{
|
||||
auto old_configuration = loaded_config.configuration;
|
||||
loaded_config = ConfigProcessor().loadConfigWithZooKeeperIncludes(
|
||||
config_path, main_config_zk_node_cache, /* fallback_to_preprocessed = */ true);
|
||||
ConfigProcessor config_processor(config_path);
|
||||
loaded_config = config_processor.loadConfigWithZooKeeperIncludes(
|
||||
main_config_zk_node_cache, /* fallback_to_preprocessed = */ true);
|
||||
config_processor.savePreprocessedConfig(loaded_config);
|
||||
config().removeConfiguration(old_configuration.get());
|
||||
config().add(loaded_config.configuration.duplicate(), PRIO_DEFAULT, false);
|
||||
}
|
||||
|
@ -8,6 +8,9 @@
|
||||
1
|
||||
2147483647
|
||||
1
|
||||
5
|
||||
255
|
||||
1
|
||||
5120
|
||||
121
|
||||
256
|
||||
|
@ -9,6 +9,9 @@ select gcd(255, 254);
|
||||
select gcd(2147483647, 2147483646);
|
||||
select gcd(4611686011984936962, 2147483647);
|
||||
select gcd(-2147483648, 1);
|
||||
select gcd(255, 515);
|
||||
select gcd(255, 510);
|
||||
select gcd(255, 512);
|
||||
-- test lcm
|
||||
select lcm(1280, 1024);
|
||||
select lcm(11, 121);
|
||||
|
13
dbms/tests/queries/0_stateless/00516_modulo.reference
Normal file
13
dbms/tests/queries/0_stateless/00516_modulo.reference
Normal file
@ -0,0 +1,13 @@
|
||||
8
|
||||
1
|
||||
255
|
||||
255
|
||||
255
|
||||
0
|
||||
127
|
||||
0
|
||||
-1
|
||||
57
|
||||
3
|
||||
20
|
||||
16
|
13
dbms/tests/queries/0_stateless/00516_modulo.sql
Normal file
13
dbms/tests/queries/0_stateless/00516_modulo.sql
Normal file
@ -0,0 +1,13 @@
|
||||
SELECT 1000 % 32;
|
||||
SELECT 7 % 3;
|
||||
SELECT 255 % 510;
|
||||
SELECT 255 % 512;
|
||||
SELECT 255 % 1000000009;
|
||||
SELECT 0 % 255;
|
||||
SELECT 2147483647 % 255;
|
||||
SELECT -1 % -1;
|
||||
SELECT -1 % -2;
|
||||
SELECT 255 % 99;
|
||||
SELECT 42 % 13;
|
||||
SELECT 42 % 22;
|
||||
SELECT 1234567 % 123;
|
@ -9,7 +9,7 @@ BUILDDIR = build
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you do not have Sphinx installed, grab it from http://sphinx-doc.org/ )
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
@ -25,7 +25,9 @@ default:
|
||||
$(SPHINXBUILD) -b html $(SPHINXOPTS) ru $(BUILDDIR)/docs/ru
|
||||
$(SPHINXBUILD) -b html $(SPHINXOPTS) en $(BUILDDIR)/docs/en
|
||||
$(SPHINXBUILD) -b singlehtml $(SPHINXOPTS) ru $(BUILDDIR)/docs/ru/single
|
||||
sed -i "s|external\\\\\" href=\\\\\"[\.a-z_-\/]*#|external\\\\\" href=\\\\\"#|g" 'build/docs/ru/single/index.html'
|
||||
$(SPHINXBUILD) -b singlehtml $(SPHINXOPTS) en $(BUILDDIR)/docs/en/single
|
||||
sed -i "s|external\\\\\" href=\\\\\"[\.a-z_-\/]*#|external\\\\\" href=\\\\\"#|g" 'build/docs/en/single/index.html'
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@ -181,4 +183,3 @@ pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
<a name="data_types"></a>
|
||||
|
||||
Типы данных
|
||||
===========
|
||||
|
||||
|
@ -1,45 +1,69 @@
|
||||
Функции по работе с массивами
|
||||
=============================
|
||||
# Функции по работе с массивами
|
||||
|
||||
### empty
|
||||
|
||||
## empty
|
||||
Возвращает 1 для пустого массива, и 0 для непустого массива.
|
||||
Тип результата - UInt8.
|
||||
Функция также работает для строк.
|
||||
|
||||
### notEmpty
|
||||
## notEmpty
|
||||
Возвращает 0 для пустого массива, и 1 для непустого массива.
|
||||
Тип результата - UInt8.
|
||||
Функция также работает для строк.
|
||||
|
||||
### length
|
||||
## length
|
||||
Возвращает количество элементов в массиве.
|
||||
Тип результата - UInt64.
|
||||
Функция также работает для строк.
|
||||
|
||||
### emptyArrayUInt8, emptyArrayUInt16, emptyArrayUInt32, emptyArrayUInt64
|
||||
## emptyArrayUInt8, emptyArrayUInt16, emptyArrayUInt32, emptyArrayUInt64
|
||||
|
||||
### emptyArrayInt8, emptyArrayInt16, emptyArrayInt32, emptyArrayInt64
|
||||
## emptyArrayInt8, emptyArrayInt16, emptyArrayInt32, emptyArrayInt64
|
||||
|
||||
### emptyArrayFloat32, emptyArrayFloat64
|
||||
## emptyArrayFloat32, emptyArrayFloat64
|
||||
|
||||
### emptyArrayDate, emptyArrayDateTime
|
||||
## emptyArrayDate, emptyArrayDateTime
|
||||
|
||||
### emptyArrayString
|
||||
## emptyArrayString
|
||||
Принимает ноль аргументов и возвращает пустой массив соответствующего типа.
|
||||
|
||||
### emptyArrayToSingle
|
||||
## emptyArrayToSingle
|
||||
Принимает пустой массив и возвращает массив из одного элемента, равного значению по умолчанию.
|
||||
|
||||
### range(N)
|
||||
## range(N)
|
||||
Возвращает массив чисел от 0 до N-1.
|
||||
На всякий случай, если на блок данных, создаются массивы суммарной длины больше 100 000 000 элементов, то кидается исключение.
|
||||
|
||||
### array(x1, ...), оператор \[x1, ...\]
|
||||
## array(x1, ...), оператор \[x1, ...\]
|
||||
Создаёт массив из аргументов функции.
|
||||
Аргументы должны быть константами и иметь типы, для которых есть наименьший общий тип. Должен быть передан хотя бы один аргумент, так как иначе непонятно, какого типа создавать массив. То есть, с помощью этой функции невозможно создать пустой массив (для этого используйте функции emptyArray\*, описанные выше).
|
||||
Возвращает результат типа Array(T), где T - наименьший общий тип от переданных аргументов.
|
||||
|
||||
### arrayElement(arr, n), оператор arr\[n\]
|
||||
## arrayConcat
|
||||
|
||||
Объединяет массивы, переданные в качестве аргументов.
|
||||
|
||||
```
|
||||
arrayConcat(arrays)
|
||||
```
|
||||
|
||||
**Аргументы**
|
||||
|
||||
- `arrays` - Перечисленные через запятую массивы `[values]`.
|
||||
|
||||
**Пример**
|
||||
|
||||
```sql
|
||||
SELECT arrayConcat([1, 2], [3, 4], [5, 6]) AS res
|
||||
```
|
||||
```
|
||||
┌─res───────────┐
|
||||
│ [1,2,3,4,5,6] │
|
||||
└───────────────┘
|
||||
```
|
||||
|
||||
|
||||
## arrayElement(arr, n), оператор arr\[n\]
|
||||
Достаёт элемент с индексом n из массива arr.
|
||||
n должен быть любым целочисленным типом.
|
||||
Индексы в массиве начинаются с единицы.
|
||||
@ -47,17 +71,17 @@ n должен быть любым целочисленным типом.
|
||||
|
||||
Если индекс выходит за границы массива, то возвращается некоторое значение по умолчанию (0 для чисел, пустая строка для строк и т. п.).
|
||||
|
||||
### has(arr, elem)
|
||||
## has(arr, elem)
|
||||
Проверяет наличие элемента elem в массиве arr.
|
||||
Возвращает 0, если элемента в массиве нет, или 1, если есть.
|
||||
|
||||
### indexOf(arr, x)
|
||||
## indexOf(arr, x)
|
||||
Возвращает индекс элемента x (начиная с 1), если он есть в массиве, или 0, если его нет.
|
||||
|
||||
### countEqual(arr, x)
|
||||
## countEqual(arr, x)
|
||||
Возвращает количество элементов массива, равных x. Эквивалентно arrayCount(elem -> elem = x, arr).
|
||||
|
||||
### arrayEnumerate(arr)
|
||||
## arrayEnumerate(arr)
|
||||
Возвращает массив \[1, 2, 3, ..., length(arr)\]
|
||||
|
||||
Эта функция обычно используется совместно с ARRAY JOIN. Она позволяет, после применения ARRAY JOIN, посчитать что-либо только один раз для каждого массива. Пример:
|
||||
@ -98,7 +122,7 @@ WHERE (CounterID = 160656) AND notEmpty(GoalsReached)
|
||||
|
||||
Также эта функция может быть использована в функциях высшего порядка. Например, с её помощью можно достать индексы массива для элементов, удовлетворяющих некоторому условию.
|
||||
|
||||
### arrayEnumerateUniq(arr, ...)
|
||||
## arrayEnumerateUniq(arr, ...)
|
||||
Возвращает массив, такого же размера, как исходный, где для каждого элемента указано, какой он по счету среди элементов с таким же значением.
|
||||
Например: arrayEnumerateUniq(\[10, 20, 10, 30\]) = \[1, 1, 2, 1\].
|
||||
|
||||
@ -151,11 +175,132 @@ SELECT arrayEnumerateUniq([1, 1, 1, 2, 2, 2], [1, 1, 2, 1, 1, 2]) AS res
|
||||
|
||||
Это нужно при использовании ARRAY JOIN с вложенной структурой данных и затем агрегации по нескольким элементам этой структуры.
|
||||
|
||||
### arrayUniq(arr, ...)
|
||||
## arrayPopBack
|
||||
|
||||
Удаляет последний элемент из массива.
|
||||
|
||||
```
|
||||
arrayPopBack(array)
|
||||
```
|
||||
|
||||
**Аргументы**
|
||||
|
||||
- `array` - Массив.
|
||||
|
||||
**Пример**
|
||||
|
||||
```sql
|
||||
SELECT arrayPopBack([1, 2, 3]) AS res
|
||||
```
|
||||
```
|
||||
┌─res───┐
|
||||
│ [1,2] │
|
||||
└───────┘
|
||||
```
|
||||
|
||||
## arrayPopFront
|
||||
|
||||
Удаляет первый элемент из массива.
|
||||
|
||||
```
|
||||
arrayPopFront(array)
|
||||
```
|
||||
|
||||
**Аргументы**
|
||||
|
||||
- `array` - Массив.
|
||||
|
||||
**Пример**
|
||||
|
||||
```sql
|
||||
SELECT arrayPopFront([1, 2, 3]) AS res
|
||||
```
|
||||
```
|
||||
┌─res───┐
|
||||
│ [2,3] │
|
||||
└───────┘
|
||||
```
|
||||
|
||||
## arrayPushBack
|
||||
|
||||
Добавляет один элемент в конец массива.
|
||||
|
||||
```
|
||||
arrayPushBack(array, single_value)
|
||||
```
|
||||
|
||||
**Аргументы**
|
||||
|
||||
- `array` - Массив.
|
||||
- `single_value` - Одиночное значение. В массив с числам можно добавить только числа, в массив со строками только строки. При добавлении чисел ClickHouse автоматически приводит тип `single_value` к типу данных массива. Подробнее о типах данных в ClickHouse читайте в разделе "[Типы данных](../data_types/index.md#data_types)".
|
||||
|
||||
**Пример**
|
||||
|
||||
```sql
|
||||
SELECT arrayPushBack(['a'], 'b') AS res
|
||||
```
|
||||
```
|
||||
┌─res───────┐
|
||||
│ ['a','b'] │
|
||||
└───────────┘
|
||||
```
|
||||
|
||||
## arrayPushFront
|
||||
|
||||
Добавляет один элемент в начало массива.
|
||||
|
||||
```
|
||||
arrayPushFront(array, single_value)
|
||||
```
|
||||
|
||||
**Аргументы**
|
||||
|
||||
- `array` - Массив.
|
||||
- `single_value` - Одиночное значение. В массив с числам можно добавить только числа, в массив со строками только строки. При добавлении чисел ClickHouse автоматически приводит тип `single_value` к типу данных массива. Подробнее о типах данных в ClickHouse читайте в разделе "[Типы данных](../data_types/index.md#data_types)".
|
||||
|
||||
**Пример**
|
||||
|
||||
```sql
|
||||
SELECT arrayPushBack(['b'], 'a') AS res
|
||||
```
|
||||
```
|
||||
┌─res───────┐
|
||||
│ ['a','b'] │
|
||||
└───────────┘
|
||||
```
|
||||
|
||||
## arraySlice
|
||||
|
||||
Возвращает срез массива.
|
||||
|
||||
```
|
||||
arraySlice(array, offset[, length])
|
||||
```
|
||||
|
||||
**Аргументы**
|
||||
|
||||
- `array` - Массив данных.
|
||||
- `offset` - Отступ от края массива. Положительное значение - отступ слева, отрицательное значение - отступ справа. Отсчет элементов массива начинается с 1.
|
||||
- `length` - Длина необходимого среза. Если указать отрицательное значение, то функция вернёт открытый срез `[offset, array_length - length)`. Если не указать значение, то функция вернёт срез `[offset, the_end_of_array]`.
|
||||
|
||||
**Пример**
|
||||
|
||||
```sql
|
||||
SELECT arraySlice([1, 2, 3, 4, 5], 2, 3) AS res
|
||||
```
|
||||
```
|
||||
┌─res─────┐
|
||||
│ [2,3,4] │
|
||||
└─────────┘
|
||||
```
|
||||
|
||||
|
||||
## arrayUniq(arr, ...)
|
||||
Если передан один аргумент, считает количество разных элементов в массиве.
|
||||
Если передано несколько аргументов, считает количество разных кортежей из элементов на соответствующих позициях в нескольких массивах.
|
||||
|
||||
Если необходимо получить список уникальных элементов массива, можно воспользоваться arrayReduce('groupUniqArray', arr).
|
||||
|
||||
### arrayJoin(arr)
|
||||
Особенная функция. Смотрите раздел "Функция arrayJoin".
|
||||
## arrayJoin(arr)
|
||||
Особенная функция. Смотрите раздел ["Функция arrayJoin"](array_join.md#functions_arrayjoin).
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
<a name="functions_arrayjoin"></a>
|
||||
|
||||
Функция arrayJoin
|
||||
=================
|
||||
|
||||
|
@ -524,7 +524,7 @@ void BaseDaemon::reloadConfiguration()
|
||||
*/
|
||||
std::string log_command_line_option = config().getString("logger.log", "");
|
||||
config_path = config().getString("config-file", "config.xml");
|
||||
loaded_config = ConfigProcessor(false, true).loadConfig(config_path, /* allow_zk_includes = */ true);
|
||||
loaded_config = ConfigProcessor(config_path, false, true).loadConfig(/* allow_zk_includes = */ true);
|
||||
if (last_configuration != nullptr)
|
||||
config().removeConfiguration(last_configuration);
|
||||
last_configuration = loaded_config.configuration.duplicate();
|
||||
@ -720,6 +720,20 @@ void BaseDaemon::initialize(Application & self)
|
||||
/// Считаем конфигурацию
|
||||
reloadConfiguration();
|
||||
|
||||
/// This must be done before creation of any files (including logs).
|
||||
if (config().has("umask"))
|
||||
{
|
||||
std::string umask_str = config().getString("umask");
|
||||
mode_t umask_num = 0;
|
||||
std::stringstream stream;
|
||||
stream << umask_str;
|
||||
stream >> std::oct >> umask_num;
|
||||
|
||||
umask(umask_num);
|
||||
}
|
||||
|
||||
ConfigProcessor(config_path).savePreprocessedConfig(loaded_config);
|
||||
|
||||
/// В случае падения - сохраняем коры
|
||||
{
|
||||
struct rlimit rlim;
|
||||
@ -749,18 +763,6 @@ void BaseDaemon::initialize(Application & self)
|
||||
tzset();
|
||||
}
|
||||
|
||||
/// This must be done before creation of any files (including logs).
|
||||
if (config().has("umask"))
|
||||
{
|
||||
std::string umask_str = config().getString("umask");
|
||||
mode_t umask_num = 0;
|
||||
std::stringstream stream;
|
||||
stream << umask_str;
|
||||
stream >> std::oct >> umask_num;
|
||||
|
||||
umask(umask_num);
|
||||
}
|
||||
|
||||
std::string log_path = config().getString("logger.log", "");
|
||||
if (!log_path.empty())
|
||||
log_path = Poco::Path(log_path).setFileName("").toString();
|
||||
|
@ -11,8 +11,8 @@ int main(int argc, char ** argv)
|
||||
return 3;
|
||||
}
|
||||
|
||||
ConfigProcessor processor(false, true);
|
||||
XMLDocumentPtr document = processor.processConfig(argv[1]);
|
||||
ConfigProcessor processor(argv[1], false, true);
|
||||
XMLDocumentPtr document = processor.processConfig();
|
||||
Poco::XML::DOMWriter().writeNode(std::cout, document);
|
||||
}
|
||||
catch (Poco::Exception & e)
|
||||
|
Loading…
Reference in New Issue
Block a user