Merge remote-tracking branch 'upstream/master' into fix8

This commit is contained in:
proller 2017-11-27 16:46:23 +03:00
commit e190cb383c
22 changed files with 336 additions and 133 deletions

View File

@ -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/)

View File

@ -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 ()

View File

@ -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)
{

View File

@ -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);
};

View File

@ -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>();

View File

@ -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)

View File

@ -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;

View File

@ -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)
{

View File

@ -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:

View File

@ -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);

View File

@ -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
{

View File

@ -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);
}

View File

@ -8,6 +8,9 @@
1
2147483647
1
5
255
1
5120
121
256

View File

@ -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);

View File

@ -0,0 +1,13 @@
8
1
255
255
255
0
127
0
-1
57
3
20
16

View 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;

View File

@ -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."

View File

@ -1,3 +1,5 @@
<a name="data_types"></a>
Типы данных
===========

View File

@ -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 -&gt; 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).

View File

@ -1,3 +1,5 @@
<a name="functions_arrayjoin"></a>
Функция arrayJoin
=================

View File

@ -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();

View File

@ -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)