mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 16:50:48 +00:00
merged with master
This commit is contained in:
commit
bff77d1bae
1
.gitignore
vendored
1
.gitignore
vendored
@ -223,3 +223,4 @@ config-preprocessed.xml
|
||||
# Gulp dependencies used to minify website
|
||||
node_modules
|
||||
public
|
||||
website/docs
|
||||
|
@ -1,6 +1,6 @@
|
||||
#This strings autochanged from release_lib.sh :
|
||||
set(VERSION_DESCRIBE v1.1.54236-testing)
|
||||
set(VERSION_REVISION 54236)
|
||||
set(VERSION_DESCRIBE v1.1.54237-testing)
|
||||
set(VERSION_REVISION 54237)
|
||||
#===end of autochange
|
||||
|
||||
set (VERSION_MAJOR 1)
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <Columns/ColumnArray.h>
|
||||
#include <Columns/ColumnsNumber.h>
|
||||
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <Columns/ColumnsNumber.h>
|
||||
#include <Parsers/CommonParsers.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
#include <Parsers/ExpressionElementParsers.h>
|
||||
#include <Parsers/ASTLiteral.h>
|
||||
|
@ -216,7 +216,7 @@ struct StdDevPopImpl
|
||||
|
||||
}
|
||||
|
||||
/** If `compute_marginal_moments` flag is set this class provides the heir
|
||||
/** If `compute_marginal_moments` flag is set this class provides the successor
|
||||
* CovarianceData support of marginal moments for calculating the correlation.
|
||||
*/
|
||||
template<bool compute_marginal_moments>
|
||||
|
@ -23,6 +23,8 @@ struct CollectTables;
|
||||
* SELECT array FROM t ARRAY JOIN array array -> array
|
||||
* SELECT nested.elem FROM t ARRAY JOIN nested nested -> nested
|
||||
* SELECT elem FROM t ARRAY JOIN [1, 2, 3] AS elem elem -> [1, 2, 3]
|
||||
*
|
||||
* Does not analyze arrayJoin functions.
|
||||
*/
|
||||
struct AnalyzeArrayJoins
|
||||
{
|
||||
|
@ -36,7 +36,7 @@ try
|
||||
auto system_database = std::make_shared<DatabaseMemory>("system");
|
||||
context.addDatabase("system", system_database);
|
||||
system_database->attachTable("one", StorageSystemOne::create("one"));
|
||||
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers"));
|
||||
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers", false));
|
||||
context.setCurrentDatabase("system");
|
||||
|
||||
AnalyzeLambdas analyze_lambdas;
|
||||
|
@ -32,8 +32,8 @@ try
|
||||
auto system_database = std::make_shared<DatabaseMemory>("system");
|
||||
context.addDatabase("system", system_database);
|
||||
context.setCurrentDatabase("system");
|
||||
system_database->attachTable("one", StorageSystemOne::create("one"));
|
||||
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers"));
|
||||
system_database->attachTable("one", StorageSystemOne::create("one"));
|
||||
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers", false));
|
||||
|
||||
AnalyzeResultOfQuery analyzer;
|
||||
analyzer.process(ast, context);
|
||||
|
@ -33,8 +33,8 @@ try
|
||||
auto system_database = std::make_shared<DatabaseMemory>("system");
|
||||
context.addDatabase("system", system_database);
|
||||
context.setCurrentDatabase("system");
|
||||
system_database->attachTable("one", StorageSystemOne::create("one"));
|
||||
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers"));
|
||||
system_database->attachTable("one", StorageSystemOne::create("one"));
|
||||
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers", false));
|
||||
|
||||
CollectAliases collect_aliases;
|
||||
collect_aliases.process(ast);
|
||||
|
@ -38,8 +38,8 @@ try
|
||||
|
||||
auto system_database = std::make_shared<DatabaseMemory>("system");
|
||||
context.addDatabase("system", system_database);
|
||||
system_database->attachTable("one", StorageSystemOne::create("one"));
|
||||
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers"));
|
||||
system_database->attachTable("one", StorageSystemOne::create("one"));
|
||||
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers", false));
|
||||
context.setCurrentDatabase("system");
|
||||
|
||||
AnalyzeLambdas analyze_lambdas;
|
||||
|
@ -39,8 +39,8 @@ try
|
||||
|
||||
auto system_database = std::make_shared<DatabaseMemory>("system");
|
||||
context.addDatabase("system", system_database);
|
||||
system_database->attachTable("one", StorageSystemOne::create("one"));
|
||||
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers"));
|
||||
system_database->attachTable("one", StorageSystemOne::create("one"));
|
||||
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers", false));
|
||||
context.setCurrentDatabase("system");
|
||||
|
||||
AnalyzeLambdas analyze_lambdas;
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <Columns/ColumnNullable.h>
|
||||
#include <DataTypes/DataTypeTuple.h>
|
||||
#include <DataTypes/DataTypeNullable.h>
|
||||
#include <ext/enumerate.hpp>
|
||||
#include <ext/enumerate.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <Columns/ColumnTuple.h>
|
||||
#include <ext/map.hpp>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/map.h>
|
||||
#include <ext/range.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#include <Columns/ColumnVector.h>
|
||||
|
||||
#include <ext/bit_cast.hpp>
|
||||
#include <ext/bit_cast.h>
|
||||
|
||||
#if __SSE2__
|
||||
#include <emmintrin.h>
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <ext/scope_guard.hpp>
|
||||
#include <ext/scope_guard.h>
|
||||
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/randomSeed.h>
|
||||
|
@ -6,7 +6,8 @@
|
||||
#include <Poco/Mutex.h>
|
||||
#include <Poco/Semaphore.h>
|
||||
|
||||
#include <Core/Types.h>
|
||||
#include <common/Types.h>
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@ -66,8 +67,8 @@ public:
|
||||
fill_count.set();
|
||||
}
|
||||
|
||||
template <class ... Args>
|
||||
void emplace(Args && ... args)
|
||||
template <typename... Args>
|
||||
void emplace(Args &&... args)
|
||||
{
|
||||
empty_count.wait();
|
||||
{
|
||||
@ -88,7 +89,7 @@ public:
|
||||
empty_count.set();
|
||||
}
|
||||
|
||||
bool tryPush(const T & x, DB::UInt64 milliseconds = 0)
|
||||
bool tryPush(const T & x, UInt64 milliseconds = 0)
|
||||
{
|
||||
if (empty_count.tryWait(milliseconds))
|
||||
{
|
||||
@ -102,8 +103,8 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class ... Args>
|
||||
bool tryEmplace(DB::UInt64 milliseconds, Args && ... args)
|
||||
template <typename... Args>
|
||||
bool tryEmplace(UInt64 milliseconds, Args &&... args)
|
||||
{
|
||||
if (empty_count.tryWait(milliseconds))
|
||||
{
|
||||
@ -117,7 +118,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tryPop(T & x, DB::UInt64 milliseconds = 0)
|
||||
bool tryPop(T & x, UInt64 milliseconds = 0)
|
||||
{
|
||||
if (fill_count.tryWait(milliseconds))
|
||||
{
|
||||
|
@ -198,6 +198,7 @@ public:
|
||||
/// Create table
|
||||
NamesAndTypesListPtr columns = std::make_shared<NamesAndTypesList>(sample_block.getColumnsList());
|
||||
StoragePtr storage = StorageMemory::create(data.second, columns);
|
||||
storage->startup();
|
||||
context.addExternalTable(data.second, storage);
|
||||
BlockOutputStreamPtr output = storage->write(ASTPtr(), context.getSettingsRef());
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <climits>
|
||||
#include <random>
|
||||
#include <common/Types.h>
|
||||
#include <ext/scope_guard.hpp>
|
||||
#include <ext/scope_guard.h>
|
||||
#include <Core/Types.h>
|
||||
#include <Common/PoolBase.h>
|
||||
#include <Common/ProfileEvents.h>
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include <ext/bit_cast.hpp>
|
||||
#include <ext/bit_cast.h>
|
||||
#include <Core/Types.h>
|
||||
#include <Core/Defines.h>
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <mutex>
|
||||
#include <ext/function_traits.hpp>
|
||||
#include <ext/function_traits.h>
|
||||
|
||||
|
||||
/** The simplest cache for a free function.
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
#include <Common/Arena.h>
|
||||
#include <common/likely.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/size.hpp>
|
||||
#include <ext/bit_cast.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <ext/size.h>
|
||||
#include <ext/bit_cast.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Common/UTF8Helpers.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <Poco/UTF8Encoding.h>
|
||||
#include <Poco/Unicode.h>
|
||||
#include <stdint.h>
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <Core/Types.h>
|
||||
#include <Poco/UTF8Encoding.h>
|
||||
#include <Poco/Unicode.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <Common/hex.h>
|
||||
#include <Common/StringUtils.h>
|
||||
#include <Common/escapeForFileName.h>
|
||||
|
||||
@ -11,8 +11,6 @@ std::string escapeForFileName(const std::string & s)
|
||||
const char * pos = s.data();
|
||||
const char * end = pos + s.size();
|
||||
|
||||
static const char * hex = "0123456789ABCDEF";
|
||||
|
||||
while (pos != end)
|
||||
{
|
||||
char c = *pos;
|
||||
@ -22,8 +20,8 @@ std::string escapeForFileName(const std::string & s)
|
||||
else
|
||||
{
|
||||
res += '%';
|
||||
res += hex[c / 16];
|
||||
res += hex[c % 16];
|
||||
res += hexUppercase(c / 16);
|
||||
res += hexUppercase(c % 16);
|
||||
}
|
||||
|
||||
++pos;
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include <Common/hex.h>
|
||||
|
||||
const char * const char_to_digit_table = (
|
||||
const char * const hex_digit_to_char_uppercase_table = "0123456789ABCDEF";
|
||||
const char * const hex_digit_to_char_lowercase_table = "0123456789abcdef";
|
||||
|
||||
const char * const hex_char_to_digit_table =
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
@ -16,5 +19,4 @@ const char * const char_to_digit_table = (
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
);
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
|
@ -1,3 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
extern const char * const char_to_digit_table;
|
||||
|
||||
/// Maps 0..15 to 0..9A..F or 0..9a..f correspondingly.
|
||||
|
||||
extern const char * const hex_digit_to_char_uppercase_table;
|
||||
extern const char * const hex_digit_to_char_lowercase_table;
|
||||
|
||||
inline char hexUppercase(unsigned char c)
|
||||
{
|
||||
return hex_digit_to_char_uppercase_table[c];
|
||||
}
|
||||
|
||||
inline char hexLowercase(unsigned char c)
|
||||
{
|
||||
return hex_digit_to_char_lowercase_table[c];
|
||||
}
|
||||
|
||||
|
||||
/// Maps 0..9, A..F, a..f to 0..15. Other chars are mapped to implementation specific value.
|
||||
|
||||
extern const char * const hex_char_to_digit_table;
|
||||
|
||||
inline char unhex(char c)
|
||||
{
|
||||
return hex_char_to_digit_table[static_cast<unsigned char>(c)];
|
||||
}
|
||||
|
@ -11,8 +11,8 @@
|
||||
#include <memory>
|
||||
#include <array>
|
||||
#include <sys/resource.h>
|
||||
#include <ext/bit_cast.hpp>
|
||||
#include <ext/size.hpp>
|
||||
#include <ext/bit_cast.h>
|
||||
#include <ext/size.h>
|
||||
#include <Common/Arena.h>
|
||||
|
||||
#include <Core/StringRef.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <ext/bit_cast.hpp>
|
||||
#include <ext/bit_cast.h>
|
||||
#include <Common/RadixSort.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
|
@ -373,6 +373,9 @@ namespace ErrorCodes
|
||||
extern const int BAD_CAST = 368;
|
||||
extern const int ALL_REPLICAS_ARE_STALE = 369;
|
||||
extern const int DATA_TYPE_CANNOT_BE_USED_IN_TABLES = 370;
|
||||
extern const int SESSION_NOT_FOUND = 371;
|
||||
extern const int SESSION_IS_LOCKED = 372;
|
||||
extern const int INVALID_SESSION_TIMEOUT = 373;
|
||||
|
||||
extern const int KEEPER_EXCEPTION = 999;
|
||||
extern const int POCO_EXCEPTION = 1000;
|
||||
|
@ -195,7 +195,7 @@ protected:
|
||||
QuotaForIntervals * quota = nullptr; /// If nullptr - the quota is not used.
|
||||
double prev_elapsed = 0;
|
||||
|
||||
/// The heirs must implement this function.
|
||||
/// The successors must implement this function.
|
||||
virtual Block readImpl() = 0;
|
||||
|
||||
/// Here you can do a preliminary initialization.
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include <DataStreams/MaterializingBlockOutputStream.h>
|
||||
#include <DataTypes/DataTypeNullable.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -42,7 +42,7 @@ try
|
||||
chain.finalize();
|
||||
ExpressionActionsPtr expression = chain.getLastActions();
|
||||
|
||||
StoragePtr table = StorageSystemNumbers::create("Numbers");
|
||||
StoragePtr table = StorageSystemNumbers::create("numbers", false);
|
||||
|
||||
Names column_names;
|
||||
column_names.push_back("number");
|
||||
@ -50,7 +50,7 @@ try
|
||||
QueryProcessingStage::Enum stage;
|
||||
|
||||
BlockInputStreamPtr in;
|
||||
in = table->read(column_names, 0, context, stage)[0];
|
||||
in = table->read(column_names, 0, context, stage, 8192, 1)[0];
|
||||
in = std::make_shared<ExpressionBlockInputStream>(in, expression);
|
||||
in = std::make_shared<LimitBlockInputStream>(in, 10, std::max(static_cast<Int64>(0), static_cast<Int64>(n) - 10));
|
||||
|
||||
|
@ -48,14 +48,14 @@ try
|
||||
chain.finalize();
|
||||
ExpressionActionsPtr expression = chain.getLastActions();
|
||||
|
||||
StoragePtr table = StorageSystemNumbers::create("Numbers");
|
||||
StoragePtr table = StorageSystemNumbers::create("numbers", false);
|
||||
|
||||
Names column_names;
|
||||
column_names.push_back("number");
|
||||
|
||||
QueryProcessingStage::Enum stage;
|
||||
|
||||
BlockInputStreamPtr in = table->read(column_names, 0, context, stage)[0];
|
||||
BlockInputStreamPtr in = table->read(column_names, 0, context, stage, 8192, 1)[0];
|
||||
in = std::make_shared<FilterBlockInputStream>(in, expression, 1);
|
||||
in = std::make_shared<LimitBlockInputStream>(in, 10, std::max(static_cast<Int64>(0), static_cast<Int64>(n) - 10));
|
||||
|
||||
|
@ -35,62 +35,62 @@ int main(int argc, char ** argv)
|
||||
{
|
||||
NamesAndTypesList names_and_types_list
|
||||
{
|
||||
{"WatchID", std::make_shared<DataTypeUInt64>()},
|
||||
{"JavaEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"Title", std::make_shared<DataTypeString>()},
|
||||
{"EventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"CounterID", std::make_shared<DataTypeUInt32>()},
|
||||
{"ClientIP", std::make_shared<DataTypeUInt32>()},
|
||||
{"RegionID", std::make_shared<DataTypeUInt32>()},
|
||||
{"UniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"CounterClass", std::make_shared<DataTypeUInt8>()},
|
||||
{"OS", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgent", std::make_shared<DataTypeUInt8>()},
|
||||
{"URL", std::make_shared<DataTypeString>()},
|
||||
{"Referer", std::make_shared<DataTypeString>()},
|
||||
{"ResolutionWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionDepth", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor2", std::make_shared<DataTypeString>()},
|
||||
{"NetMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"NetMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgentMajor", std::make_shared<DataTypeUInt16>()},
|
||||
{"UserAgentMinor", std::make_shared<DataTypeFixedString>(2)},
|
||||
{"CookieEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"JavascriptEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsMobile", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhone", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhoneModel", std::make_shared<DataTypeString>()},
|
||||
{"Params", std::make_shared<DataTypeString>()},
|
||||
{"IPNetworkID", std::make_shared<DataTypeUInt32>()},
|
||||
{"TraficSourceID", std::make_shared<DataTypeInt8>()},
|
||||
{"SearchEngineID", std::make_shared<DataTypeUInt16>()},
|
||||
{"SearchPhrase", std::make_shared<DataTypeString>()},
|
||||
{"AdvEngineID", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsArtifical", std::make_shared<DataTypeUInt8>()},
|
||||
{"WindowClientWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"WindowClientHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ClientTimeZone", std::make_shared<DataTypeInt16>()},
|
||||
{"ClientEventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"SilverlightVersion1", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion2", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion3", std::make_shared<DataTypeUInt32>()},
|
||||
{"SilverlightVersion4", std::make_shared<DataTypeUInt16>()},
|
||||
{"PageCharset", std::make_shared<DataTypeString>()},
|
||||
{"CodeVersion", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsLink", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsDownload", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsNotBounce", std::make_shared<DataTypeUInt8>()},
|
||||
{"FUniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"OriginalURL", std::make_shared<DataTypeString>()},
|
||||
{"HID", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsOldCounter", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsEvent", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsParameter", std::make_shared<DataTypeUInt8>()},
|
||||
{"DontCountHits", std::make_shared<DataTypeUInt8>()},
|
||||
{"WithHash", std::make_shared<DataTypeUInt8>()},
|
||||
{"WatchID", std::make_shared<DataTypeUInt64>()},
|
||||
{"JavaEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"Title", std::make_shared<DataTypeString>()},
|
||||
{"EventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"CounterID", std::make_shared<DataTypeUInt32>()},
|
||||
{"ClientIP", std::make_shared<DataTypeUInt32>()},
|
||||
{"RegionID", std::make_shared<DataTypeUInt32>()},
|
||||
{"UniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"CounterClass", std::make_shared<DataTypeUInt8>()},
|
||||
{"OS", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgent", std::make_shared<DataTypeUInt8>()},
|
||||
{"URL", std::make_shared<DataTypeString>()},
|
||||
{"Referer", std::make_shared<DataTypeString>()},
|
||||
{"ResolutionWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionDepth", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor2", std::make_shared<DataTypeString>()},
|
||||
{"NetMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"NetMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgentMajor", std::make_shared<DataTypeUInt16>()},
|
||||
{"UserAgentMinor", std::make_shared<DataTypeFixedString>(2)},
|
||||
{"CookieEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"JavascriptEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsMobile", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhone", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhoneModel", std::make_shared<DataTypeString>()},
|
||||
{"Params", std::make_shared<DataTypeString>()},
|
||||
{"IPNetworkID", std::make_shared<DataTypeUInt32>()},
|
||||
{"TraficSourceID", std::make_shared<DataTypeInt8>()},
|
||||
{"SearchEngineID", std::make_shared<DataTypeUInt16>()},
|
||||
{"SearchPhrase", std::make_shared<DataTypeString>()},
|
||||
{"AdvEngineID", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsArtifical", std::make_shared<DataTypeUInt8>()},
|
||||
{"WindowClientWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"WindowClientHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ClientTimeZone", std::make_shared<DataTypeInt16>()},
|
||||
{"ClientEventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"SilverlightVersion1", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion2", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion3", std::make_shared<DataTypeUInt32>()},
|
||||
{"SilverlightVersion4", std::make_shared<DataTypeUInt16>()},
|
||||
{"PageCharset", std::make_shared<DataTypeString>()},
|
||||
{"CodeVersion", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsLink", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsDownload", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsNotBounce", std::make_shared<DataTypeUInt8>()},
|
||||
{"FUniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"OriginalURL", std::make_shared<DataTypeString>()},
|
||||
{"HID", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsOldCounter", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsEvent", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsParameter", std::make_shared<DataTypeUInt8>()},
|
||||
{"DontCountHits", std::make_shared<DataTypeUInt8>()},
|
||||
{"WithHash", std::make_shared<DataTypeUInt8>()},
|
||||
};
|
||||
|
||||
Context context;
|
||||
@ -105,7 +105,9 @@ int main(int argc, char ** argv)
|
||||
|
||||
/// create an object of an existing hit log table
|
||||
|
||||
StoragePtr table = StorageLog::create("./", "HitLog", std::make_shared<NamesAndTypesList>(names_and_types_list));
|
||||
StoragePtr table = StorageLog::create("./", "HitLog", std::make_shared<NamesAndTypesList>(names_and_types_list),
|
||||
NamesAndTypesList{}, NamesAndTypesList{}, ColumnDefaults{}, DEFAULT_MAX_COMPRESS_BLOCK_SIZE);
|
||||
table->startup();
|
||||
|
||||
/// read from it, apply the expression, filter, and write in tsv form to the console
|
||||
|
||||
@ -126,7 +128,7 @@ int main(int argc, char ** argv)
|
||||
|
||||
QueryProcessingStage::Enum stage;
|
||||
|
||||
BlockInputStreamPtr in = table->read(column_names, 0, context, stage)[0];
|
||||
BlockInputStreamPtr in = table->read(column_names, 0, context, stage, 8192, 1)[0];
|
||||
in = std::make_shared<FilterBlockInputStream>(in, expression, 4);
|
||||
//in = std::make_shared<LimitBlockInputStream>(in, 10, 0);
|
||||
|
||||
|
@ -65,14 +65,14 @@ try
|
||||
chain.finalize();
|
||||
ExpressionActionsPtr expression = chain.getLastActions();
|
||||
|
||||
StoragePtr table = StorageSystemNumbers::create("Numbers");
|
||||
StoragePtr table = StorageSystemNumbers::create("numbers", false);
|
||||
|
||||
Names column_names;
|
||||
column_names.push_back("number");
|
||||
|
||||
QueryProcessingStage::Enum stage;
|
||||
|
||||
BlockInputStreamPtr in = table->read(column_names, 0, context, stage)[0];
|
||||
BlockInputStreamPtr in = table->read(column_names, 0, context, stage, 8192, 1)[0];
|
||||
|
||||
ForkBlockInputStreams fork(in);
|
||||
|
||||
|
@ -30,62 +30,62 @@ try
|
||||
|
||||
NamesAndTypesList names_and_types_list
|
||||
{
|
||||
{"WatchID", std::make_shared<DataTypeUInt64>()},
|
||||
{"JavaEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"Title", std::make_shared<DataTypeString>()},
|
||||
{"EventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"CounterID", std::make_shared<DataTypeUInt32>()},
|
||||
{"ClientIP", std::make_shared<DataTypeUInt32>()},
|
||||
{"RegionID", std::make_shared<DataTypeUInt32>()},
|
||||
{"UniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"CounterClass", std::make_shared<DataTypeUInt8>()},
|
||||
{"OS", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgent", std::make_shared<DataTypeUInt8>()},
|
||||
{"URL", std::make_shared<DataTypeString>()},
|
||||
{"Referer", std::make_shared<DataTypeString>()},
|
||||
{"ResolutionWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionDepth", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor2", std::make_shared<DataTypeString>()},
|
||||
{"NetMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"NetMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgentMajor", std::make_shared<DataTypeUInt16>()},
|
||||
{"UserAgentMinor", std::make_shared<DataTypeFixedString>(2)},
|
||||
{"CookieEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"JavascriptEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsMobile", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhone", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhoneModel", std::make_shared<DataTypeString>()},
|
||||
{"Params", std::make_shared<DataTypeString>()},
|
||||
{"IPNetworkID", std::make_shared<DataTypeUInt32>()},
|
||||
{"TraficSourceID", std::make_shared<DataTypeInt8>()},
|
||||
{"SearchEngineID", std::make_shared<DataTypeUInt16>()},
|
||||
{"SearchPhrase", std::make_shared<DataTypeString>()},
|
||||
{"AdvEngineID", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsArtifical", std::make_shared<DataTypeUInt8>()},
|
||||
{"WindowClientWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"WindowClientHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ClientTimeZone", std::make_shared<DataTypeInt16>()},
|
||||
{"ClientEventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"SilverlightVersion1", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion2", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion3", std::make_shared<DataTypeUInt32>()},
|
||||
{"SilverlightVersion4", std::make_shared<DataTypeUInt16>()},
|
||||
{"PageCharset", std::make_shared<DataTypeString>()},
|
||||
{"CodeVersion", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsLink", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsDownload", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsNotBounce", std::make_shared<DataTypeUInt8>()},
|
||||
{"FUniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"OriginalURL", std::make_shared<DataTypeString>()},
|
||||
{"HID", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsOldCounter", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsEvent", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsParameter", std::make_shared<DataTypeUInt8>()},
|
||||
{"DontCountHits", std::make_shared<DataTypeUInt8>()},
|
||||
{"WithHash", std::make_shared<DataTypeUInt8>()},
|
||||
{"WatchID", std::make_shared<DataTypeUInt64>()},
|
||||
{"JavaEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"Title", std::make_shared<DataTypeString>()},
|
||||
{"EventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"CounterID", std::make_shared<DataTypeUInt32>()},
|
||||
{"ClientIP", std::make_shared<DataTypeUInt32>()},
|
||||
{"RegionID", std::make_shared<DataTypeUInt32>()},
|
||||
{"UniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"CounterClass", std::make_shared<DataTypeUInt8>()},
|
||||
{"OS", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgent", std::make_shared<DataTypeUInt8>()},
|
||||
{"URL", std::make_shared<DataTypeString>()},
|
||||
{"Referer", std::make_shared<DataTypeString>()},
|
||||
{"ResolutionWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionDepth", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor2", std::make_shared<DataTypeString>()},
|
||||
{"NetMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"NetMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgentMajor", std::make_shared<DataTypeUInt16>()},
|
||||
{"UserAgentMinor", std::make_shared<DataTypeFixedString>(2)},
|
||||
{"CookieEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"JavascriptEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsMobile", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhone", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhoneModel", std::make_shared<DataTypeString>()},
|
||||
{"Params", std::make_shared<DataTypeString>()},
|
||||
{"IPNetworkID", std::make_shared<DataTypeUInt32>()},
|
||||
{"TraficSourceID", std::make_shared<DataTypeInt8>()},
|
||||
{"SearchEngineID", std::make_shared<DataTypeUInt16>()},
|
||||
{"SearchPhrase", std::make_shared<DataTypeString>()},
|
||||
{"AdvEngineID", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsArtifical", std::make_shared<DataTypeUInt8>()},
|
||||
{"WindowClientWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"WindowClientHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ClientTimeZone", std::make_shared<DataTypeInt16>()},
|
||||
{"ClientEventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"SilverlightVersion1", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion2", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion3", std::make_shared<DataTypeUInt32>()},
|
||||
{"SilverlightVersion4", std::make_shared<DataTypeUInt16>()},
|
||||
{"PageCharset", std::make_shared<DataTypeString>()},
|
||||
{"CodeVersion", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsLink", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsDownload", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsNotBounce", std::make_shared<DataTypeUInt8>()},
|
||||
{"FUniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"OriginalURL", std::make_shared<DataTypeString>()},
|
||||
{"HID", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsOldCounter", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsEvent", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsParameter", std::make_shared<DataTypeUInt8>()},
|
||||
{"DontCountHits", std::make_shared<DataTypeUInt8>()},
|
||||
{"WithHash", std::make_shared<DataTypeUInt8>()},
|
||||
};
|
||||
|
||||
Names column_names;
|
||||
@ -95,13 +95,15 @@ try
|
||||
|
||||
/// create an object of an existing hit log table
|
||||
|
||||
StoragePtr table = StorageLog::create("./", "HitLog", std::make_shared<NamesAndTypesList>(names_and_types_list));
|
||||
StoragePtr table = StorageLog::create("./", "HitLog", std::make_shared<NamesAndTypesList>(names_and_types_list),
|
||||
NamesAndTypesList{}, NamesAndTypesList{}, ColumnDefaults{}, DEFAULT_MAX_COMPRESS_BLOCK_SIZE);
|
||||
table->startup();
|
||||
|
||||
/// read from it
|
||||
if (argc == 2 && 0 == strcmp(argv[1], "read"))
|
||||
{
|
||||
QueryProcessingStage::Enum stage;
|
||||
BlockInputStreamPtr in = table->read(column_names, 0, Context{}, stage)[0];
|
||||
BlockInputStreamPtr in = table->read(column_names, 0, Context{}, stage, 8192, 1)[0];
|
||||
WriteBufferFromFileDescriptor out1(STDOUT_FILENO);
|
||||
CompressedWriteBuffer out2(out1);
|
||||
NativeBlockOutputStream out3(out2, ClickHouseRevision::get());
|
||||
|
@ -34,62 +34,62 @@ try
|
||||
{
|
||||
NamesAndTypesList names_and_types_list
|
||||
{
|
||||
{"WatchID", std::make_shared<DataTypeUInt64>()},
|
||||
{"JavaEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"Title", std::make_shared<DataTypeString>()},
|
||||
{"EventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"CounterID", std::make_shared<DataTypeUInt32>()},
|
||||
{"ClientIP", std::make_shared<DataTypeUInt32>()},
|
||||
{"RegionID", std::make_shared<DataTypeUInt32>()},
|
||||
{"UniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"CounterClass", std::make_shared<DataTypeUInt8>()},
|
||||
{"OS", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgent", std::make_shared<DataTypeUInt8>()},
|
||||
{"URL", std::make_shared<DataTypeString>()},
|
||||
{"Referer", std::make_shared<DataTypeString>()},
|
||||
{"ResolutionWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionDepth", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor2", std::make_shared<DataTypeString>()},
|
||||
{"NetMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"NetMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgentMajor", std::make_shared<DataTypeUInt16>()},
|
||||
{"UserAgentMinor", std::make_shared<DataTypeFixedString>(2)},
|
||||
{"CookieEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"JavascriptEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsMobile", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhone", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhoneModel", std::make_shared<DataTypeString>()},
|
||||
{"Params", std::make_shared<DataTypeString>()},
|
||||
{"IPNetworkID", std::make_shared<DataTypeUInt32>()},
|
||||
{"TraficSourceID", std::make_shared<DataTypeInt8>()},
|
||||
{"SearchEngineID", std::make_shared<DataTypeUInt16>()},
|
||||
{"SearchPhrase", std::make_shared<DataTypeString>()},
|
||||
{"AdvEngineID", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsArtifical", std::make_shared<DataTypeUInt8>()},
|
||||
{"WindowClientWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"WindowClientHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ClientTimeZone", std::make_shared<DataTypeInt16>()},
|
||||
{"ClientEventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"SilverlightVersion1", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion2", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion3", std::make_shared<DataTypeUInt32>()},
|
||||
{"SilverlightVersion4", std::make_shared<DataTypeUInt16>()},
|
||||
{"PageCharset", std::make_shared<DataTypeString>()},
|
||||
{"CodeVersion", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsLink", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsDownload", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsNotBounce", std::make_shared<DataTypeUInt8>()},
|
||||
{"FUniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"OriginalURL", std::make_shared<DataTypeString>()},
|
||||
{"HID", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsOldCounter", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsEvent", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsParameter", std::make_shared<DataTypeUInt8>()},
|
||||
{"DontCountHits", std::make_shared<DataTypeUInt8>()},
|
||||
{"WithHash", std::make_shared<DataTypeUInt8>()},
|
||||
{"WatchID", std::make_shared<DataTypeUInt64>()},
|
||||
{"JavaEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"Title", std::make_shared<DataTypeString>()},
|
||||
{"EventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"CounterID", std::make_shared<DataTypeUInt32>()},
|
||||
{"ClientIP", std::make_shared<DataTypeUInt32>()},
|
||||
{"RegionID", std::make_shared<DataTypeUInt32>()},
|
||||
{"UniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"CounterClass", std::make_shared<DataTypeUInt8>()},
|
||||
{"OS", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgent", std::make_shared<DataTypeUInt8>()},
|
||||
{"URL", std::make_shared<DataTypeString>()},
|
||||
{"Referer", std::make_shared<DataTypeString>()},
|
||||
{"ResolutionWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ResolutionDepth", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"FlashMinor2", std::make_shared<DataTypeString>()},
|
||||
{"NetMajor", std::make_shared<DataTypeUInt8>()},
|
||||
{"NetMinor", std::make_shared<DataTypeUInt8>()},
|
||||
{"UserAgentMajor", std::make_shared<DataTypeUInt16>()},
|
||||
{"UserAgentMinor", std::make_shared<DataTypeFixedString>(2)},
|
||||
{"CookieEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"JavascriptEnable", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsMobile", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhone", std::make_shared<DataTypeUInt8>()},
|
||||
{"MobilePhoneModel", std::make_shared<DataTypeString>()},
|
||||
{"Params", std::make_shared<DataTypeString>()},
|
||||
{"IPNetworkID", std::make_shared<DataTypeUInt32>()},
|
||||
{"TraficSourceID", std::make_shared<DataTypeInt8>()},
|
||||
{"SearchEngineID", std::make_shared<DataTypeUInt16>()},
|
||||
{"SearchPhrase", std::make_shared<DataTypeString>()},
|
||||
{"AdvEngineID", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsArtifical", std::make_shared<DataTypeUInt8>()},
|
||||
{"WindowClientWidth", std::make_shared<DataTypeUInt16>()},
|
||||
{"WindowClientHeight", std::make_shared<DataTypeUInt16>()},
|
||||
{"ClientTimeZone", std::make_shared<DataTypeInt16>()},
|
||||
{"ClientEventTime", std::make_shared<DataTypeDateTime>()},
|
||||
{"SilverlightVersion1", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion2", std::make_shared<DataTypeUInt8>()},
|
||||
{"SilverlightVersion3", std::make_shared<DataTypeUInt32>()},
|
||||
{"SilverlightVersion4", std::make_shared<DataTypeUInt16>()},
|
||||
{"PageCharset", std::make_shared<DataTypeString>()},
|
||||
{"CodeVersion", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsLink", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsDownload", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsNotBounce", std::make_shared<DataTypeUInt8>()},
|
||||
{"FUniqID", std::make_shared<DataTypeUInt64>()},
|
||||
{"OriginalURL", std::make_shared<DataTypeString>()},
|
||||
{"HID", std::make_shared<DataTypeUInt32>()},
|
||||
{"IsOldCounter", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsEvent", std::make_shared<DataTypeUInt8>()},
|
||||
{"IsParameter", std::make_shared<DataTypeUInt8>()},
|
||||
{"DontCountHits", std::make_shared<DataTypeUInt8>()},
|
||||
{"WithHash", std::make_shared<DataTypeUInt8>()},
|
||||
};
|
||||
|
||||
using NamesAndTypesMap = std::map<String, DataTypePtr>;
|
||||
@ -107,7 +107,9 @@ try
|
||||
|
||||
/// create an object of an existing hit log table
|
||||
|
||||
StoragePtr table = StorageLog::create("./", "HitLog", std::make_shared<NamesAndTypesList>(names_and_types_list));
|
||||
StoragePtr table = StorageLog::create("./", "HitLog", std::make_shared<NamesAndTypesList>(names_and_types_list),
|
||||
NamesAndTypesList{}, NamesAndTypesList{}, ColumnDefaults{}, DEFAULT_MAX_COMPRESS_BLOCK_SIZE);
|
||||
table->startup();
|
||||
|
||||
/// read from it, sort it, and write it in tsv form to the console
|
||||
|
||||
@ -143,7 +145,7 @@ try
|
||||
|
||||
QueryProcessingStage::Enum stage;
|
||||
|
||||
BlockInputStreamPtr in = table->read(column_names, 0, Context{}, stage, argc == 2 ? atoi(argv[1]) : 1048576)[0];
|
||||
BlockInputStreamPtr in = table->read(column_names, 0, Context{}, stage, argc == 2 ? atoi(argv[1]) : 65536, 1)[0];
|
||||
in = std::make_shared<PartialSortingBlockInputStream>(in, sort_columns);
|
||||
in = std::make_shared<MergeSortingBlockInputStream>(in, sort_columns, DEFAULT_BLOCK_SIZE, 0, 0, "");
|
||||
//in = std::make_shared<LimitBlockInputStream>(in, 10, 0);
|
||||
|
@ -25,7 +25,7 @@ using namespace DB;
|
||||
void test1()
|
||||
{
|
||||
Context context;
|
||||
StoragePtr table = StorageSystemNumbers::create("numbers");
|
||||
StoragePtr table = StorageSystemNumbers::create("numbers", false);
|
||||
|
||||
Names column_names;
|
||||
column_names.push_back("number");
|
||||
@ -35,9 +35,9 @@ void test1()
|
||||
QueryProcessingStage::Enum stage3;
|
||||
|
||||
BlockInputStreams streams;
|
||||
streams.emplace_back(std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage1, 1)[0], 30, 30000));
|
||||
streams.emplace_back(std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage2, 1)[0], 30, 2000));
|
||||
streams.emplace_back(std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage3, 1)[0], 30, 100));
|
||||
streams.emplace_back(std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage1, 1, 1)[0], 30, 30000));
|
||||
streams.emplace_back(std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage2, 1, 1)[0], 30, 2000));
|
||||
streams.emplace_back(std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage3, 1, 1)[0], 30, 100));
|
||||
|
||||
UnionBlockInputStream<> union_stream(streams, nullptr, 2);
|
||||
|
||||
@ -50,13 +50,12 @@ void test1()
|
||||
out->write(block);
|
||||
wb.next();
|
||||
}
|
||||
//copyData(union_stream, *out);
|
||||
}
|
||||
|
||||
void test2()
|
||||
{
|
||||
Context context;
|
||||
StoragePtr table = StorageSystemNumbers::create("numbers");
|
||||
StoragePtr table = StorageSystemNumbers::create("numbers", false);
|
||||
|
||||
Names column_names;
|
||||
column_names.push_back("number");
|
||||
@ -85,15 +84,15 @@ void test2()
|
||||
|
||||
BlockInputStreams streams;
|
||||
|
||||
BlockInputStreamPtr stream1 = std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage1, 1)[0], 30, 30000);
|
||||
BlockInputStreamPtr stream1 = std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage1, 1, 1)[0], 30, 30000);
|
||||
stream1 = std::make_shared<BlockExtraInfoInputStream>(stream1, extra_info1);
|
||||
streams.emplace_back(stream1);
|
||||
|
||||
BlockInputStreamPtr stream2 = std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage2, 1)[0], 30, 2000);
|
||||
BlockInputStreamPtr stream2 = std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage2, 1, 1)[0], 30, 2000);
|
||||
stream2 = std::make_shared<BlockExtraInfoInputStream>(stream2, extra_info2);
|
||||
streams.emplace_back(stream2);
|
||||
|
||||
BlockInputStreamPtr stream3 = std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage3, 1)[0], 30, 100);
|
||||
BlockInputStreamPtr stream3 = std::make_shared<LimitBlockInputStream>(table->read(column_names, 0, context, stage3, 1, 1)[0], 30, 100);
|
||||
stream3 = std::make_shared<BlockExtraInfoInputStream>(stream3, extra_info3);
|
||||
streams.emplace_back(stream3);
|
||||
|
||||
@ -165,7 +164,6 @@ void test2()
|
||||
out->write(out_block);
|
||||
wb.next();
|
||||
}
|
||||
//copyData(union_stream, *out);
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
|
@ -1,11 +1,12 @@
|
||||
#include <DataStreams/verbosePrintString.h>
|
||||
#include <Common/hex.h>
|
||||
#include <IO/Operators.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
void verbosePrintString(BufferBase::Position begin, BufferBase::Position end, WriteBuffer & out)
|
||||
void verbosePrintString(const char * begin, const char * end, WriteBuffer & out)
|
||||
{
|
||||
if (end == begin)
|
||||
{
|
||||
@ -50,10 +51,7 @@ void verbosePrintString(BufferBase::Position begin, BufferBase::Position end, Wr
|
||||
default:
|
||||
{
|
||||
if (*pos >= 0 && *pos < 32)
|
||||
{
|
||||
static const char * hex = "0123456789ABCDEF";
|
||||
out << "<0x" << hex[*pos / 16] << hex[*pos % 16] << ">";
|
||||
}
|
||||
out << "<0x" << hexUppercase(*pos / 16) << hexUppercase(*pos % 16) << ">";
|
||||
else
|
||||
out << *pos;
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <IO/WriteBuffer.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
class WriteBuffer;
|
||||
|
||||
|
||||
/** Print string in double quotes and with control characters in "<NAME>" form - for output diagnostic info to user.
|
||||
*/
|
||||
void verbosePrintString(BufferBase::Position begin, BufferBase::Position end, WriteBuffer & out);
|
||||
void verbosePrintString(const char * begin, const char * end, WriteBuffer & out);
|
||||
|
||||
}
|
||||
|
@ -125,16 +125,16 @@ void DataTypeArray::serializeBinaryBulk(const IColumn & column, WriteBuffer & os
|
||||
}
|
||||
|
||||
|
||||
void DataTypeArray::deserializeBinaryBulk(IColumn & column, ReadBuffer & istr, size_t limit, double avg_value_size_hint) const
|
||||
void DataTypeArray::deserializeBinaryBulk(IColumn & column, ReadBuffer & istr, size_t limit, double) const
|
||||
{
|
||||
ColumnArray & column_array = typeid_cast<ColumnArray &>(column);
|
||||
ColumnArray::Offsets_t & offsets = column_array.getOffsets();
|
||||
IColumn & nested_column = column_array.getData();
|
||||
|
||||
/// Number of values correlated with `offsets` must be read.
|
||||
/// Number of values corresponding with `offsets` must be read.
|
||||
size_t last_offset = (offsets.empty() ? 0 : offsets.back());
|
||||
if (last_offset < nested_column.size())
|
||||
throw Exception("Nested column longer than last offset", ErrorCodes::LOGICAL_ERROR);
|
||||
throw Exception("Nested column is longer than last offset", ErrorCodes::LOGICAL_ERROR);
|
||||
size_t nested_limit = last_offset - nested_column.size();
|
||||
nested->deserializeBinaryBulk(nested_column, istr, nested_limit, 0);
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <Parsers/parseQuery.h>
|
||||
#include <DataTypes/DataTypeEnum.h>
|
||||
|
||||
#include <ext/map.hpp>
|
||||
#include <ext/map.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -184,11 +184,11 @@ void DataTypeString::deserializeBinaryBulk(IColumn & column, ReadBuffer & istr,
|
||||
}
|
||||
else
|
||||
{
|
||||
/** A small heuristic to evaluate that there are a lot of empty lines in the column.
|
||||
/** A small heuristic to evaluate that there are a lot of empty strings in the column.
|
||||
* In this case, to save RAM, we will say that the average size of the value is small.
|
||||
*/
|
||||
if (istr.position() + sizeof(UInt32) <= istr.buffer().end()
|
||||
&& unalignedLoad<UInt32>(istr.position()) == 0) /// The first 4 rows are in the buffer and are empty.
|
||||
&& unalignedLoad<UInt32>(istr.position()) == 0) /// The first 4 strings are in the buffer and are empty.
|
||||
{
|
||||
avg_chars_size = 1;
|
||||
}
|
||||
|
@ -4,9 +4,9 @@
|
||||
#include <DataStreams/NativeBlockOutputStream.h>
|
||||
#include <DataTypes/DataTypeTuple.h>
|
||||
|
||||
#include <ext/map.hpp>
|
||||
#include <ext/enumerate.hpp>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/map.h>
|
||||
#include <ext/enumerate.h>
|
||||
#include <ext/range.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <DataTypes/DataTypeArray.h>
|
||||
#include <DataTypes/DataTypeNull.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <ext/size.hpp>
|
||||
#include <ext/size.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -414,6 +414,8 @@ StoragePtr DatabaseCloud::tryGetTable(const String & table_name)
|
||||
definition, name, data_path, context, false,
|
||||
"in zookeeper node " + zookeeper_path + "/table_definitions/" + hashToHex(table_hash));
|
||||
|
||||
table->startup();
|
||||
|
||||
local_tables_cache.emplace(table_name, table);
|
||||
return table;
|
||||
}
|
||||
|
@ -181,6 +181,60 @@ void DatabaseOrdinary::loadTables(Context & context, ThreadPool * thread_pool, b
|
||||
task();
|
||||
}
|
||||
|
||||
if (thread_pool)
|
||||
thread_pool->wait();
|
||||
|
||||
/// After all tables was basically initialized, startup them.
|
||||
startupTables(thread_pool);
|
||||
}
|
||||
|
||||
|
||||
void DatabaseOrdinary::startupTables(ThreadPool * thread_pool)
|
||||
{
|
||||
LOG_INFO(log, "Starting up tables.");
|
||||
|
||||
StopwatchWithLock watch;
|
||||
std::atomic<size_t> tables_processed {0};
|
||||
size_t total_tables = tables.size();
|
||||
|
||||
auto task_function = [&](Tables::iterator begin, Tables::iterator end)
|
||||
{
|
||||
for (Tables::iterator it = begin; it != end; ++it)
|
||||
{
|
||||
if ((++tables_processed) % PRINT_MESSAGE_EACH_N_TABLES == 0
|
||||
|| watch.lockTestAndRestart(PRINT_MESSAGE_EACH_N_SECONDS))
|
||||
{
|
||||
LOG_INFO(log, std::fixed << std::setprecision(2) << tables_processed * 100.0 / total_tables << "%");
|
||||
watch.restart();
|
||||
}
|
||||
|
||||
it->second->startup();
|
||||
}
|
||||
};
|
||||
|
||||
const size_t bunch_size = TABLES_PARALLEL_LOAD_BUNCH_SIZE;
|
||||
size_t num_bunches = (total_tables + bunch_size - 1) / bunch_size;
|
||||
|
||||
Tables::iterator begin = tables.begin();
|
||||
for (size_t i = 0; i < num_bunches; ++i)
|
||||
{
|
||||
auto end = begin;
|
||||
|
||||
if (i + 1 == num_bunches)
|
||||
end = tables.end();
|
||||
else
|
||||
std::advance(end, bunch_size);
|
||||
|
||||
auto task = std::bind(task_function, begin, end);
|
||||
|
||||
if (thread_pool)
|
||||
thread_pool->schedule(task);
|
||||
else
|
||||
task();
|
||||
|
||||
begin = end;
|
||||
}
|
||||
|
||||
if (thread_pool)
|
||||
thread_pool->wait();
|
||||
}
|
||||
|
@ -45,6 +45,9 @@ public:
|
||||
const NamesAndTypesList & alias_columns,
|
||||
const ColumnDefaults & column_defaults,
|
||||
const ASTModifier & engine_modifier) override;
|
||||
|
||||
private:
|
||||
void startupTables(ThreadPool * thread_pool);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ String getTableDefinitionFromCreateQuery(const ASTPtr & query);
|
||||
/** Create a table by its definition, without using InterpreterCreateQuery.
|
||||
* (InterpreterCreateQuery has more complex functionality, and it can not be used if the database has not been created yet)
|
||||
* Returns the table name and the table itself.
|
||||
* You must subsequently call IStorage::startup method to use the table.
|
||||
*/
|
||||
std::pair<String, StoragePtr> createTableFromDefinition(
|
||||
const String & definition,
|
||||
|
@ -14,9 +14,9 @@
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <Dictionaries/CacheDictionary.h>
|
||||
#include <Dictionaries/DictionaryBlockInputStream.h>
|
||||
#include <ext/size.hpp>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/map.hpp>
|
||||
#include <ext/size.h>
|
||||
#include <ext/range.h>
|
||||
#include <ext/map.h>
|
||||
|
||||
|
||||
namespace ProfileEvents
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <Common/ArenaWithFreeLists.h>
|
||||
#include <Common/CurrentMetrics.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <ext/bit_cast.hpp>
|
||||
#include <ext/bit_cast.h>
|
||||
#include <Poco/RWLock.h>
|
||||
#include <cmath>
|
||||
#include <atomic>
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <Interpreters/executeQuery.h>
|
||||
#include <Common/isLocalAddress.h>
|
||||
#include <memory>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <Common/ProfilingScopedRWLock.h>
|
||||
#include <Common/ProfileEvents.h>
|
||||
#include <Common/CurrentMetrics.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
|
||||
|
||||
namespace ProfileEvents
|
||||
|
@ -9,9 +9,9 @@
|
||||
#include <Common/HashTable/HashMap.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Core/StringRef.h>
|
||||
#include <ext/scope_guard.hpp>
|
||||
#include <ext/bit_cast.hpp>
|
||||
#include <ext/map.hpp>
|
||||
#include <ext/scope_guard.h>
|
||||
#include <ext/bit_cast.h>
|
||||
#include <ext/map.h>
|
||||
#include <Poco/RWLock.h>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <ext/map.hpp>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/map.h>
|
||||
#include <ext/range.h>
|
||||
#include <Dictionaries/ComplexKeyHashedDictionary.h>
|
||||
#include <Dictionaries/DictionaryBlockInputStream.h>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <Common/HashTable/HashMap.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Common/Arena.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <IO/WriteBuffer.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <Poco/Util/AbstractConfiguration.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <boost/range/join.hpp>
|
||||
#include <IO/WriteBuffer.h>
|
||||
#include <IO/WriteBufferFromString.h>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <Dictionaries/ExternalResultDescription.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <DataTypes/DataTypeString.h>
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include <Dictionaries/DictionaryStructure.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Common/Arena.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/size.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <ext/size.h>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <ext/size.hpp>
|
||||
#include <ext/size.h>
|
||||
#include <Dictionaries/HashedDictionary.h>
|
||||
#include <Dictionaries/DictionaryBlockInputStream.h>
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <Dictionaries/DictionaryStructure.h>
|
||||
#include <Common/HashTable/HashMap.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <DataTypes/DataTypeDateTime.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Columns/ColumnsNumber.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <Core/FieldVisitors.h>
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <Dictionaries/MongoDBDictionarySource.h>
|
||||
#include <Dictionaries/MongoDBBlockInputStream.h>
|
||||
#include <Core/FieldVisitors.h>
|
||||
#include <ext/enumerate.hpp>
|
||||
#include <ext/enumerate.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <Dictionaries/MySQLBlockInputStream.h>
|
||||
#include <Columns/ColumnsNumber.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <Dictionaries/IDictionarySource.h>
|
||||
#include <Dictionaries/ExternalQueryBuilder.h>
|
||||
#include <Dictionaries/DictionaryStructure.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <mysqlxx/PoolWithFailover.h>
|
||||
#include <Poco/Util/AbstractConfiguration.h>
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <Columns/ColumnString.h>
|
||||
|
||||
#include <common/logger_useful.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <Dictionaries/DictionaryStructure.h>
|
||||
#include <Common/HashTable/HashMap.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <stack>
|
||||
#include <ext/map.hpp>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/map.h>
|
||||
#include <ext/range.h>
|
||||
#include <Poco/Net/IPAddress.h>
|
||||
#include <Poco/ByteOrder.h>
|
||||
#include <Dictionaries/TrieDictionary.h>
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <Common/HashTable/HashMap.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Common/Arena.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <btrie.h>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <Functions/ObjectPool.h>
|
||||
#include <Common/StringUtils.h>
|
||||
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <numeric>
|
||||
@ -35,28 +35,29 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
|
||||
/** Функции по работе с массивами:
|
||||
/** Array functions:
|
||||
*
|
||||
* array(с1, с2, ...) - создать массив из констант.
|
||||
* arrayElement(arr, i) - получить элемент массива по индексу.
|
||||
* Индекс начинается с 1. Также индекс может быть отрицательным - тогда он считается с конца массива.
|
||||
* has(arr, x) - есть ли в массиве элемент x.
|
||||
* indexOf(arr, x) - возвращает индекс элемента x (начиная с 1), если он есть в массиве, или 0, если его нет.
|
||||
* arrayEnumerate(arr) - возаращает массив [1,2,3,..., length(arr)]
|
||||
* array(c1, c2, ...) - create an array.
|
||||
* arrayElement(arr, i) - get the array element by index. If index is not constant and out of range - return default value of data type.
|
||||
* The index begins with 1. Also, the index can be negative - then it is counted from the end of the array.
|
||||
* has(arr, x) - whether there is an element x in the array.
|
||||
* indexOf(arr, x) - returns the index of the element x (starting with 1), if it exists in the array, or 0 if it is not.
|
||||
* arrayEnumerate(arr) - Returns the array [1,2,3,..., length(arr)]
|
||||
*
|
||||
* arrayUniq(arr) - считает количество разных элементов в массиве,
|
||||
* arrayUniq(arr1, arr2, ...) - считает количество разных кортежей из элементов на соответствующих позициях в нескольких массивах.
|
||||
* arrayUniq(arr) - counts the number of different elements in the array,
|
||||
* arrayUniq(arr1, arr2, ...) - counts the number of different tuples from the elements in the corresponding positions in several arrays.
|
||||
*
|
||||
* arrayEnumerateUniq(arr)
|
||||
* - возаращает массив, параллельный данному, где для каждого элемента указано,
|
||||
* какой он по счету среди элементов с таким значением.
|
||||
* Например: arrayEnumerateUniq([10, 20, 10, 30]) = [1, 1, 2, 1]
|
||||
* - outputs an array parallel (having same size) to this, where for each element specified
|
||||
* how much times this element was encountered before (including this element) among elements with the same value.
|
||||
* For example: arrayEnumerateUniq([10, 20, 10, 30]) = [1, 1, 2, 1]
|
||||
* arrayEnumerateUniq(arr1, arr2...)
|
||||
* - для кортежей из элементов на соответствующих позициях в нескольких массивах.
|
||||
* - for tuples from elements in the corresponding positions in several arrays.
|
||||
*
|
||||
* emptyArrayToSingle(arr) - заменить пустые массивы на массивы из одного элемента со значением "по-умолчанию".
|
||||
* emptyArrayToSingle(arr) - replace empty arrays with arrays of one element with a default value.
|
||||
*
|
||||
* arrayReduce('agg', arr1, ...) - применить агрегатную функцию agg к массивам arr1...
|
||||
* arrayReduce('agg', arr1, ...) - apply the aggregate function `agg` to arrays `arr1...`
|
||||
* If multiple arrays passed, then elements on corresponding positions are passed as multiple arguments to the aggregate function.
|
||||
*/
|
||||
|
||||
|
||||
@ -142,7 +143,7 @@ private:
|
||||
template <typename IndexType>
|
||||
bool executeArgument(Block & block, const ColumnNumbers & arguments, size_t result, ArrayImpl::NullMapBuilder & builder);
|
||||
|
||||
/** Для массива кортежей функция вычисляется покомпонентно - для каждого элемента кортежа.
|
||||
/** For a tuple array, the function is evaluated component-wise for each element of the tuple.
|
||||
*/
|
||||
bool executeTuple(Block & block, const ColumnNumbers & arguments, size_t result);
|
||||
};
|
||||
@ -159,7 +160,7 @@ struct IndexToOne
|
||||
struct IndexIdentity
|
||||
{
|
||||
using ResultType = UInt64;
|
||||
/// Индекс возвращается начиная с единицы.
|
||||
/// The index is returned starting from 1.
|
||||
static bool apply(size_t j, ResultType & current) { current = j + 1; return false; }
|
||||
};
|
||||
|
||||
@ -193,7 +194,7 @@ private:
|
||||
|
||||
static bool hasNull(const U & value, const PaddedPODArray<UInt8> & null_map, size_t i)
|
||||
{
|
||||
throw Exception{"Internal error", ErrorCodes::LOGICAL_ERROR};
|
||||
throw Exception{"Logical error: constant column cannot have null map.", ErrorCodes::LOGICAL_ERROR};
|
||||
}
|
||||
|
||||
/// Both function arguments are ordinary.
|
||||
@ -1033,7 +1034,7 @@ public:
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
/// If one or both arguments passed to this function are nullable,
|
||||
/// we create a new block that contains non-nullable parameters:
|
||||
/// we create a new block that contains non-nullable arguments:
|
||||
/// - if the 1st argument is a non-constant array of nullable values,
|
||||
/// it is turned into a non-constant array of ordinary values + a null
|
||||
/// byte map;
|
||||
@ -1181,8 +1182,8 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/// Считает количество разных элементов в массиве, или количество разных кортежей из элементов на соответствующих позициях в нескольких массивах.
|
||||
/// NOTE Реализация частично совпадает с arrayEnumerateUniq.
|
||||
/// Counts the number of different elements in the array, or the number of different tuples from the elements at the corresponding positions in several arrays.
|
||||
/// NOTE The implementation partially matches arrayEnumerateUniq.
|
||||
class FunctionArrayUniq : public IFunction
|
||||
{
|
||||
public:
|
||||
@ -1199,7 +1200,7 @@ public:
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
|
||||
private:
|
||||
/// Изначально выделить кусок памяти для 512 элементов.
|
||||
/// Initially allocate a piece of memory for 512 elements. NOTE: This is just a guess.
|
||||
static constexpr size_t INITIAL_SIZE_DEGREE = 9;
|
||||
|
||||
template <typename T>
|
||||
@ -1239,7 +1240,7 @@ public:
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
|
||||
private:
|
||||
/// Изначально выделить кусок памяти для 512 элементов.
|
||||
/// Initially allocate a piece of memory for 512 elements. NOTE: This is just a guess.
|
||||
static constexpr size_t INITIAL_SIZE_DEGREE = 9;
|
||||
|
||||
template <typename T>
|
||||
@ -1382,7 +1383,7 @@ class IAggregateFunction;
|
||||
using AggregateFunctionPtr = std::shared_ptr<IAggregateFunction>;
|
||||
|
||||
/** Applies an aggregate function to array and returns its result.
|
||||
* If aggregate function has multiple arguments, then this function can be applied to multiple arrays with the same size.
|
||||
* If aggregate function has multiple arguments, then this function can be applied to multiple arrays of the same size.
|
||||
*/
|
||||
class FunctionArrayReduce : public IFunction
|
||||
{
|
||||
@ -1406,9 +1407,9 @@ private:
|
||||
};
|
||||
|
||||
|
||||
struct NameHas { static constexpr auto name = "has"; };
|
||||
struct NameIndexOf { static constexpr auto name = "indexOf"; };
|
||||
struct NameCountEqual { static constexpr auto name = "countEqual"; };
|
||||
struct NameHas { static constexpr auto name = "has"; };
|
||||
struct NameIndexOf { static constexpr auto name = "indexOf"; };
|
||||
struct NameCountEqual { static constexpr auto name = "countEqual"; };
|
||||
|
||||
using FunctionHas = FunctionArrayIndex<IndexToOne, NameHas>;
|
||||
using FunctionIndexOf = FunctionArrayIndex<IndexIdentity, NameIndexOf>;
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <DataTypes/DataTypeString.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Columns/ColumnConst.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
|
||||
#include <unicode/ucnv.h>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Common/hex.h>
|
||||
#include <IO/ReadBufferFromString.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <DataTypes/DataTypeString.h>
|
||||
@ -17,31 +17,29 @@
|
||||
#include <Functions/IFunction.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <array>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Функции кодирования:
|
||||
/** Encoding functions:
|
||||
*
|
||||
* IPv4NumToString(num) - См. ниже.
|
||||
* IPv4StringToNum(string) - Преобразуют, например, '192.168.0.1' в 3232235521 и наоборот.
|
||||
* IPv4NumToString (num) - See below.
|
||||
* IPv4StringToNum(string) - Convert, for example, '192.168.0.1' to 3232235521 and vice versa.
|
||||
*
|
||||
* hex(x) - Возвращает hex; буквы заглавные; префиксов 0x или суффиксов h нет.
|
||||
* Для чисел возвращает строку переменной длины - hex в "человеческом" (big endian) формате, с вырезанием старших нулей, но только по целым байтам. Для дат и дат-с-временем - как для чисел.
|
||||
* Например, hex(257) = '0101'.
|
||||
* unhex(string) - Возвращает строку, hex от которой равен string с точностью до регистра и отбрасывания одного ведущего нуля.
|
||||
* Если такой строки не существует, оставляет за собой право вернуть любой мусор.
|
||||
* hex(x) - Returns hex; capital letters; there are no prefixes 0x or suffixes h.
|
||||
* For numbers, returns a variable-length string - hex in the "human" (big endian) format, with the leading zeros being cut,
|
||||
* but only by whole bytes. For dates and datetimes - the same as for numbers.
|
||||
* For example, hex(257) = '0101'.
|
||||
* unhex(string) - Returns a string, hex of which is equal to `string` with regard of case and discarding one leading zero.
|
||||
* If such a string does not exist, could return arbitary implementation specific value.
|
||||
*
|
||||
* bitmaskToArray(x) - Возвращает массив степеней двойки в двоичной записи x. Например, bitmaskToArray(50) = [2, 16, 32].
|
||||
* bitmaskToArray(x) - Returns an array of powers of two in the binary form of x. For example, bitmaskToArray(50) = [2, 16, 32].
|
||||
*/
|
||||
|
||||
|
||||
/// Включая нулевой символ в конце.
|
||||
#define MAX_UINT_HEX_LENGTH 20
|
||||
|
||||
const auto ipv4_bytes_length = 4;
|
||||
const auto ipv6_bytes_length = 16;
|
||||
const auto uuid_bytes_length = 16;
|
||||
@ -56,9 +54,6 @@ private:
|
||||
return value >= base ? 1 + int_log(value / base, base, value % base || carry) : value % base > 1 || carry;
|
||||
}
|
||||
|
||||
/// mapping of digits up to base 16
|
||||
static constexpr auto && digits = "0123456789abcdef";
|
||||
|
||||
/// print integer in desired base, faster than sprintf
|
||||
template <uint32_t base, typename T, uint32_t buffer_size = sizeof(T) * int_log(256, base, false)>
|
||||
static void print_integer(char *& out, T value)
|
||||
@ -72,7 +67,7 @@ private:
|
||||
|
||||
while (value > 0)
|
||||
{
|
||||
*ptr++ = digits[value % base];
|
||||
*ptr++ = hexLowercase(value % base);
|
||||
value /= base;
|
||||
}
|
||||
|
||||
@ -664,16 +659,16 @@ public:
|
||||
{
|
||||
char * begin = out;
|
||||
|
||||
/// Запишем все задом наперед.
|
||||
/// Write everything backwards.
|
||||
for (size_t offset = 0; offset <= 24; offset += 8)
|
||||
{
|
||||
if (offset > 0)
|
||||
*(out++) = '.';
|
||||
|
||||
/// Достаем очередной байт.
|
||||
/// Get the next byte.
|
||||
UInt32 value = (ip >> offset) & static_cast<UInt32>(255);
|
||||
|
||||
/// Быстрее, чем sprintf.
|
||||
/// Faster than sprintf.
|
||||
if (value == 0)
|
||||
{
|
||||
*(out++) = '0';
|
||||
@ -688,7 +683,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// И развернем.
|
||||
/// And reverse.
|
||||
std::reverse(begin, out);
|
||||
|
||||
*(out++) = '\0';
|
||||
@ -708,7 +703,7 @@ public:
|
||||
ColumnString::Chars_t & vec_res = col_res->getChars();
|
||||
ColumnString::Offsets_t & offsets_res = col_res->getOffsets();
|
||||
|
||||
vec_res.resize(vec_in.size() * INET_ADDRSTRLEN); /// самое длинное значение: 255.255.255.255\0
|
||||
vec_res.resize(vec_in.size() * INET_ADDRSTRLEN); /// the longest value is: 255.255.255.255\0
|
||||
offsets_res.resize(vec_in.size());
|
||||
char * begin = reinterpret_cast<char *>(&vec_res[0]);
|
||||
char * pos = begin;
|
||||
@ -847,16 +842,16 @@ public:
|
||||
for (auto i = 0; i < 3; ++i)
|
||||
*(out++) = 'x';
|
||||
|
||||
/// Запишем все задом наперед.
|
||||
/// Write everything backwards.
|
||||
for (size_t offset = 8; offset <= 24; offset += 8)
|
||||
{
|
||||
if (offset > 0)
|
||||
*(out++) = '.';
|
||||
|
||||
/// Достаем очередной байт.
|
||||
/// Get the next byte.
|
||||
UInt32 value = (ip >> offset) & static_cast<UInt32>(255);
|
||||
|
||||
/// Быстрее, чем sprintf.
|
||||
/// Faster than sprintf.
|
||||
if (value == 0)
|
||||
{
|
||||
*(out++) = '0';
|
||||
@ -871,7 +866,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// И развернем.
|
||||
/// And reverse.
|
||||
std::reverse(begin, out);
|
||||
|
||||
*(out++) = '\0';
|
||||
@ -891,7 +886,7 @@ public:
|
||||
ColumnString::Chars_t & vec_res = col_res->getChars();
|
||||
ColumnString::Offsets_t & offsets_res = col_res->getOffsets();
|
||||
|
||||
vec_res.resize(vec_in.size() * INET_ADDRSTRLEN); /// самое длинное значение: 255.255.255.255\0
|
||||
vec_res.resize(vec_in.size() * INET_ADDRSTRLEN); /// the longest value is: 255.255.255.255\0
|
||||
offsets_res.resize(vec_in.size());
|
||||
char * begin = reinterpret_cast<char *>(&vec_res[0]);
|
||||
char * pos = begin;
|
||||
@ -1012,19 +1007,16 @@ public:
|
||||
{
|
||||
char * begin = out;
|
||||
|
||||
/// mapping of digits up to base 16
|
||||
static char digits[] = "0123456789ABCDEF";
|
||||
|
||||
/// Запишем все задом наперед.
|
||||
/// Write everything backwards.
|
||||
for (size_t offset = 0; offset <= 40; offset += 8)
|
||||
{
|
||||
if (offset > 0)
|
||||
*(out++) = ':';
|
||||
|
||||
/// Достаем очередной байт.
|
||||
/// Get the next byte.
|
||||
UInt64 value = (mac >> offset) & static_cast<UInt64>(255);
|
||||
|
||||
/// Быстрее, чем sprintf.
|
||||
/// Faster than sprintf.
|
||||
if (value < 16)
|
||||
{
|
||||
*(out++) = '0';
|
||||
@ -1037,13 +1029,13 @@ public:
|
||||
{
|
||||
while (value > 0)
|
||||
{
|
||||
*(out++) = digits[value % 16];
|
||||
*(out++) = hexUppercase(value % 16);
|
||||
value /= 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// И развернем.
|
||||
/// And reverse.
|
||||
std::reverse(begin, out);
|
||||
|
||||
*(out++) = '\0';
|
||||
@ -1063,7 +1055,7 @@ public:
|
||||
ColumnString::Chars_t & vec_res = col_res->getChars();
|
||||
ColumnString::Offsets_t & offsets_res = col_res->getOffsets();
|
||||
|
||||
vec_res.resize(vec_in.size() * 18); /// самое длинное значение: xx:xx:xx:xx:xx:xx\0
|
||||
vec_res.resize(vec_in.size() * 18); /// the longest value is: xx:xx:xx:xx:xx:xx\0
|
||||
offsets_res.resize(vec_in.size());
|
||||
char * begin = reinterpret_cast<char *>(&vec_res[0]);
|
||||
char * pos = begin;
|
||||
@ -1595,20 +1587,19 @@ public:
|
||||
template <typename T>
|
||||
void executeOneUInt(T x, char *& out)
|
||||
{
|
||||
const char digit[17] = "0123456789ABCDEF";
|
||||
bool was_nonzero = false;
|
||||
for (int offset = (sizeof(T) - 1) * 8; offset >= 0; offset -= 8)
|
||||
{
|
||||
UInt8 byte = static_cast<UInt8>((x >> offset) & 255);
|
||||
|
||||
/// Ведущие нули.
|
||||
/// Leading zeros.
|
||||
if (byte == 0 && !was_nonzero && offset)
|
||||
continue;
|
||||
|
||||
was_nonzero = true;
|
||||
|
||||
*(out++) = digit[byte >> 4];
|
||||
*(out++) = digit[byte & 15];
|
||||
*(out++) = hexUppercase(byte / 16);
|
||||
*(out++) = hexUppercase(byte % 16);
|
||||
}
|
||||
*(out++) = '\0';
|
||||
}
|
||||
@ -1619,6 +1610,8 @@ public:
|
||||
const ColumnVector<T> * col_vec = typeid_cast<const ColumnVector<T> *>(col);
|
||||
const ColumnConst<T> * col_const = typeid_cast<const ColumnConst<T> *>(col);
|
||||
|
||||
static constexpr size_t MAX_UINT_HEX_LENGTH = sizeof(T) * 2 + 1; /// Including trailing zero byte.
|
||||
|
||||
if (col_vec)
|
||||
{
|
||||
auto col_str = std::make_shared<ColumnString>();
|
||||
@ -1630,12 +1623,12 @@ public:
|
||||
|
||||
size_t size = in_vec.size();
|
||||
out_offsets.resize(size);
|
||||
out_vec.resize(size * 3 + MAX_UINT_HEX_LENGTH);
|
||||
out_vec.resize(size * 3 + MAX_UINT_HEX_LENGTH); /// 3 is length of one byte in hex plus zero byte.
|
||||
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
/// Ручной экспоненциальный рост, чтобы не полагаться на линейное амортизированное время работы resize (его никто не гарантирует).
|
||||
/// Manual exponential growth, so as not to rely on the linear amortized work time of `resize` (no one guarantees it).
|
||||
if (pos + MAX_UINT_HEX_LENGTH > out_vec.size())
|
||||
out_vec.resize(out_vec.size() * 2 + MAX_UINT_HEX_LENGTH);
|
||||
|
||||
@ -1669,12 +1662,11 @@ public:
|
||||
|
||||
void executeOneString(const UInt8 * pos, const UInt8 * end, char *& out)
|
||||
{
|
||||
const char digit[17] = "0123456789ABCDEF";
|
||||
while (pos < end)
|
||||
{
|
||||
UInt8 byte = *(pos++);
|
||||
*(out++) = digit[byte >> 4];
|
||||
*(out++) = digit[byte & 15];
|
||||
*(out++) = hexUppercase(byte / 16);
|
||||
*(out++) = hexUppercase(byte % 16);
|
||||
}
|
||||
*(out++) = '\0';
|
||||
}
|
||||
@ -1718,13 +1710,13 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
else if(col_const_in)
|
||||
else if (col_const_in)
|
||||
{
|
||||
const std::string & src = col_const_in->getData();
|
||||
std::string res(src.size() * 2, '\0');
|
||||
char * pos = &res[0];
|
||||
const UInt8 * src_ptr = reinterpret_cast<const UInt8 *>(src.c_str());
|
||||
/// Запишем ноль в res[res.size()]. Начиная с C++11, это корректно.
|
||||
/// Let's write zero into res[res.size()]. Starting with C++ 11, this is correct.
|
||||
executeOneString(src_ptr, src_ptr + src.size(), pos);
|
||||
|
||||
col_res = std::make_shared<ColumnConstString>(col_const_in->size(), res);
|
||||
@ -1828,28 +1820,26 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
UInt8 undigitUnsafe(char c)
|
||||
{
|
||||
if (c <= '9')
|
||||
return c - '0';
|
||||
if (c <= 'Z')
|
||||
return c - ('A' - 10);
|
||||
return c - ('a' - 10);
|
||||
}
|
||||
|
||||
void unhexOne(const char * pos, const char * end, char *& out)
|
||||
{
|
||||
if ((end - pos) & 1)
|
||||
{
|
||||
*(out++) = undigitUnsafe(*(pos++));
|
||||
*out = unhex(*pos);
|
||||
++out;
|
||||
++pos;
|
||||
}
|
||||
while (pos < end)
|
||||
{
|
||||
UInt8 major = undigitUnsafe(*(pos++));
|
||||
UInt8 minor = undigitUnsafe(*(pos++));
|
||||
*(out++) = (major << 4) | minor;
|
||||
UInt8 major = unhex(*pos);
|
||||
++pos;
|
||||
UInt8 minor = unhex(*pos);
|
||||
++pos;
|
||||
|
||||
*out = (major << 4) | minor;
|
||||
++out;
|
||||
}
|
||||
*(out++) = '\0';
|
||||
*out = '\0';
|
||||
++out;
|
||||
}
|
||||
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
|
@ -29,20 +29,20 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Функции сравнения: ==, !=, <, >, <=, >=.
|
||||
* Функции сравнения возвращают всегда 0 или 1 (UInt8).
|
||||
/** Comparison functions: ==, !=, <, >, <=, >=.
|
||||
* The comparison functions always return 0 or 1 (UInt8).
|
||||
*
|
||||
* Сравнивать можно следующие типы:
|
||||
* - числа;
|
||||
* - строки и фиксированные строки;
|
||||
* - даты;
|
||||
* - даты-с-временем;
|
||||
* внутри каждой группы, но не из разных групп;
|
||||
* - кортежи (сравнение лексикографическое).
|
||||
* You can compare the following types:
|
||||
* - numbers;
|
||||
* - strings and fixed strings;
|
||||
* - dates;
|
||||
* - datetimes;
|
||||
* within each group, but not from different groups;
|
||||
* - tuples (lexicographic comparison).
|
||||
*
|
||||
* Исключение: можно сравнивать дату и дату-с-временем с константной строкой. Пример: EventDate = '2015-01-01'.
|
||||
* Exception: You can compare the date and datetime with a constant string. Example: EventDate = '2015-01-01'.
|
||||
*
|
||||
* TODO Массивы.
|
||||
* TODO Arrays.
|
||||
*/
|
||||
|
||||
template <typename A, typename B> struct EqualsOp
|
||||
@ -94,9 +94,9 @@ struct NumComparisonImpl
|
||||
/// If you don't specify NO_INLINE, the compiler will inline this function, but we don't need this as this function contains tight loop inside.
|
||||
static void NO_INLINE vector_vector(const PaddedPODArray<A> & a, const PaddedPODArray<B> & b, PaddedPODArray<UInt8> & c)
|
||||
{
|
||||
/** GCC 4.8.2 векторизует цикл только если его записать в такой форме.
|
||||
* В данном случае, если сделать цикл по индексу массива (код будет выглядеть проще),
|
||||
* цикл не будет векторизовываться.
|
||||
/** GCC 4.8.2 vectorizes a loop only if it is written in this form.
|
||||
* In this case, if you loop through the array index (the code will look simpler),
|
||||
* the loop will not be vectorized.
|
||||
*/
|
||||
|
||||
size_t size = a.size();
|
||||
@ -178,7 +178,7 @@ struct StringComparisonImpl
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
/// Завершающий ноль в меньшей по длине строке входит в сравнение.
|
||||
/// The trailing zero in the smaller string is included in the comparison.
|
||||
c[i] = Op::apply(memcmp(&a_data[0], &b_data[0], std::min(a_offsets[0], b_offsets[0])), 0);
|
||||
}
|
||||
else
|
||||
@ -742,7 +742,7 @@ private:
|
||||
Block & block, size_t result, const IColumn * col_left_untyped, const IColumn * col_right_untyped,
|
||||
const DataTypePtr & left_type, const DataTypePtr & right_type, bool left_is_num, bool right_is_num)
|
||||
{
|
||||
/// Уже не такой и особый случай - сравнение дат, дат-с-временем и перечислений со строковой константой.
|
||||
/// This is no longer very special case - comparing dates, datetimes, and enumerations with a string constant.
|
||||
const IColumn * column_string_untyped = !left_is_num ? col_left_untyped : col_right_untyped;
|
||||
const IColumn * column_number = left_is_num ? col_left_untyped : col_right_untyped;
|
||||
const IDataType * number_type = left_is_num ? left_type.get() : right_type.get();
|
||||
@ -817,7 +817,7 @@ private:
|
||||
|
||||
void executeTuple(Block & block, size_t result, const IColumn * c0, const IColumn * c1)
|
||||
{
|
||||
/** Сравнивать кортежи будем лексикографически. Это делается следующим образом:
|
||||
/** We will lexicographically compare the tuples. This is done as follows:
|
||||
* x == y : x1 == y1 && x2 == y2 ...
|
||||
* x != y : x1 != y1 || x2 != y2 ...
|
||||
*
|
||||
@ -825,7 +825,7 @@ private:
|
||||
* x > y: x1 > y1 || (x1 == y1 && (x2 > y2 || (x2 == y2 ... && xn > yn))
|
||||
* x <= y: x1 < y1 || (x1 == y1 && (x2 < y2 || (x2 == y2 ... && xn <= yn))
|
||||
*
|
||||
* Рекурсивная запись:
|
||||
* Recursive record:
|
||||
* x <= y: x1 < y1 || (x1 == y1 && x_tail <= y_tail)
|
||||
*
|
||||
* x >= y: x1 > y1 || (x1 == y1 && (x2 > y2 || (x2 == y2 ... && xn >= yn))
|
||||
@ -874,12 +874,12 @@ private:
|
||||
tmp_block.insert(x->getData().safeGetByPosition(i));
|
||||
tmp_block.insert(y->getData().safeGetByPosition(i));
|
||||
|
||||
/// Сравнение элементов.
|
||||
/// Comparison of the elements.
|
||||
tmp_block.insert({ nullptr, std::make_shared<DataTypeUInt8>(), "" });
|
||||
func_compare.execute(tmp_block, {i * 3, i * 3 + 1}, i * 3 + 2);
|
||||
}
|
||||
|
||||
/// Логическая свёртка.
|
||||
/// Logical convolution.
|
||||
tmp_block.insert({ nullptr, std::make_shared<DataTypeUInt8>(), "" });
|
||||
|
||||
ColumnNumbers convolution_args(tuple_size);
|
||||
@ -901,7 +901,7 @@ private:
|
||||
|
||||
Block tmp_block;
|
||||
|
||||
/// Попарное сравнение на неравенство всех элементов; на равенство всех элементов кроме последнего.
|
||||
/// Pairwise comparison of the inequality of all elements; on the equality of all elements except the last.
|
||||
for (size_t i = 0; i < tuple_size; ++i)
|
||||
{
|
||||
tmp_block.insert(x->getData().safeGetByPosition(i));
|
||||
@ -921,7 +921,7 @@ private:
|
||||
func_compare_tail.execute(tmp_block, {i * 4, i * 4 + 1}, i * 4 + 2);
|
||||
}
|
||||
|
||||
/// Комбинирование. Сложный код - сделайте рисунок. Можно заменить на рекурсивное сравнение кортежей.
|
||||
/// Combination. Complex code - make a drawing. It can be replaced by a recursive comparison of tuples.
|
||||
size_t i = tuple_size - 1;
|
||||
while (i > 0)
|
||||
{
|
||||
@ -970,7 +970,7 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 2; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
/// Get result types by argument types. If the function does not apply to these arguments, throw an exception.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
bool left_is_date = false;
|
||||
@ -1001,32 +1001,32 @@ public:
|
||||
const DataTypeTuple * right_tuple = nullptr;
|
||||
|
||||
false
|
||||
|| (right_is_date = typeid_cast<const DataTypeDate *>(arguments[1].get()))
|
||||
|| (right_is_date_time = typeid_cast<const DataTypeDateTime *>(arguments[1].get()))
|
||||
|| (right_is_enum8 = typeid_cast<const DataTypeEnum8 *>(arguments[1].get()))
|
||||
|| (right_is_enum16 = typeid_cast<const DataTypeEnum16 *>(arguments[1].get()))
|
||||
|| (right_is_string = typeid_cast<const DataTypeString *>(arguments[1].get()))
|
||||
|| (right_is_date = typeid_cast<const DataTypeDate *>(arguments[1].get()))
|
||||
|| (right_is_date_time = typeid_cast<const DataTypeDateTime *>(arguments[1].get()))
|
||||
|| (right_is_enum8 = typeid_cast<const DataTypeEnum8 *>(arguments[1].get()))
|
||||
|| (right_is_enum16 = typeid_cast<const DataTypeEnum16 *>(arguments[1].get()))
|
||||
|| (right_is_string = typeid_cast<const DataTypeString *>(arguments[1].get()))
|
||||
|| (right_is_fixed_string = typeid_cast<const DataTypeFixedString *>(arguments[1].get()))
|
||||
|| (right_tuple = typeid_cast<const DataTypeTuple *>(arguments[1].get()));
|
||||
|| (right_tuple = typeid_cast<const DataTypeTuple *>(arguments[1].get()));
|
||||
|
||||
const bool right_is_enum = right_is_enum8 || right_is_enum16;
|
||||
|
||||
if (!( (arguments[0]->behavesAsNumber() && arguments[1]->behavesAsNumber() && !(left_is_enum ^ right_is_enum))
|
||||
|| ((left_is_string || left_is_fixed_string) && (right_is_string || right_is_fixed_string))
|
||||
|| (left_is_date && right_is_date)
|
||||
|| (left_is_date && right_is_string) /// Можно сравнивать дату, дату-с-временем и перечисление с константной строкой.
|
||||
|| (left_is_string && right_is_date)
|
||||
|| (left_is_date_time && right_is_date_time)
|
||||
|| (left_is_date_time && right_is_string)
|
||||
|| (left_is_string && right_is_date_time)
|
||||
|| (left_is_date_time && right_is_date_time)
|
||||
|| (left_is_date_time && right_is_string)
|
||||
|| (left_is_string && right_is_date_time)
|
||||
|| (left_is_enum && right_is_enum && arguments[0]->getName() == arguments[1]->getName()) /// only equivalent enum type values can be compared against
|
||||
|| (left_is_enum && right_is_string)
|
||||
|| (left_is_string && right_is_enum)
|
||||
|| (left_tuple && right_tuple && left_tuple->getElements().size() == right_tuple->getElements().size())
|
||||
|| (arguments[0]->equals(*arguments[1]))))
|
||||
if (!((arguments[0]->behavesAsNumber() && arguments[1]->behavesAsNumber() && !(left_is_enum ^ right_is_enum))
|
||||
|| ((left_is_string || left_is_fixed_string) && (right_is_string || right_is_fixed_string))
|
||||
|| (left_is_date && right_is_date)
|
||||
|| (left_is_date && right_is_string) /// You can compare the date, datetime and an enumeration with a constant string.
|
||||
|| (left_is_string && right_is_date)
|
||||
|| (left_is_date_time && right_is_date_time)
|
||||
|| (left_is_date_time && right_is_string)
|
||||
|| (left_is_string && right_is_date_time)
|
||||
|| (left_is_date_time && right_is_date_time)
|
||||
|| (left_is_date_time && right_is_string)
|
||||
|| (left_is_string && right_is_date_time)
|
||||
|| (left_is_enum && right_is_enum && arguments[0]->getName() == arguments[1]->getName()) /// only equivalent enum type values can be compared against
|
||||
|| (left_is_enum && right_is_string)
|
||||
|| (left_is_string && right_is_enum)
|
||||
|| (left_tuple && right_tuple && left_tuple->getElements().size() == right_tuple->getElements().size())
|
||||
|| (arguments[0]->equals(*arguments[1]))))
|
||||
throw Exception("Illegal types of arguments (" + arguments[0]->getName() + ", " + arguments[1]->getName() + ")"
|
||||
" of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
@ -1052,16 +1052,16 @@ public:
|
||||
|
||||
if (left_is_num && right_is_num)
|
||||
{
|
||||
if (!( executeNumLeftType<UInt8>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt16>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt32>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt64>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int8>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int16>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int32>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int64>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Float32>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Float64>(block, result, col_left_untyped, col_right_untyped)))
|
||||
if (!( executeNumLeftType<UInt8>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt16>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt32>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt64>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int8>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int16>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int32>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int64>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Float32>(block, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Float64>(block, result, col_left_untyped, col_right_untyped)))
|
||||
throw Exception("Illegal column " + col_left_untyped->getName()
|
||||
+ " of first argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
@ -1077,15 +1077,15 @@ public:
|
||||
block, result, col_left_untyped, col_right_untyped,
|
||||
col_with_type_and_name_left.type, col_with_type_and_name_right.type,
|
||||
left_is_num, right_is_num);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
using FunctionEquals = FunctionComparison<EqualsOp, NameEquals> ;
|
||||
using FunctionNotEquals = FunctionComparison<NotEqualsOp, NameNotEquals> ;
|
||||
using FunctionLess = FunctionComparison<LessOp, NameLess> ;
|
||||
using FunctionGreater = FunctionComparison<GreaterOp, NameGreater> ;
|
||||
using FunctionLessOrEquals = FunctionComparison<LessOrEqualsOp, NameLessOrEquals> ;
|
||||
using FunctionGreaterOrEquals = FunctionComparison<GreaterOrEqualsOp, NameGreaterOrEquals>;
|
||||
using FunctionEquals = FunctionComparison<EqualsOp, NameEquals>;
|
||||
using FunctionNotEquals = FunctionComparison<NotEqualsOp, NameNotEquals>;
|
||||
using FunctionLess = FunctionComparison<LessOp, NameLess>;
|
||||
using FunctionGreater = FunctionComparison<GreaterOp, NameGreater>;
|
||||
using FunctionLessOrEquals = FunctionComparison<LessOrEqualsOp, NameLessOrEquals>;
|
||||
using FunctionGreaterOrEquals = FunctionComparison<GreaterOrEqualsOp, NameGreaterOrEquals>;
|
||||
|
||||
}
|
||||
|
@ -19,9 +19,9 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Функция выбора по условию: if(cond, then, else).
|
||||
/** Selection function by condition: if(cond, then, else).
|
||||
* cond - UInt8
|
||||
* then, else - числовые типы, для которых есть общий тип, либо даты, даты-с-временем, либо строки, либо массивы таких типов.
|
||||
* then, else - numeric types for which there is a general type, or dates, datetimes, or strings, or arrays of these types.
|
||||
*/
|
||||
|
||||
|
||||
@ -610,9 +610,9 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/** Реализация для массивов строк.
|
||||
* NOTE: Код слишком сложный, потому что он работает в внутренностями массивов строк.
|
||||
* NOTE: Массивы из FixedString не поддерживаются.
|
||||
/** Implementation for string arrays.
|
||||
* NOTE: The code is too complex because it works with the internals of the arrays of strings.
|
||||
* NOTE: Arrays of FixedString are not supported.
|
||||
*/
|
||||
struct StringArrayIfImpl
|
||||
{
|
||||
@ -666,7 +666,7 @@ struct StringArrayIfImpl
|
||||
for (size_t j = 0; j < array_size; ++j)
|
||||
{
|
||||
const String & str = from_data[j].get<const String &>();
|
||||
size_t string_size = str.size() + 1; /// Включая 0 на конце.
|
||||
size_t string_size = str.size() + 1; /// Including 0 at the end.
|
||||
|
||||
to_data.resize(to_string_prev_offset + string_size);
|
||||
memcpy(&to_data[to_string_prev_offset], str.data(), string_size);
|
||||
@ -1121,7 +1121,7 @@ private:
|
||||
{
|
||||
if (col_then_fixed && col_else_fixed)
|
||||
{
|
||||
/// Результат - FixedString.
|
||||
/// The result is FixedString.
|
||||
|
||||
if (col_then_fixed->getN() != col_else_fixed->getN())
|
||||
throw Exception("FixedString columns as 'then' and 'else' arguments of function 'if' has different sizes", ErrorCodes::ILLEGAL_COLUMN);
|
||||
@ -1142,7 +1142,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Результат - String.
|
||||
/// The result is String.
|
||||
std::shared_ptr<ColumnString> col_res = std::make_shared<ColumnString>();
|
||||
block.safeGetByPosition(result).column = col_res;
|
||||
|
||||
@ -1582,7 +1582,7 @@ public:
|
||||
|
||||
bool hasSpecialSupportForNulls() const override { return true; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
/// Get result types by argument types. If the function does not apply to these arguments, throw an exception.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
bool cond_is_null = arguments[0]->isNull();
|
||||
@ -1640,7 +1640,7 @@ public:
|
||||
}
|
||||
else if (type_arr1 && type_arr2)
|
||||
{
|
||||
/// NOTE Сообщения об ошибках будут относится к типам элементов массивов, что немного некорректно.
|
||||
/// NOTE Error messages will refer to the types of array elements, which is slightly incorrect.
|
||||
return std::make_shared<DataTypeArray>(getReturnTypeImpl({arguments[0], type_arr1->getNestedType(), type_arr2->getNestedType()}));
|
||||
}
|
||||
else if (type_tuple1 && type_tuple2)
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <ext/enumerate.hpp>
|
||||
#include <ext/collection_cast.hpp>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/enumerate.h>
|
||||
#include <ext/collection_cast.h>
|
||||
#include <ext/range.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include <IO/WriteBufferFromVector.h>
|
||||
|
@ -23,7 +23,7 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Функции работы с датой и временем.
|
||||
/** Functions for working with date and time.
|
||||
*
|
||||
* toYear, toMonth, toDayOfMonth, toDayOfWeek, toHour, toMinute, toSecond,
|
||||
* toMonday, toStartOfMonth, toStartOfYear, toStartOfMinute, toStartOfFiveMinute
|
||||
@ -31,43 +31,43 @@ namespace DB
|
||||
* now
|
||||
* TODO: makeDate, makeDateTime
|
||||
*
|
||||
* (toDate - расположена в файле FunctionsConversion.h)
|
||||
* (toDate - located in FunctionConversion.h file)
|
||||
*
|
||||
* Возвращаемые типы:
|
||||
* Return types:
|
||||
* toYear -> UInt16
|
||||
* toMonth, toDayOfMonth, toDayOfWeek, toHour, toMinute, toSecond -> UInt8
|
||||
* toMonday, toStartOfMonth, toStartOfYear -> Date
|
||||
* toStartOfMinute, toStartOfHour, toTime, now -> DateTime
|
||||
*
|
||||
* А также:
|
||||
* And also:
|
||||
*
|
||||
* timeSlot(EventTime)
|
||||
* - округляет время до получаса.
|
||||
* - rounds the time to half an hour.
|
||||
*
|
||||
* timeSlots(StartTime, Duration)
|
||||
* - для интервала времени, начинающегося в StartTime и продолжающегося Duration секунд,
|
||||
* возвращает массив моментов времени, состоящий из округлений вниз до получаса точек из этого интервала.
|
||||
* Например, timeSlots(toDateTime('2012-01-01 12:20:00'), 600) = [toDateTime('2012-01-01 12:00:00'), toDateTime('2012-01-01 12:30:00')].
|
||||
* Это нужно для поиска хитов, входящих в соответствующий визит.
|
||||
* - for the time interval beginning at `StartTime` and continuing `Duration` seconds,
|
||||
* returns an array of time points, consisting of rounding down to half an hour of points from this interval.
|
||||
* For example, timeSlots(toDateTime('2012-01-01 12:20:00'), 600) = [toDateTime('2012-01-01 12:00:00'), toDateTime('2012-01-01 12:30:00')].
|
||||
* This is necessary to search for hits that are part of the corresponding visit.
|
||||
*/
|
||||
|
||||
|
||||
#define TIME_SLOT_SIZE 1800
|
||||
|
||||
/** Всевозможные преобразования.
|
||||
* Представляют собой две функции - от даты-с-временем (UInt32) и от даты (UInt16).
|
||||
/** Extra transformations.
|
||||
* Represents two functions - from datetime (UInt32) and from date (UInt16).
|
||||
*
|
||||
* Также для преобразования T определяется "фактор-преобразование" F.
|
||||
* Это такое преобразование F, что его значение идентифицирует область монотонности T
|
||||
* (при фиксированном значении F, преобразование T является монотонным).
|
||||
* Also, the "factor transformation" F is defined for the T transformation.
|
||||
* This is a transformation of F such that its value identifies the region of monotonicity T
|
||||
* (for a fixed value of F, the transformation T is monotonic).
|
||||
*
|
||||
* Или, образно, если T аналогично взятию остатка от деления, то F аналогично делению.
|
||||
* Or, figuratively, if T is similar to taking the remainder of division, then F is similar to division.
|
||||
*
|
||||
* Пример: для преобразования T "получить номер дня в месяце" (2015-02-03 -> 3),
|
||||
* фактор-преобразованием F является "округлить до месяца" (2015-02-03 -> 2015-02-01).
|
||||
* Example: to convert T "get the day number in the month" (2015-02-03 -> 3),
|
||||
* factor-transformation F is "round to the nearest month" (2015-02-03 -> 2015-02-01).
|
||||
*/
|
||||
|
||||
/// Это фактор-преобразование будет говорить, что функция монотонна всюду.
|
||||
/// This factor transformation will say that the function is monotone everywhere.
|
||||
struct ZeroTransform
|
||||
{
|
||||
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone) { return 0; }
|
||||
@ -161,7 +161,7 @@ struct ToStartOfYearImpl
|
||||
|
||||
struct ToTimeImpl
|
||||
{
|
||||
/// При переводе во время, дату будем приравнивать к 1970-01-02.
|
||||
/// When transforming to time, the date will be equated to 1970-01-02.
|
||||
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toTime(t) + 86400;
|
||||
@ -554,13 +554,13 @@ public:
|
||||
if (std::is_same<typename Transform::FactorTransform, ZeroTransform>::value)
|
||||
return is_monotonic;
|
||||
|
||||
/// Этот метод вызывается только если у функции один аргумент. Поэтому, нас пока не волнует не-локальная тайм-зона.
|
||||
/// This method is called only if the function has one argument. Therefore, we do not care about the non-local time zone.
|
||||
const DateLUTImpl & date_lut = DateLUT::instance();
|
||||
|
||||
if (left.isNull() || right.isNull())
|
||||
return is_not_monotonic;
|
||||
|
||||
/// Функция монотонна на отрезке [left, right], если фактор-преобразование возвращает для них одинаковые значения.
|
||||
/// The function is monotonous on the [left, right] segment, if the factor transformation returns the same values for them.
|
||||
|
||||
if (typeid_cast<const DataTypeDate *>(&type))
|
||||
{
|
||||
@ -578,7 +578,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/// Получить текущее время. (Оно - константа, вычисляется один раз за весь запрос.)
|
||||
/// Get the current time. (It is a constant, it is evaluated once for the entire query.)
|
||||
class FunctionNow : public IFunction
|
||||
{
|
||||
public:
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <Dictionaries/RangeHashedDictionary.h>
|
||||
#include <Dictionaries/TrieDictionary.h>
|
||||
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <Columns/ColumnsNumber.h>
|
||||
#include <Columns/ColumnConst.h>
|
||||
#include <Functions/IFunction.h>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <math.h>
|
||||
#include <array>
|
||||
|
||||
|
@ -25,27 +25,27 @@
|
||||
#include <Common/HashTable/Hash.h>
|
||||
#include <Functions/IFunction.h>
|
||||
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Функции хэширования.
|
||||
/** Hashing functions.
|
||||
*
|
||||
* Половинка MD5:
|
||||
* Half MD5:
|
||||
* halfMD5: String -> UInt64
|
||||
*
|
||||
* Более быстрая криптографическая хэш-функция:
|
||||
* A faster cryptographic hash function:
|
||||
* sipHash64: String -> UInt64
|
||||
*
|
||||
* Быстрая некриптографическая хэш функция для строк:
|
||||
* Fast non-cryptographic hash function for strings:
|
||||
* cityHash64: String -> UInt64
|
||||
*
|
||||
* Некриптографический хеш от кортежа значений любых типов (использует cityHash64 для строк и intHash64 для чисел):
|
||||
* A non-cryptographic hash from a tuple of values of any types (uses cityHash64 for strings and intHash64 for numbers):
|
||||
* cityHash64: any* -> UInt64
|
||||
*
|
||||
* Быстрая некриптографическая хэш функция от любого целого числа:
|
||||
* Fast non-cryptographic hash function from any integer:
|
||||
* intHash32: number -> UInt32
|
||||
* intHash64: number -> UInt64
|
||||
*
|
||||
@ -66,7 +66,7 @@ struct HalfMD5Impl
|
||||
MD5_Update(&ctx, reinterpret_cast<const unsigned char *>(begin), size);
|
||||
MD5_Final(buf.char_data, &ctx);
|
||||
|
||||
return Poco::ByteOrder::flipBytes(buf.uint64_data); /// Совместимость с существующим кодом.
|
||||
return Poco::ByteOrder::flipBytes(buf.uint64_data); /// Compatibility with existing code.
|
||||
}
|
||||
};
|
||||
|
||||
@ -151,7 +151,7 @@ struct IntHash32Impl
|
||||
|
||||
static UInt32 apply(UInt64 x)
|
||||
{
|
||||
/// seed взят из /dev/urandom. Он позволяет избежать нежелательных зависимостей с хэшами в разных структурах данных.
|
||||
/// seed is taken from /dev/urandom. It allows you to avoid undesirable dependencies with hashes in different data structures.
|
||||
return intHash32<0x75D9543DE018BF45ULL>(x);
|
||||
}
|
||||
};
|
||||
@ -371,8 +371,8 @@ template <>
|
||||
UInt64 toInteger<Float64>(Float64 x);
|
||||
|
||||
|
||||
/** Используются хэш-функции под названием CityHash, FarmHash, MetroHash.
|
||||
* В связи с этим, этот шаблон назван со словами NeighbourhoodHash.
|
||||
/** We use hash functions called CityHash, FarmHash, MetroHash.
|
||||
* In this regard, this template is named with the words `NeighborhoodHash`.
|
||||
*/
|
||||
template <typename Impl>
|
||||
class FunctionNeighbourhoodHash64 : public IFunction
|
||||
@ -507,7 +507,7 @@ private:
|
||||
}
|
||||
else if (const ColumnConstArray * col_from = typeid_cast<const ColumnConstArray *>(column))
|
||||
{
|
||||
/// NOTE: тут, конечно, можно обойтись без материалиации столбца.
|
||||
/// NOTE: here, of course, you can do without the materialization of the column.
|
||||
ColumnPtr full_column = col_from->convertToFullColumn();
|
||||
executeArray<first>(type, &*full_column, vec_to);
|
||||
}
|
||||
@ -644,15 +644,15 @@ struct URLHierarchyHashImpl
|
||||
{
|
||||
auto pos = begin;
|
||||
|
||||
/// Распарсим всё, что идёт до пути
|
||||
/// Let's parse everything that goes before the path
|
||||
|
||||
/// Предположим, что протокол уже переведён в нижний регистр.
|
||||
/// Suppose that the protocol has already been changed to lowercase.
|
||||
while (pos < end && ((*pos > 'a' && *pos < 'z') || (*pos > '0' && *pos < '9')))
|
||||
++pos;
|
||||
|
||||
/** Будем вычислять иерархию только для URL-ов, в которых есть протокол, и после него идут два слеша.
|
||||
* (http, file - подходят, mailto, magnet - не подходят), и после двух слешей ещё хоть что-нибудь есть
|
||||
* Для остальных просто вернём полный URL как единственный элемент иерархии.
|
||||
/** We will calculate the hierarchy only for URLs in which there is a protocol, and after it there are two slashes.
|
||||
* (http, file - fit, mailto, magnet - do not fit), and after two slashes there is still something
|
||||
* For the rest, simply return the full URL as the only element of the hierarchy.
|
||||
*/
|
||||
if (pos == begin || pos == end || !(*pos++ == ':' && pos < end && *pos++ == '/' && pos < end && *pos++ == '/' && pos < end))
|
||||
{
|
||||
@ -660,7 +660,7 @@ struct URLHierarchyHashImpl
|
||||
return 0 == level ? pos - begin : 0;
|
||||
}
|
||||
|
||||
/// Доменом для простоты будем считать всё, что после протокола и двух слешей, до следующего слеша или до ? или до #
|
||||
/// The domain for simplicity is everything that after the protocol and the two slashes, until the next slash or before `?` or `#`
|
||||
while (pos < end && !(*pos == '/' || *pos == '?' || *pos == '#'))
|
||||
++pos;
|
||||
|
||||
@ -674,7 +674,7 @@ struct URLHierarchyHashImpl
|
||||
|
||||
while (current_level != level && pos < end)
|
||||
{
|
||||
/// Идём до следующего / или ? или #, пропуская все те, что вначале.
|
||||
/// We go to the next `/` or `?` or `#`, skipping all at the beginning.
|
||||
while (pos < end && (*pos == '/' || *pos == '?' || *pos == '#'))
|
||||
++pos;
|
||||
if (pos == end)
|
||||
|
@ -20,24 +20,24 @@ namespace ErrorCodes
|
||||
extern const int SIZES_OF_ARRAYS_DOESNT_MATCH;
|
||||
}
|
||||
|
||||
/** Функции высшего порядка для массивов:
|
||||
/** Higher-order functions for arrays:
|
||||
*
|
||||
* arrayMap(x1,...,xn -> expression, array1,...,arrayn) - применить выражение к каждому элементу массива (или набора параллельных массивов).
|
||||
* arrayFilter(x -> predicate, array) - оставить в массиве только элементы, для которых выражение истинно.
|
||||
* arrayCount(x1,...,xn -> expression, array1,...,arrayn) - для скольки элементов массива выражение истинно.
|
||||
* arrayExists(x1,...,xn -> expression, array1,...,arrayn) - истинно ли выражение для хотя бы одного элемента массива.
|
||||
* arrayAll(x1,...,xn -> expression, array1,...,arrayn) - истинно ли выражение для всех элементов массива.
|
||||
* arrayMap(x1,...,xn -> expression, array1,...,arrayn) - apply the expression to each element of the array (or set of parallel arrays).
|
||||
* arrayFilter(x -> predicate, array) - leave in the array only the elements for which the expression is true.
|
||||
* arrayCount(x1,...,xn -> expression, array1,...,arrayn) - for how many elements of the array the expression is true.
|
||||
* arrayExists(x1,...,xn -> expression, array1,...,arrayn) - is the expression true for at least one array element.
|
||||
* arrayAll(x1,...,xn -> expression, array1,...,arrayn) - is the expression true for all elements of the array.
|
||||
*
|
||||
* Для функций arrayCount, arrayExists, arrayAll доступна еще перегрузка вида f(array), которая работает так же, как f(x -> x, array).
|
||||
* For functions arrayCount, arrayExists, arrayAll, an overload of the form f(array) is available, which works in the same way as f(x -> x, array).
|
||||
*/
|
||||
|
||||
struct ArrayMapImpl
|
||||
{
|
||||
/// true, если выражение (для перегрузки f(expression, arrays)) или массив (для f(array)) должно быть булевым.
|
||||
/// true if the expression (for an overload of f(expression, arrays)) or an array (for f(array)) should be boolean.
|
||||
static bool needBoolean() { return false; }
|
||||
/// true, если перегрузка f(array) недоступна.
|
||||
/// true if the f(array) overload is unavailable.
|
||||
static bool needExpression() { return true; }
|
||||
/// true, если массив должен быть ровно один.
|
||||
/// true if the array must be exactly one.
|
||||
static bool needOneArray() { return false; }
|
||||
|
||||
static DataTypePtr getReturnType(const DataTypePtr & expression_return, const DataTypePtr & array_element)
|
||||
@ -64,7 +64,7 @@ struct ArrayFilterImpl
|
||||
return std::make_shared<DataTypeArray>(array_element);
|
||||
}
|
||||
|
||||
/// Если массивов несколько, сюда передается первый.
|
||||
/// If there are several arrays, the first one is passed here.
|
||||
static ColumnPtr execute(const ColumnArray & array, ColumnPtr mapped)
|
||||
{
|
||||
const ColumnUInt8 * column_filter = typeid_cast<const ColumnUInt8 *>(&*mapped);
|
||||
@ -610,8 +610,8 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Вызывается, если хоть один агрумент функции - лямбда-выражение.
|
||||
/// Для аргументов-лямбда-выражений определяет типы аргументов этих выражений.
|
||||
/// Called if at least one function argument is a lambda expression.
|
||||
/// For argument-lambda expressions, it defines the types of arguments of these expressions.
|
||||
void getLambdaArgumentTypesImpl(DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() < 1)
|
||||
@ -679,7 +679,7 @@ public:
|
||||
throw Exception("Type of first argument for function " + getName() + " must be an expression.",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
/// Типы остальных аргументов уже проверены в getLambdaArgumentTypes.
|
||||
/// The types of the remaining arguments are already checked in getLambdaArgumentTypes.
|
||||
|
||||
DataTypePtr return_type = expression->getReturnType();
|
||||
if (Impl::needBoolean() && !typeid_cast<const DataTypeUInt8 *>(&*return_type))
|
||||
@ -735,9 +735,9 @@ public:
|
||||
throw Exception("Column of first argument for function " + getName() + " must be an expression.",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
/// Типы остальных аргументов уже проверены в getLambdaArgumentTypes.
|
||||
/// The types of the remaining arguments are already checked in getLambdaArgumentTypes.
|
||||
|
||||
/// Попросим добавить в блок все столбцы, упоминаемые в выражении, размноженные в массив, параллельный обрабатываемому.
|
||||
/// Let's add to the block all the columns mentioned in the expression, multiplied into an array parallel to the one being processed.
|
||||
const ExpressionActions & expression = *column_expression->getExpression();
|
||||
const NamesAndTypesList & required_columns = expression.getRequiredColumnsWithTypes();
|
||||
|
||||
@ -803,7 +803,7 @@ public:
|
||||
ColumnPtr column_first_array_ptr;
|
||||
const ColumnArray * column_first_array = nullptr;
|
||||
|
||||
/// Положим в блок аргументы выражения.
|
||||
/// Put the expression arguments in the block.
|
||||
|
||||
for (size_t i = 0; i < expression_arguments.size(); ++i)
|
||||
{
|
||||
@ -828,7 +828,7 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Первое условие - оптимизация: не сравнивать данные, если указатели равны.
|
||||
/// The first condition is optimization: do not compare data if the pointers are equal.
|
||||
if (column_array->getOffsetsColumn() != offsets_column
|
||||
&& column_array->getOffsets() != typeid_cast<const ColumnArray::ColumnOffsets_t &>(*offsets_column).getData())
|
||||
throw Exception("Arrays passed to " + getName() + " must have equal size", ErrorCodes::SIZES_OF_ARRAYS_DOESNT_MATCH);
|
||||
@ -848,7 +848,7 @@ public:
|
||||
argument_names.insert(argument_name);
|
||||
}
|
||||
|
||||
/// Положим в блок все нужные столбцы, размноженные по размерам массивов.
|
||||
/// Put all the necessary columns multiplied by the sizes of arrays into the block.
|
||||
|
||||
Names required_columns = expression.getRequiredColumns();
|
||||
size_t prerequisite_index = 0;
|
||||
|
@ -11,8 +11,8 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Функции - логические связки: and, or, not, xor.
|
||||
* Принимают любые числовые типы, возвращают UInt8, содержащий 0 или 1.
|
||||
/** Functions are logical links: and, or, not, xor.
|
||||
* Accept any numeric types, return a UInt8 containing 0 or 1.
|
||||
*/
|
||||
|
||||
template<typename B>
|
||||
@ -91,7 +91,7 @@ using UInt8ColumnPtrs = std::vector<const ColumnUInt8 *>;
|
||||
template <typename Op, size_t N>
|
||||
struct AssociativeOperationImpl
|
||||
{
|
||||
/// Выбрасывает N последних столбцов из in (если их меньше, то все) и кладет в result их комбинацию.
|
||||
/// Erases the N last columns from `in` (if there are less, then all) and puts into `result` their combination.
|
||||
static void execute(UInt8ColumnPtrs & in, UInt8Container & result)
|
||||
{
|
||||
if (N > in.size())
|
||||
@ -113,11 +113,11 @@ struct AssociativeOperationImpl
|
||||
const UInt8Container & vec;
|
||||
AssociativeOperationImpl<Op, N - 1> continuation;
|
||||
|
||||
/// Запоминает последние N столбцов из in.
|
||||
/// Remembers the last N columns from `in`.
|
||||
AssociativeOperationImpl(UInt8ColumnPtrs & in)
|
||||
: vec(in[in.size() - N]->getData()), continuation(in) {}
|
||||
|
||||
/// Возвращает комбинацию значений в i-й строке всех столбцов, запомненных в конструкторе.
|
||||
/// Returns a combination of values in the i-th row of all columns stored in the constructor.
|
||||
inline UInt8 apply(size_t i) const
|
||||
{
|
||||
if (Op::isSaturable())
|
||||
@ -252,7 +252,7 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
/// Get result types by argument types. If the function does not apply to these arguments, throw an exception.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() < 2)
|
||||
@ -281,11 +281,11 @@ public:
|
||||
}
|
||||
size_t n = in[0]->size();
|
||||
|
||||
/// Скомбинируем все константные столбцы в одно значение.
|
||||
/// Combine all constant columns into a single value.
|
||||
UInt8 const_val = 0;
|
||||
bool has_consts = extractConstColumns(in, const_val);
|
||||
|
||||
// Если это значение однозначно определяет результат, вернем его.
|
||||
// If this value uniquely determines the result, return it.
|
||||
if (has_consts && (in.empty() || Impl<UInt8>::apply(const_val, 0) == Impl<UInt8>::apply(const_val, 1)))
|
||||
{
|
||||
if (!in.empty())
|
||||
@ -295,7 +295,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
/// Если это значение - нейтральный элемент, забудем про него.
|
||||
/// If this value is a neutral element, let's forget about it.
|
||||
if (has_consts && Impl<UInt8>::apply(const_val, 0) == 0 && Impl<UInt8>::apply(const_val, 1) == 1)
|
||||
has_consts = false;
|
||||
|
||||
@ -313,8 +313,8 @@ public:
|
||||
vec_res.resize(n);
|
||||
}
|
||||
|
||||
/// Разделим входные столбцы на UInt8 и остальные. Первые обработаем более эффективно.
|
||||
/// col_res в каждый момент будет либо находится в конце uint8_in, либо не содержаться в uint8_in.
|
||||
/// Divide the input columns into UInt8 and the rest. The first will be processed more efficiently.
|
||||
/// col_res at each moment will either be at the end of uint8_in, or not contained in uint8_in.
|
||||
UInt8ColumnPtrs uint8_in;
|
||||
ColumnPlainPtrs other_in;
|
||||
for (IColumn * column : in)
|
||||
@ -325,7 +325,7 @@ public:
|
||||
other_in.push_back(column);
|
||||
}
|
||||
|
||||
/// Нужен хотя бы один столбец в uint8_in, чтобы было с кем комбинировать столбцы из other_in.
|
||||
/// You need at least one column in uint8_in, so that you can combine columns from other_in.
|
||||
if (uint8_in.empty())
|
||||
{
|
||||
if (other_in.empty())
|
||||
@ -336,16 +336,16 @@ public:
|
||||
uint8_in.push_back(col_res.get());
|
||||
}
|
||||
|
||||
/// Эффективно скомбинируем все столбцы правильного типа.
|
||||
/// Effectively combine all the columns of the correct type.
|
||||
while (uint8_in.size() > 1)
|
||||
{
|
||||
/// При большом размере блока объединять по 6 толбцов за проход быстрее всего.
|
||||
/// При маленьком - чем больше, тем быстрее.
|
||||
/// With a large block size, combining 6 columns per pass is the fastest.
|
||||
/// When small - more, is faster.
|
||||
AssociativeOperationImpl<Impl<UInt8>, 10>::execute(uint8_in, vec_res);
|
||||
uint8_in.push_back(col_res.get());
|
||||
}
|
||||
|
||||
/// По одному добавим все столбцы неправильного типа.
|
||||
/// Add all the columns of the wrong type one at a time.
|
||||
while (!other_in.empty())
|
||||
{
|
||||
executeUInt8Other(uint8_in[0]->getData(), other_in.back(), vec_res);
|
||||
@ -353,7 +353,7 @@ public:
|
||||
uint8_in[0] = col_res.get();
|
||||
}
|
||||
|
||||
/// Такое возможно, если среди аргументов ровно один неконстантный, и он имеет тип UInt8.
|
||||
/// This is possible if there is exactly one non-constant among the arguments, and it is of type UInt8.
|
||||
if (uint8_in[0] != col_res.get())
|
||||
{
|
||||
vec_res.assign(uint8_in[0]->getData());
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <Functions/FunctionsMiscellaneous.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <Poco/Net/DNS.h>
|
||||
#include <Common/ClickHouseRevision.h>
|
||||
#include <Columns/ColumnSet.h>
|
||||
|
@ -12,24 +12,24 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Функции генерации псевдослучайных чисел.
|
||||
* Функция может быть вызвана без аргументов или с одним аргументом.
|
||||
* Аргумент игнорируется и служит лишь для того, чтобы несколько вызовов одной функции считались разными и не склеивались.
|
||||
/** Pseudo-random number generation functions.
|
||||
* The function can be called without arguments or with one argument.
|
||||
* The argument is ignored and only serves to ensure that several calls to one function are considered different and do not stick together.
|
||||
*
|
||||
* Пример:
|
||||
* SELECT rand(), rand() - выдаст два одинаковых столбца.
|
||||
* SELECT rand(1), rand(2) - выдаст два разных столбца.
|
||||
* Example:
|
||||
* SELECT rand(), rand() - will output two identical columns.
|
||||
* SELECT rand(1), rand(2) - will output two different columns.
|
||||
*
|
||||
* Некриптографические генераторы:
|
||||
* Non-cryptographic generators:
|
||||
*
|
||||
* rand - linear congruental generator 0 .. 2^32 - 1.
|
||||
* rand64 - комбинирует несколько значений rand, чтобы получить значения из диапазона 0 .. 2^64 - 1.
|
||||
* rand64 - combines several rand values to get values from the range 0 .. 2^64 - 1.
|
||||
*
|
||||
* randConstant - служебная функция, выдаёт константный столбец со случайным значением.
|
||||
* randConstant - service function, produces a constant column with a random value.
|
||||
*
|
||||
* В качестве затравки используют время.
|
||||
* Замечание: переинициализируется на каждый блок.
|
||||
* Это значит, что таймер должен быть достаточного разрешения, чтобы выдавать разные значения на каждый блок.
|
||||
* The time is used as the seed.
|
||||
* Note: it is reinitialized for each block.
|
||||
* This means that the timer must be of sufficient resolution to give different values to each block.
|
||||
*/
|
||||
|
||||
namespace detail
|
||||
@ -42,11 +42,11 @@ namespace detail
|
||||
|
||||
struct LinearCongruentialGenerator
|
||||
{
|
||||
/// Константы из man lrand48_r.
|
||||
/// Constants from man lrand48_r.
|
||||
static constexpr UInt64 a = 0x5DEECE66D;
|
||||
static constexpr UInt64 c = 0xB;
|
||||
|
||||
/// А эта - из head -c8 /dev/urandom | xxd -p
|
||||
/// And this is from `head -c8 /dev/urandom | Xxd -p`
|
||||
UInt64 current = 0x09826f4a081cee35ULL;
|
||||
|
||||
LinearCongruentialGenerator() {}
|
||||
@ -194,7 +194,7 @@ class FunctionRandomConstant : public IFunction
|
||||
private:
|
||||
using ToType = typename Impl::ReturnType;
|
||||
|
||||
/// Значение одно для разных блоков.
|
||||
/// The value is one for different blocks.
|
||||
bool is_initialized = false;
|
||||
ToType value;
|
||||
|
||||
|
@ -15,19 +15,19 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Функции округления:
|
||||
* roundToExp2 - вниз до ближайшей степени двойки;
|
||||
* roundDuration - вниз до ближайшего из: 0, 1, 10, 30, 60, 120, 180, 240, 300, 600, 1200, 1800, 3600, 7200, 18000, 36000;
|
||||
* roundAge - вниз до ближайшего из: 0, 18, 25, 35, 45, 55.
|
||||
/** Rounding Functions:
|
||||
* roundToExp2 - down to the nearest power of two;
|
||||
* roundDuration - down to the nearest of: 0, 1, 10, 30, 60, 120, 180, 240, 300, 600, 1200, 1800, 3600, 7200, 18000, 36000;
|
||||
* roundAge - down to the nearest of: 0, 18, 25, 35, 45, 55.
|
||||
*
|
||||
* round(x, N) - арифметическое округление (N = 0 по умолчанию).
|
||||
* ceil(x, N) - наименьшее число, которое не меньше x (N = 0 по умолчанию).
|
||||
* floor(x, N) - наибольшее число, которое не больше x (N = 0 по умолчанию).
|
||||
* round(x, N) - arithmetic rounding (N = 0 by default).
|
||||
* ceil(x, N) is the smallest number that is at least x (N = 0 by default).
|
||||
* floor(x, N) is the largest number that is not greater than x (N = 0 by default).
|
||||
*
|
||||
* Значение параметра N:
|
||||
* - N > 0: округлять до числа с N десятичными знаками после запятой
|
||||
* - N < 0: окурглять до целого числа с N нулевыми знаками
|
||||
* - N = 0: округлять до целого числа
|
||||
* The value of the parameter N:
|
||||
* - N > 0: round to the number with N decimal places after the decimal point
|
||||
* - N < 0: round to an integer with N zero characters
|
||||
* - N = 0: round to an integer
|
||||
*/
|
||||
|
||||
template<typename A>
|
||||
@ -106,8 +106,8 @@ struct RoundAgeImpl
|
||||
}
|
||||
};
|
||||
|
||||
/** Быстрое вычисление остатка от деления для применения к округлению целых чисел.
|
||||
* Без проверки, потому что делитель всегда положительный.
|
||||
/** Quick calculation of the remainder of the division to apply to the rounding of integers.
|
||||
* Without verification, because the divisor is always positive.
|
||||
*/
|
||||
template<typename T, typename Enable = void>
|
||||
struct FastModulo;
|
||||
@ -161,14 +161,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** Этот параметр контролирует поведение функций округления.
|
||||
/** This parameter controls the behavior of the rounding functions.
|
||||
*/
|
||||
enum ScaleMode
|
||||
{
|
||||
PositiveScale, // округлять до числа с N десятичными знаками после запятой
|
||||
NegativeScale, // окурглять до целого числа с N нулевыми знаками
|
||||
ZeroScale, // округлять до целого числа
|
||||
NullScale // возвращать нулевое значение
|
||||
PositiveScale, // round to a number with N decimal places after the decimal point
|
||||
NegativeScale, // round to an integer with N zero characters
|
||||
ZeroScale, // round to an integer
|
||||
NullScale // return zero value
|
||||
};
|
||||
|
||||
#if !defined(_MM_FROUND_NINT)
|
||||
@ -177,7 +177,7 @@ enum ScaleMode
|
||||
#define _MM_FROUND_CEIL 2
|
||||
#endif
|
||||
|
||||
/** Реализация низкоуровневых функций округления для целочисленных значений.
|
||||
/** Implementing low-level rounding functions for integer values.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode, typename Enable = void>
|
||||
struct IntegerRoundingComputation;
|
||||
@ -283,7 +283,7 @@ public:
|
||||
static const size_t data_count = 4;
|
||||
|
||||
protected:
|
||||
/// Предотвратить появление отрицательных нолей определённых в стандарте IEEE-754.
|
||||
/// Prevent the appearance of negative zeros defined in the IEEE-754 standard.
|
||||
static inline void normalize(__m128 & val, const __m128 & mask)
|
||||
{
|
||||
__m128 mask1 = _mm_cmpeq_ps(val, getZero());
|
||||
@ -321,7 +321,7 @@ public:
|
||||
static const size_t data_count = 2;
|
||||
|
||||
protected:
|
||||
/// Предотвратить появление отрицательных нолей определённых в стандарте IEEE-754.
|
||||
/// Prevent the occurrence of negative zeros defined in the IEEE-754 standard.
|
||||
static inline void normalize(__m128d & val, const __m128d & mask)
|
||||
{
|
||||
__m128d mask1 = _mm_cmpeq_pd(val, getZero());
|
||||
@ -351,7 +351,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
/** Реализация низкоуровневых функций округления для значений с плавающей точкой.
|
||||
/** Implementation of low-level round-off functions for floating-point values.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
class FloatRoundingComputation;
|
||||
@ -372,7 +372,7 @@ public:
|
||||
__m128 val = _mm_loadu_ps(in);
|
||||
__m128 mask = _mm_cmplt_ps(val, getZero());
|
||||
|
||||
/// Алгоритм округления.
|
||||
/// Rounding algorithm.
|
||||
val = _mm_mul_ps(val, scale);
|
||||
val = _mm_round_ps(val, rounding_mode);
|
||||
val = _mm_div_ps(val, scale);
|
||||
@ -398,20 +398,20 @@ public:
|
||||
__m128 val = _mm_loadu_ps(in);
|
||||
__m128 mask = _mm_cmplt_ps(val, getZero());
|
||||
|
||||
/// Превратить отрицательные значения в положительные.
|
||||
/// Turn negative values into positive values.
|
||||
__m128 factor = _mm_cmpge_ps(val, getZero());
|
||||
factor = _mm_min_ps(factor, getTwo());
|
||||
factor = _mm_sub_ps(factor, getOne());
|
||||
val = _mm_mul_ps(val, factor);
|
||||
|
||||
/// Алгоритм округления.
|
||||
/// Rounding algorithm.
|
||||
val = _mm_div_ps(val, scale);
|
||||
__m128 res = _mm_cmpge_ps(val, getOneTenth());
|
||||
val = _mm_round_ps(val, rounding_mode);
|
||||
val = _mm_mul_ps(val, scale);
|
||||
val = _mm_and_ps(val, res);
|
||||
|
||||
/// Вернуть настоящие знаки всех значений.
|
||||
/// Return the real signs of all values.
|
||||
val = _mm_mul_ps(val, factor);
|
||||
|
||||
normalize(val, mask);
|
||||
@ -463,7 +463,7 @@ public:
|
||||
__m128d val = _mm_loadu_pd(in);
|
||||
__m128d mask = _mm_cmplt_pd(val, getZero());
|
||||
|
||||
/// Алгоритм округления.
|
||||
/// Rounding algorithm.
|
||||
val = _mm_mul_pd(val, scale);
|
||||
val = _mm_round_pd(val, rounding_mode);
|
||||
val = _mm_div_pd(val, scale);
|
||||
@ -489,20 +489,20 @@ public:
|
||||
__m128d val = _mm_loadu_pd(in);
|
||||
__m128d mask = _mm_cmplt_pd(val, getZero());
|
||||
|
||||
/// Превратить отрицательные значения в положительные.
|
||||
/// Turn negative values into positive values.
|
||||
__m128d factor = _mm_cmpge_pd(val, getZero());
|
||||
factor = _mm_min_pd(factor, getTwo());
|
||||
factor = _mm_sub_pd(factor, getOne());
|
||||
val = _mm_mul_pd(val, factor);
|
||||
|
||||
/// Алгоритм округления.
|
||||
/// Rounding algorithm.
|
||||
val = _mm_div_pd(val, scale);
|
||||
__m128d res = _mm_cmpge_pd(val, getOneTenth());
|
||||
val = _mm_round_pd(val, rounding_mode);
|
||||
val = _mm_mul_pd(val, scale);
|
||||
val = _mm_and_pd(val, res);
|
||||
|
||||
/// Вернуть настоящие знаки всех значений.
|
||||
/// Return the real signs of all values.
|
||||
val = _mm_mul_pd(val, factor);
|
||||
|
||||
normalize(val, mask);
|
||||
@ -538,7 +538,7 @@ public:
|
||||
}
|
||||
};
|
||||
#else
|
||||
/// Реализация для ARM. Не векторизована. Не исправляет отрицательные нули.
|
||||
/// Implementation for ARM. Not vectorized. Does not fix negative zeros.
|
||||
|
||||
template <int mode>
|
||||
float roundWithMode(float x)
|
||||
@ -613,12 +613,12 @@ public:
|
||||
#endif
|
||||
|
||||
|
||||
/** Реализация высокоуровневых функций округления.
|
||||
/** Implementing high-level rounding functions.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode, typename Enable = void>
|
||||
struct FunctionRoundingImpl;
|
||||
|
||||
/** Реализация высокоуровневых функций округления для целочисленных значений.
|
||||
/** Implement high-level rounding functions for integer values.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct FunctionRoundingImpl<T, rounding_mode, scale_mode,
|
||||
@ -650,7 +650,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** Реализация высокоуровневых функций округления для значений с плавающей точкой.
|
||||
/** Implement high-level round-off functions for floating-point values.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct FunctionRoundingImpl<T, rounding_mode, scale_mode,
|
||||
@ -730,7 +730,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** Реализация высокоуровневых функций округления в том случае, когда возвращается нулевое значение.
|
||||
/** Implementation of high-level rounding functions in the case when a zero value is returned.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct FunctionRoundingImpl<T, rounding_mode, scale_mode,
|
||||
@ -748,11 +748,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Следующий код генерирует во время сборки таблицу степеней числа 10.
|
||||
/// The following code generates a table of powers of 10 during the build.
|
||||
|
||||
namespace
|
||||
{
|
||||
/// Отдельные степени числа 10.
|
||||
/// Individual degrees of the number 10.
|
||||
|
||||
template<size_t N>
|
||||
struct PowerOf10
|
||||
@ -767,7 +767,7 @@ namespace
|
||||
};
|
||||
}
|
||||
|
||||
/// Объявление и определение контейнера содержащего таблицу степеней числа 10.
|
||||
/// Declaring and defining a container containing a table of powers of 10.
|
||||
|
||||
template<size_t... TArgs>
|
||||
struct TableContainer
|
||||
@ -778,7 +778,7 @@ struct TableContainer
|
||||
template<size_t... TArgs>
|
||||
const std::array<size_t, sizeof...(TArgs)> TableContainer<TArgs...>::values {{ TArgs... }};
|
||||
|
||||
/// Генератор первых N степеней.
|
||||
/// The generator of the first N degrees.
|
||||
|
||||
template<size_t N, size_t... TArgs>
|
||||
struct FillArrayImpl
|
||||
@ -798,9 +798,9 @@ struct FillArray
|
||||
using result = typename FillArrayImpl<N - 1>::result;
|
||||
};
|
||||
|
||||
/** Этот шаблон определяет точность, которую используют функции round/ceil/floor,
|
||||
* затем преобразовывает её в значение, которое можно использовать в операциях
|
||||
* умножения и деления. Поэтому оно называется масштабом.
|
||||
/** This pattern defines the precision that the round/ceil/floor functions use,
|
||||
* then converts it to a value that can be used in operations of
|
||||
* multiplication and division. Therefore, it is called a scale.
|
||||
*/
|
||||
template<typename T, typename U, typename Enable = void>
|
||||
struct ScaleForRightType;
|
||||
@ -944,7 +944,7 @@ struct ScaleForRightType<T, U,
|
||||
}
|
||||
};
|
||||
|
||||
/** Превратить параметр точности в масштаб.
|
||||
/** Turn the precision parameter into a scale.
|
||||
*/
|
||||
template<typename T>
|
||||
struct ScaleForLeftType
|
||||
@ -968,7 +968,7 @@ struct ScaleForLeftType
|
||||
}
|
||||
};
|
||||
|
||||
/** Главный шаблон применяющий функцию округления к значению или столбцу.
|
||||
/** The main template that applies the rounding function to a value or column.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct Cruncher
|
||||
@ -997,7 +997,7 @@ struct Cruncher
|
||||
}
|
||||
};
|
||||
|
||||
/** Выбрать подходящий алгоритм обработки в зависимости от масштаба.
|
||||
/** Select the appropriate processing algorithm depending on the scale.
|
||||
*/
|
||||
template<typename T, template <typename> class U, int rounding_mode>
|
||||
struct Dispatcher
|
||||
@ -1028,9 +1028,9 @@ struct Dispatcher
|
||||
}
|
||||
};
|
||||
|
||||
/** Шаблон для функций, которые округляют значение входного параметра типа
|
||||
* (U)Int8/16/32/64 или Float32/64, и принимают дополнительный необязятельный
|
||||
* параметр (по умолчанию - 0).
|
||||
/** A template for functions that round the value of an input parameter of type
|
||||
* (U)Int8/16/32/64 or Float32/64, and accept an additional optional
|
||||
* parameter (default is 0).
|
||||
*/
|
||||
template<typename Name, int rounding_mode>
|
||||
class FunctionRounding : public IFunction
|
||||
@ -1072,7 +1072,7 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
/// Get result types by argument types. If the function does not apply to these arguments, throw an exception.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if ((arguments.size() < 1) || (arguments.size() > 2))
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <Functions/FunctionsString.h>
|
||||
|
||||
#include <ext/range.hpp>
|
||||
#include <ext/range.h>
|
||||
#include <Columns/ColumnArray.h>
|
||||
#include <DataTypes/DataTypeArray.h>
|
||||
#include <Functions/FunctionFactory.h>
|
||||
@ -102,6 +102,7 @@ struct LengthImpl
|
||||
|
||||
/** If the string is UTF-8 encoded text, it returns the length of the text in code points.
|
||||
* (not in characters: the length of the text "ё" can be either 1 or 2, depending on the normalization)
|
||||
* (not in characters: the length of the text "" can be either 1 or 2, depending on the normalization)
|
||||
* Otherwise, the behavior is undefined.
|
||||
*/
|
||||
struct LengthUTF8Impl
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
namespace DB
|
||||
{
|
||||
/** Функции работы со строками:
|
||||
/** String functions
|
||||
*
|
||||
* length, empty, notEmpty,
|
||||
* concat, substring, lower, upper, reverse
|
||||
@ -26,11 +26,11 @@ namespace DB
|
||||
* s, c1, c2 -> s: substring, substringUTF8
|
||||
* s, c1, c2, s2 -> s: replace, replaceUTF8
|
||||
*
|
||||
* Функции поиска строк и регулярных выражений расположены отдельно.
|
||||
* Функции работы с URL расположены отдельно.
|
||||
* Функции кодирования строк, конвертации в другие типы расположены отдельно.
|
||||
* The search functions for strings and regular expressions are located separately.
|
||||
* URL functions are located separately.
|
||||
* String encoding functions, converting to other types are located separately.
|
||||
*
|
||||
* Функции length, empty, notEmpty, reverse также работают с массивами.
|
||||
* The functions length, empty, notEmpty, reverse also work with arrays.
|
||||
*/
|
||||
|
||||
|
||||
@ -89,10 +89,10 @@ inline void UTF8CyrillicToCase(const UInt8 *& src, const UInt8 * const src_end,
|
||||
}
|
||||
|
||||
|
||||
/** Если строка содержит текст в кодировке UTF-8 - перевести его в нижний (верхний) регистр.
|
||||
* Замечание: предполагается, что после перевода символа в другой регистр,
|
||||
* длина его мультибайтовой последовательности в UTF-8 не меняется.
|
||||
* Иначе - поведение не определено.
|
||||
/** If the string contains UTF-8 encoded text, convert it to the lower (upper) case.
|
||||
* Note: It is assumed that after the character is converted to another case,
|
||||
* the length of its multibyte sequence in UTF-8 does not change.
|
||||
* Otherwise, the behavior is undefined.
|
||||
*/
|
||||
template <char not_case_lower_bound,
|
||||
char not_case_upper_bound,
|
||||
|
@ -15,31 +15,31 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Функции, разделяющие строки на массив строк или наоборот.
|
||||
/** Functions that split strings into an array of strings or vice versa.
|
||||
*
|
||||
* splitByChar(sep, s)
|
||||
* splitByString(sep, s)
|
||||
* splitByRegexp(regexp, s)
|
||||
*
|
||||
* extractAll(s, regexp) - выделить из строки подпоследовательности, соответствующие регекспу.
|
||||
* - первый subpattern, если в regexp-е есть subpattern;
|
||||
* - нулевой subpattern (сматчившуюся часть, иначе);
|
||||
* - инача, пустой массив
|
||||
* extractAll(s, regexp) - select from the string the subsequences corresponding to the regexp.
|
||||
* - first subpattern, if regexp has subpattern;
|
||||
* - zero subpattern (the match part, otherwise);
|
||||
* - otherwise, an empty array
|
||||
*
|
||||
* arrayStringConcat(arr)
|
||||
* arrayStringConcat(arr, delimiter)
|
||||
* - склеить массив строк в одну строку через разделитель.
|
||||
* - join an array of strings into one string via a separator.
|
||||
*
|
||||
* alphaTokens(s) - выделить из строки подпоследовательности [a-zA-Z]+.
|
||||
* alphaTokens(s) - select from the string subsequence `[a-zA-Z]+`.
|
||||
*
|
||||
* Функции работы с URL расположены отдельно.
|
||||
* URL functions are located separately.
|
||||
*/
|
||||
|
||||
|
||||
using Pos = const char *;
|
||||
|
||||
|
||||
/// Генераторы подстрок. Все они обладают общим интерфейсом.
|
||||
/// Substring generators. All of them have a common interface.
|
||||
|
||||
class AlphaTokensImpl
|
||||
{
|
||||
@ -48,13 +48,13 @@ private:
|
||||
Pos end;
|
||||
|
||||
public:
|
||||
/// Получить имя фукнции.
|
||||
/// Get the name of the function.
|
||||
static constexpr auto name = "alphaTokens";
|
||||
static String getName() { return name; }
|
||||
|
||||
static size_t getNumberOfArguments() { return 1; }
|
||||
|
||||
/// Проверить типы агрументов функции.
|
||||
/// Check the type of the function's arguments.
|
||||
static void checkArguments(const DataTypes & arguments)
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]))
|
||||
@ -62,23 +62,23 @@ public:
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
}
|
||||
|
||||
/// Инициализировать по аргументам функции.
|
||||
/// Initialize by the function arguments.
|
||||
void init(Block & block, const ColumnNumbers & arguments) {}
|
||||
|
||||
/// Вызывается для каждой следующей строки.
|
||||
/// Called for each next string.
|
||||
void set(Pos pos_, Pos end_)
|
||||
{
|
||||
pos = pos_;
|
||||
end = end_;
|
||||
}
|
||||
|
||||
/// Возвращает позицию аргумента, являющегося столбцом строк
|
||||
/// Returns the position of the argument, that is the column of strings
|
||||
size_t getStringsArgumentPosition()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Получить следующий токен, если есть, или вернуть false.
|
||||
/// Get the next token, if any, or return false.
|
||||
bool get(Pos & token_begin, Pos & token_end)
|
||||
{
|
||||
/// Skip garbage
|
||||
@ -141,7 +141,7 @@ public:
|
||||
sep = sep_str[0];
|
||||
}
|
||||
|
||||
/// Возвращает позицию аргумента, являющегося столбцом строк
|
||||
/// Returns the position of the argument, that is the column of strings
|
||||
size_t getStringsArgumentPosition()
|
||||
{
|
||||
return 1;
|
||||
@ -204,20 +204,20 @@ public:
|
||||
sep = col->getData();
|
||||
}
|
||||
|
||||
/// Возвращает позицию аргумента, являющегося столбцом строк
|
||||
/// Returns the position of the argument that is the column of strings
|
||||
size_t getStringsArgumentPosition()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// Вызывается для каждой следующей строки.
|
||||
/// Called for each next string.
|
||||
void set(Pos pos_, Pos end_)
|
||||
{
|
||||
pos = pos_;
|
||||
end = end_;
|
||||
}
|
||||
|
||||
/// Получить следующий токен, если есть, или вернуть false.
|
||||
/// Get the next token, if any, or return false.
|
||||
bool get(Pos & token_begin, Pos & token_end)
|
||||
{
|
||||
if (!pos)
|
||||
@ -252,13 +252,13 @@ public:
|
||||
static String getName() { return name; }
|
||||
static size_t getNumberOfArguments() { return 2; }
|
||||
|
||||
/// Проверить типы агрументов функции.
|
||||
/// Check the type of function arguments.
|
||||
static void checkArguments( const DataTypes & arguments )
|
||||
{
|
||||
SplitByStringImpl::checkArguments(arguments);
|
||||
}
|
||||
|
||||
/// Инициализировать по аргументам функции.
|
||||
/// Initialize by the function arguments.
|
||||
void init(Block & block, const ColumnNumbers & arguments)
|
||||
{
|
||||
const ColumnConstString * col = typeid_cast<const ColumnConstString *>(block.safeGetByPosition(arguments[1]).column.get());
|
||||
@ -274,20 +274,20 @@ public:
|
||||
matches.resize(capture + 1);
|
||||
}
|
||||
|
||||
/// Возвращает позицию аргумента, являющегося столбцом строк
|
||||
/// Returns the position of the argument that is the column of strings
|
||||
size_t getStringsArgumentPosition()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Вызывается для каждой следующей строки.
|
||||
/// Called for each next string.
|
||||
void set(Pos pos_, Pos end_)
|
||||
{
|
||||
pos = pos_;
|
||||
end = end_;
|
||||
}
|
||||
|
||||
/// Получить следующий токен, если есть, или вернуть false.
|
||||
/// Get the next token, if any, or return false.
|
||||
bool get(Pos & token_begin, Pos & token_end)
|
||||
{
|
||||
if (!pos || pos > end)
|
||||
@ -305,7 +305,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Функция, принимающая строку, и возвращающая массив подстрок, создаваемый некоторым генератором.
|
||||
/// A function that takes a string, and returns an array of substrings created by some generator.
|
||||
template <typename Generator>
|
||||
class FunctionTokens : public IFunction
|
||||
{
|
||||
@ -350,7 +350,7 @@ public:
|
||||
const ColumnString::Offsets_t & src_offsets = col_str->getOffsets();
|
||||
|
||||
res_offsets.reserve(src_offsets.size());
|
||||
res_strings_offsets.reserve(src_offsets.size() * 5); /// Константа 5 - наугад.
|
||||
res_strings_offsets.reserve(src_offsets.size() * 5); /// Constant 5 - at random.
|
||||
res_strings_chars.reserve(src_chars.size());
|
||||
|
||||
Pos token_begin = nullptr;
|
||||
@ -411,7 +411,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/// Склеивает массив строк в одну строку через разделитель.
|
||||
/// Joins an array of strings into one string via a separator.
|
||||
class FunctionArrayStringConcat : public IFunction
|
||||
{
|
||||
private:
|
||||
@ -428,14 +428,14 @@ private:
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
/// С небольшим запасом - как будто разделитель идёт и после последней строки массива.
|
||||
/// With a small margin - as if the separator goes after the last string of the array.
|
||||
dst_chars.resize(
|
||||
src_chars.size()
|
||||
+ delimiter_size * src_string_offsets.size() /// Разделители после каждой строки...
|
||||
+ src_array_offsets.size() /// Нулевой байт после каждой склеенной строки
|
||||
- src_string_offsets.size()); /// Бывший нулевой байт после каждой строки массива
|
||||
+ delimiter_size * src_string_offsets.size() /// Separators after each string...
|
||||
+ src_array_offsets.size() /// Zero byte after each joined string
|
||||
- src_string_offsets.size()); /// The former zero byte after each string of the array
|
||||
|
||||
/// Будет столько строк, сколько было массивов.
|
||||
/// There will be as many strings as there were arrays.
|
||||
dst_string_offsets.resize(src_array_offsets.size());
|
||||
|
||||
ColumnArray::Offset_t current_src_array_offset = 0;
|
||||
@ -443,10 +443,10 @@ private:
|
||||
|
||||
ColumnString::Offset_t current_dst_string_offset = 0;
|
||||
|
||||
/// Цикл по массивам строк.
|
||||
/// Loop through the array of strings.
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
/// Цикл по строкам внутри массива. /// NOTE Можно всё сделать за одно копирование, если разделитель имеет размер 1.
|
||||
/// Loop through the rows within the array. /// NOTE You can do everything in one copy, if the separator has a size of 1.
|
||||
for (auto next_src_array_offset = src_array_offsets[i]; current_src_array_offset < next_src_array_offset; ++current_src_array_offset)
|
||||
{
|
||||
size_t bytes_to_copy = src_string_offsets[current_src_array_offset] - current_src_string_offset - 1;
|
||||
|
@ -10,31 +10,31 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Функции поиска и замены в строках:
|
||||
/** Search and replace functions in strings:
|
||||
*
|
||||
* position(haystack, needle) - обычный поиск подстроки в строке, возвращает позицию (в байтах) найденной подстроки, начиная с 1, или 0, если подстрока не найдена.
|
||||
* positionUTF8(haystack, needle) - то же самое, но позиция вычисляется в кодовых точках, при условии, что строка в кодировке UTF-8.
|
||||
* position(haystack, needle) - the normal search for a substring in a string, returns the position (in bytes) of the found substring starting with 1, or 0 if no substring is found.
|
||||
* positionUTF8(haystack, needle) - the same, but the position is calculated at code points, provided that the string is encoded in UTF-8.
|
||||
* positionCaseInsensitive(haystack, needle)
|
||||
* positionCaseInsensitiveUTF8(haystack, needle)
|
||||
*
|
||||
* like(haystack, pattern) - поиск по регулярному выражению LIKE; возвращает 0 или 1. Регистронезависимое, но только для латиницы.
|
||||
* like(haystack, pattern) - search by the regular expression LIKE; Returns 0 or 1. Case-insensitive, but only for Latin.
|
||||
* notLike(haystack, pattern)
|
||||
*
|
||||
* match(haystack, pattern) - поиск по регулярному выражению re2; возвращает 0 или 1.
|
||||
* match(haystack, pattern) - search by regular expression re2; Returns 0 or 1.
|
||||
*
|
||||
* Применяет регексп re2 и достаёт:
|
||||
* - первый subpattern, если в regexp-е есть subpattern;
|
||||
* - нулевой subpattern (сматчившуюся часть, иначе);
|
||||
* - если не сматчилось - пустую строку.
|
||||
* Applies regexp re2 and pulls:
|
||||
* - the first subpattern, if the regexp has a subpattern;
|
||||
* - the zero subpattern (the match part, otherwise);
|
||||
* - if not match - an empty string.
|
||||
* extract(haystack, pattern)
|
||||
*
|
||||
* replaceOne(haystack, pattern, replacement) - замена шаблона по заданным правилам, только первое вхождение.
|
||||
* replaceAll(haystack, pattern, replacement) - замена шаблона по заданным правилам, все вхождения.
|
||||
* replaceOne(haystack, pattern, replacement) - replacing the pattern with the specified rules, only the first occurrence.
|
||||
* replaceAll(haystack, pattern, replacement) - replacing the pattern with the specified rules, all occurrences.
|
||||
*
|
||||
* replaceRegexpOne(haystack, pattern, replacement) - замена шаблона по заданному регекспу, только первое вхождение.
|
||||
* replaceRegexpAll(haystack, pattern, replacement) - замена шаблона по заданному регекспу, все вхождения.
|
||||
* replaceRegexpOne(haystack, pattern, replacement) - replaces the pattern with the specified regexp, only the first occurrence.
|
||||
* replaceRegexpAll(haystack, pattern, replacement) - replaces the pattern with the specified type, all occurrences.
|
||||
*
|
||||
* Внимание! На данный момент, аргументы needle, pattern, n, replacement обязаны быть константами.
|
||||
* Warning! At this point, the arguments needle, pattern, n, replacement must be constants.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -25,30 +25,30 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
|
||||
/** transform(x, from_array, to_array[, default]) - преобразовать x согласно переданному явным образом соответствию.
|
||||
/** transform(x, from_array, to_array[, default]) - convert x according to an explicitly passed match.
|
||||
*/
|
||||
|
||||
DataTypeTraits::EnrichedDataTypePtr getSmallestCommonNumericType(const DataTypeTraits::EnrichedDataTypePtr & type1, const IDataType & type2);
|
||||
|
||||
/** transform(x, [from...], [to...], default)
|
||||
* - преобразует значения согласно явно указанному отображению.
|
||||
* - converts the values according to the explicitly specified mapping.
|
||||
*
|
||||
* x - что преобразовывать.
|
||||
* from - константный массив значений для преобразования.
|
||||
* to - константный массив значений, в которые должны быть преобразованы значения из from.
|
||||
* default - какое значение использовать, если x не равен ни одному из значений во from.
|
||||
* from и to - массивы одинаковых размеров.
|
||||
* x - what to transform.
|
||||
* from - a constant array of values for the transformation.
|
||||
* to - a constant array of values into which values from `from` must be transformed.
|
||||
* default - what value to use if x is not equal to any of the values in `from`.
|
||||
* `from` and `to` - arrays of the same size.
|
||||
*
|
||||
* Типы:
|
||||
* Types:
|
||||
* transform(T, Array(T), Array(U), U) -> U
|
||||
*
|
||||
* transform(x, [from...], [to...])
|
||||
* - eсли default не указан, то для значений x, для которых нет соответствующего элемента во from, возвращается не изменённое значение x.
|
||||
* - if `default` is not specified, then for values of `x` for which there is no corresponding element in `from`, the unchanged value of `x` is returned.
|
||||
*
|
||||
* Типы:
|
||||
* Types:
|
||||
* transform(T, Array(T), Array(T)) -> T
|
||||
*
|
||||
* Замечание: реализация довольно громоздкая.
|
||||
* Note: the implementation is rather cumbersome.
|
||||
*/
|
||||
class FunctionTransform : public IFunction
|
||||
{
|
||||
@ -131,12 +131,12 @@ public:
|
||||
|
||||
if (type_arr_to_nested->behavesAsNumber() && type_default->behavesAsNumber())
|
||||
{
|
||||
/// Берём наименьший общий тип для элементов массива значений to и для default-а.
|
||||
/// We take the smallest common type for the elements of the array of values `to` and for `default`.
|
||||
DataTypeTraits::EnrichedDataTypePtr res = getSmallestCommonNumericType(enriched_type_arr_to_nested, *type_default);
|
||||
return res.first;
|
||||
}
|
||||
|
||||
/// TODO Больше проверок.
|
||||
/// TODO More checks.
|
||||
return type_arr_to_nested->clone();
|
||||
}
|
||||
}
|
||||
@ -189,7 +189,7 @@ public:
|
||||
private:
|
||||
void executeConst(Block & block, const ColumnNumbers & arguments, const size_t result)
|
||||
{
|
||||
/// Составим блок из полноценных столбцов размера 1 и вычислим функцию как обычно.
|
||||
/// Construct a block of full-size columns of size 1 and compute the function as usual.
|
||||
|
||||
Block tmp_block;
|
||||
ColumnNumbers tmp_arguments;
|
||||
@ -724,10 +724,10 @@ private:
|
||||
}
|
||||
|
||||
|
||||
/// Разные варианты хэш-таблиц для реализации отображения.
|
||||
/// Different versions of the hash tables to implement the mapping.
|
||||
|
||||
using NumToNum = HashMap<UInt64, UInt64, HashCRC32<UInt64>>;
|
||||
using NumToString = HashMap<UInt64, StringRef, HashCRC32<UInt64>>; /// Везде StringRef-ы с завершающим нулём.
|
||||
using NumToString = HashMap <UInt64, StringRef, HashCRC32 <UInt64 >>; /// Everywhere StringRef's with trailing zero.
|
||||
using StringToNum = HashMap<StringRef, UInt64, StringRefHash>;
|
||||
using StringToString = HashMap<StringRef, StringRef, StringRefHash>;
|
||||
|
||||
@ -738,12 +738,12 @@ private:
|
||||
|
||||
Arena string_pool;
|
||||
|
||||
Field const_default_value; /// Null, если не задано.
|
||||
Field const_default_value; /// Null, if not specified.
|
||||
|
||||
bool prepared = false;
|
||||
std::mutex mutex;
|
||||
|
||||
/// Может вызываться из разных потоков. Срабатывает только при первом вызове.
|
||||
/// Can be called from different threads. It works only on the first call.
|
||||
void prepare(const Array & from, const Array & to, Block & block, const ColumnNumbers & arguments)
|
||||
{
|
||||
if (prepared)
|
||||
@ -764,7 +764,7 @@ private:
|
||||
Array converted_to;
|
||||
const Array * used_to = &to;
|
||||
|
||||
/// Задано ли значение по-умолчанию.
|
||||
/// Whether the default value is set.
|
||||
|
||||
if (arguments.size() == 4)
|
||||
{
|
||||
@ -774,7 +774,7 @@ private:
|
||||
if (const_default_col)
|
||||
const_default_value = (*const_default_col)[0];
|
||||
|
||||
/// Нужно ли преобразовать элементы to и default_value к наименьшему общему типу, который является Float64?
|
||||
/// Do I need to convert the elements `to` and `default_value` to the smallest common type that is Float64?
|
||||
bool default_col_is_float =
|
||||
typeid_cast<const ColumnFloat32 *>(default_col)
|
||||
|| typeid_cast<const ColumnFloat64 *>(default_col)
|
||||
@ -797,7 +797,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
/// Замечание: не делается проверка дубликатов в массиве from.
|
||||
/// Note: Do not check the duplicates in the `from` array.
|
||||
|
||||
if (from[0].getType() != Field::Types::String && to[0].getType() != Field::Types::String)
|
||||
{
|
||||
|
@ -20,7 +20,9 @@ static size_t decodeURL(const char * src, size_t src_size, char * dst)
|
||||
src_curr_pos = find_first_symbols<'%'>(src_curr_pos, src_end);
|
||||
|
||||
if (src_curr_pos == src_end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (src_end - src_curr_pos < 3)
|
||||
{
|
||||
src_curr_pos = src_end;
|
||||
@ -28,8 +30,8 @@ static size_t decodeURL(const char * src, size_t src_size, char * dst)
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char high = char_to_digit_table[static_cast<unsigned char>(src_curr_pos[1])];
|
||||
unsigned char low = char_to_digit_table[static_cast<unsigned char>(src_curr_pos[2])];
|
||||
unsigned char high = unhex(src_curr_pos[1]);
|
||||
unsigned char low = unhex(src_curr_pos[2]);
|
||||
|
||||
if (high != 0xFF && low != 0xFF)
|
||||
{
|
||||
|
@ -258,7 +258,7 @@ struct ExtractTopLevelDomain
|
||||
|
||||
if (!last_dot)
|
||||
return;
|
||||
/// Для IPv4-адресов не выделяем ничего.
|
||||
/// For IPv4 addresses select nothing.
|
||||
if (last_dot[1] <= '9')
|
||||
return;
|
||||
|
||||
@ -380,7 +380,7 @@ struct ExtractQueryStringAndFragment
|
||||
}
|
||||
};
|
||||
|
||||
/// С точкой на конце.
|
||||
/// With dot at the end.
|
||||
struct ExtractWWW
|
||||
{
|
||||
static void execute(Pos data, size_t size, Pos & res_data, size_t & res_size)
|
||||
@ -526,11 +526,11 @@ struct CutURLParameterImpl
|
||||
begin_pos = pos;
|
||||
end_pos = begin_pos + param_len;
|
||||
|
||||
/// Пропустим значение.
|
||||
/// Skip the value.
|
||||
while (*end_pos && *end_pos != '&' && *end_pos != '#')
|
||||
++end_pos;
|
||||
|
||||
/// Захватим '&' до или после параметра.
|
||||
/// Capture '&' before or after the parameter.
|
||||
if (*end_pos == '&')
|
||||
++end_pos;
|
||||
else if (begin_pos[-1] == '&')
|
||||
@ -573,13 +573,13 @@ public:
|
||||
|
||||
void init(Block & block, const ColumnNumbers & arguments) {}
|
||||
|
||||
/// Возвращает позицию аргумента, являющегося столбцом строк
|
||||
/// Returns the position of the argument that is the column of rows
|
||||
size_t getStringsArgumentPosition()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Вызывается для каждой следующей строки.
|
||||
/// Called for each next string.
|
||||
void set(Pos pos_, Pos end_)
|
||||
{
|
||||
pos = pos_;
|
||||
@ -587,7 +587,7 @@ public:
|
||||
first = true;
|
||||
}
|
||||
|
||||
/// Получить следующий токен, если есть, или вернуть false.
|
||||
/// Get the next token, if any, or return false.
|
||||
bool get(Pos & token_begin, Pos & token_end)
|
||||
{
|
||||
if (pos == nullptr)
|
||||
@ -656,7 +656,7 @@ public:
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
}
|
||||
|
||||
/// Возвращает позицию аргумента, являющегося столбцом строк
|
||||
/// Returns the position of the argument that is the column of rows
|
||||
size_t getStringsArgumentPosition()
|
||||
{
|
||||
return 0;
|
||||
@ -664,7 +664,7 @@ public:
|
||||
|
||||
void init(Block & block, const ColumnNumbers & arguments) {}
|
||||
|
||||
/// Вызывается для каждой следующей строки.
|
||||
/// Called for each next string.
|
||||
void set(Pos pos_, Pos end_)
|
||||
{
|
||||
pos = pos_;
|
||||
@ -672,7 +672,7 @@ public:
|
||||
first = true;
|
||||
}
|
||||
|
||||
/// Получить следующий токен, если есть, или вернуть false.
|
||||
/// Get the next token, if any, or return false.
|
||||
bool get(Pos & token_begin, Pos & token_end)
|
||||
{
|
||||
if (pos == nullptr)
|
||||
@ -735,38 +735,37 @@ public:
|
||||
|
||||
void init(Block & block, const ColumnNumbers & arguments) {}
|
||||
|
||||
/// Возвращает позицию аргумента, являющегося столбцом строк
|
||||
/// Returns the position of the argument that is the column of rows
|
||||
size_t getStringsArgumentPosition()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Вызывается для каждой следующей строки.
|
||||
/// Called for each next string.
|
||||
void set(Pos pos_, Pos end_)
|
||||
{
|
||||
begin = pos = pos_;
|
||||
end = end_;
|
||||
}
|
||||
|
||||
/// Получить следующий токен, если есть, или вернуть false.
|
||||
/// Get the next token, if any, or return false.
|
||||
bool get(Pos & token_begin, Pos & token_end)
|
||||
{
|
||||
/// Код из URLParser.
|
||||
|
||||
/// Code from URLParser.
|
||||
if (pos == end)
|
||||
return false;
|
||||
|
||||
if (pos == begin)
|
||||
{
|
||||
/// Распарсим всё, что идёт до пути
|
||||
/// Let's parse everything that goes before the path
|
||||
|
||||
/// Предположим, что протокол уже переведён в нижний регистр.
|
||||
/// Assume that the protocol has already been changed to lowercase.
|
||||
while (pos < end && ((*pos > 'a' && *pos < 'z') || (*pos > '0' && *pos < '9')))
|
||||
++pos;
|
||||
|
||||
/** Будем вычислять иерархию только для URL-ов, в которых есть протокол, и после него идут два слеша.
|
||||
* (http, file - подходят, mailto, magnet - не подходят), и после двух слешей ещё хоть что-нибудь есть
|
||||
* Для остальных просто вернём полный URL как единственный элемент иерархии.
|
||||
/** We will calculate the hierarchy only for URLs in which there is a protocol, and after it there are two slashes.
|
||||
* (http, file - fit, mailto, magnet - do not fit), and after two slashes still at least something is there
|
||||
* For the rest, simply return the full URL as the only element of the hierarchy.
|
||||
*/
|
||||
if (pos == begin || pos == end || !(*pos++ == ':' && pos < end && *pos++ == '/' && pos < end && *pos++ == '/' && pos < end))
|
||||
{
|
||||
@ -776,7 +775,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Доменом для простоты будем считать всё, что после протокола и двух слешей, до следующего слеша или до ? или до #
|
||||
/// The domain for simplicity is everything that after the protocol and two slashes, until the next slash or `?` or `#`
|
||||
while (pos < end && !(*pos == '/' || *pos == '?' || *pos == '#'))
|
||||
++pos;
|
||||
|
||||
@ -789,7 +788,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Идём до следующего / или ? или #, пропуская все те, что вначале.
|
||||
/// We go to the next `/` or `?` or `#`, skipping all those at the beginning.
|
||||
while (pos < end && (*pos == '/' || *pos == '?' || *pos == '#'))
|
||||
++pos;
|
||||
if (pos == end)
|
||||
@ -831,13 +830,13 @@ public:
|
||||
|
||||
void init(Block & block, const ColumnNumbers & arguments) {}
|
||||
|
||||
/// Возвращает позицию аргумента, являющегося столбцом строк
|
||||
/// Returns the position of the argument that is the column of rows
|
||||
size_t getStringsArgumentPosition()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Вызывается для каждой следующей строки.
|
||||
/// Called for each next string.
|
||||
void set(Pos pos_, Pos end_)
|
||||
{
|
||||
begin = pos = pos_;
|
||||
@ -845,25 +844,25 @@ public:
|
||||
end = end_;
|
||||
}
|
||||
|
||||
/// Получить следующий токен, если есть, или вернуть false.
|
||||
/// Get the next token, if any, or return false.
|
||||
bool get(Pos & token_begin, Pos & token_end)
|
||||
{
|
||||
/// Код из URLParser.
|
||||
/// Code from URLParser.
|
||||
|
||||
if (pos == end)
|
||||
return false;
|
||||
|
||||
if (pos == begin)
|
||||
{
|
||||
/// Распарсим всё, что идёт до пути
|
||||
/// Let's parse everything that goes before the path
|
||||
|
||||
/// Предположим, что протокол уже переведён в нижний регистр.
|
||||
/// Assume that the protocol has already been changed to lowercase.
|
||||
while (pos < end && ((*pos > 'a' && *pos < 'z') || (*pos > '0' && *pos < '9')))
|
||||
++pos;
|
||||
|
||||
/** Будем вычислять иерархию только для URL-ов, в которых есть протокол, и после него идут два слеша.
|
||||
* (http, file - подходят, mailto, magnet - не подходят), и после двух слешей ещё хоть что-нибудь есть
|
||||
* Для остальных просто вернём пустой массив.
|
||||
/** We will calculate the hierarchy only for URLs in which there is a protocol, and after it there are two slashes.
|
||||
* (http, file - fit, mailto, magnet - do not fit), and after two slashes still at least something is there.
|
||||
* For the rest, just return an empty array.
|
||||
*/
|
||||
if (pos == begin || pos == end || !(*pos++ == ':' && pos < end && *pos++ == '/' && pos < end && *pos++ == '/' && pos < end))
|
||||
{
|
||||
@ -871,7 +870,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Доменом для простоты будем считать всё, что после протокола и двух слешей, до следующего слеша или до ? или до #
|
||||
/// The domain for simplicity is everything that after the protocol and the two slashes, until the next slash or `?` or `#`
|
||||
while (pos < end && !(*pos == '/' || *pos == '?' || *pos == '#'))
|
||||
++pos;
|
||||
|
||||
@ -881,7 +880,7 @@ public:
|
||||
++pos;
|
||||
}
|
||||
|
||||
/// Идём до следующего / или ? или #, пропуская все те, что вначале.
|
||||
/// We go to the next `/` or `?` or `#`, skipping all those at the beginning.
|
||||
while (pos < end && (*pos == '/' || *pos == '?' || *pos == '#'))
|
||||
++pos;
|
||||
if (pos == end)
|
||||
@ -900,7 +899,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/** Выделить кусок строки, используя Extractor.
|
||||
/** Select part of string using the Extractor.
|
||||
*/
|
||||
template <typename Extractor>
|
||||
struct ExtractSubstringImpl
|
||||
@ -915,7 +914,7 @@ struct ExtractSubstringImpl
|
||||
size_t prev_offset = 0;
|
||||
size_t res_offset = 0;
|
||||
|
||||
/// Выделенный кусок.
|
||||
/// Matched part.
|
||||
Pos start;
|
||||
size_t length;
|
||||
|
||||
@ -950,7 +949,7 @@ struct ExtractSubstringImpl
|
||||
};
|
||||
|
||||
|
||||
/** Удалить кусок строки, используя Extractor.
|
||||
/** Delete part of string using the Extractor.
|
||||
*/
|
||||
template <typename Extractor>
|
||||
struct CutSubstringImpl
|
||||
@ -965,7 +964,7 @@ struct CutSubstringImpl
|
||||
size_t prev_offset = 0;
|
||||
size_t res_offset = 0;
|
||||
|
||||
/// Выделенный кусок.
|
||||
/// Matched part.
|
||||
Pos start;
|
||||
size_t length;
|
||||
|
||||
|
@ -10,26 +10,29 @@
|
||||
#include <Columns/ColumnArray.h>
|
||||
#include <Columns/ColumnFixedString.h>
|
||||
#include <Columns/ColumnConst.h>
|
||||
#include <Common/hex.h>
|
||||
#include <Common/Volnitsky.h>
|
||||
#include <Functions/IFunction.h>
|
||||
#include <IO/ReadBufferFromMemory.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
|
||||
|
||||
/** Функции для извлечения параметров визитов.
|
||||
* Реализованы через шаблоны из FunctionsStringSearch.h.
|
||||
/** Functions for retrieving "visit parameters".
|
||||
* Visit parameters in Yandex.Metrika are a special kind of JSONs.
|
||||
* These functions are applicable to almost any JSONs.
|
||||
* Implemented via templates from FunctionsStringSearch.h.
|
||||
*
|
||||
* Проверить есть ли параметр
|
||||
* Check if there is a parameter
|
||||
* visitParamHas
|
||||
*
|
||||
* Извлечь числовое значение параметра
|
||||
* Retrieve the numeric value of the parameter
|
||||
* visitParamExtractUInt
|
||||
* visitParamExtractInt
|
||||
* visitParamExtractFloat
|
||||
* visitParamExtractBool
|
||||
*
|
||||
* Извлечь строкое значение параметра
|
||||
* visitParamExtractString - значение разэскейпливается
|
||||
* Retrieve the string value of the parameter
|
||||
* visitParamExtractString - unescape value
|
||||
* visitParamExtractRaw
|
||||
*/
|
||||
|
||||
@ -55,7 +58,7 @@ struct ExtractNumericType
|
||||
{
|
||||
ReadBufferFromMemory in(begin, end - begin);
|
||||
|
||||
/// Учимся читать числа в двойных кавычках
|
||||
/// Read numbers in double quotes
|
||||
if (!in.eof() && *in.position() == '"')
|
||||
++in.position();
|
||||
|
||||
@ -140,50 +143,12 @@ struct ExtractRaw
|
||||
|
||||
struct ExtractString
|
||||
{
|
||||
static bool tryParseDigit(UInt8 c, UInt8 & res)
|
||||
static UInt64 unhexCodePoint(const UInt8 * pos)
|
||||
{
|
||||
if ('0' <= c && c <= '9')
|
||||
{
|
||||
res = c - '0';
|
||||
return true;
|
||||
}
|
||||
if ('A' <= c && c <= 'Z')
|
||||
{
|
||||
res = c - ('A' - 10);
|
||||
return true;
|
||||
}
|
||||
if ('a' <= c && c <= 'z')
|
||||
{
|
||||
res = c - ('a' - 10);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool tryUnhex(const UInt8 * pos, const UInt8 * end, int & res)
|
||||
{
|
||||
if (pos + 3 >= end)
|
||||
return false;
|
||||
|
||||
res = 0;
|
||||
{
|
||||
UInt8 major, minor;
|
||||
if (!tryParseDigit(*(pos++), major))
|
||||
return false;
|
||||
if (!tryParseDigit(*(pos++), minor))
|
||||
return false;
|
||||
res |= (major << 4) | minor;
|
||||
}
|
||||
res <<= 8;
|
||||
{
|
||||
UInt8 major, minor;
|
||||
if (!tryParseDigit(*(pos++), major))
|
||||
return false;
|
||||
if (!tryParseDigit(*(pos++), minor))
|
||||
return false;
|
||||
res |= (major << 4) | minor;
|
||||
}
|
||||
return true;
|
||||
return unhex(pos[0]) * 0xFFF
|
||||
+ unhex(pos[1]) * 0xFF
|
||||
+ unhex(pos[2]) * 0xF
|
||||
+ unhex(pos[3]);
|
||||
}
|
||||
|
||||
static bool tryExtract(const UInt8 * pos, const UInt8 * end, ColumnString::Chars_t & res_data)
|
||||
@ -231,20 +196,25 @@ struct ExtractString
|
||||
{
|
||||
++pos;
|
||||
|
||||
int unicode;
|
||||
if (!tryUnhex(pos, end, unicode))
|
||||
if (pos + 4 > end)
|
||||
return false;
|
||||
|
||||
UInt16 code_point = unhexCodePoint(pos);
|
||||
pos += 3;
|
||||
|
||||
res_data.resize(res_data.size() + 6); /// максимальный размер UTF8 многобайтовой последовательности
|
||||
static constexpr size_t max_code_point_byte_length = 4;
|
||||
|
||||
size_t old_size = res_data.size();
|
||||
res_data.resize(old_size + max_code_point_byte_length);
|
||||
|
||||
Poco::UTF8Encoding utf8;
|
||||
int length = utf8.convert(unicode, const_cast<UInt8 *>(&res_data[0]) + res_data.size() - 6, 6);
|
||||
int length = utf8.convert(code_point,
|
||||
&res_data[old_size], max_code_point_byte_length);
|
||||
|
||||
if (!length)
|
||||
return false;
|
||||
|
||||
res_data.resize(res_data.size() - 6 + length);
|
||||
res_data.resize(old_size + length);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -274,47 +244,47 @@ struct ExtractString
|
||||
};
|
||||
|
||||
|
||||
/** Ищет вхождения поля в параметре визитов и вызывает ParamExtractor
|
||||
* на каждое вхождение поля, передавая ему указатель на часть строки,
|
||||
* где начинается вхождение значения поля.
|
||||
* ParamExtractor должен распарсить и вернуть значение нужного типа.
|
||||
/** Searches for occurrences of a field in the visit parameter and calls ParamExtractor
|
||||
* for each occurrence of the field, passing it a pointer to the part of the string,
|
||||
* where the occurrence of the field value begins.
|
||||
* ParamExtractor must parse and return the value of the desired type.
|
||||
*
|
||||
* Если поле не было найдено или полю соответствует некорректное значение,
|
||||
* то используется значение по умолчанию - 0.
|
||||
* If a field was not found or an incorrect value is associated with the field,
|
||||
* then the default value used - 0.
|
||||
*/
|
||||
template <typename ParamExtractor>
|
||||
struct ExtractParamImpl
|
||||
{
|
||||
using ResultType = typename ParamExtractor::ResultType;
|
||||
|
||||
/// Предполагается, что res нужного размера и инициализирован нулями.
|
||||
/// It is assumed that `res` is the correct size and initialized with zeros.
|
||||
static void vector_constant(const ColumnString::Chars_t & data, const ColumnString::Offsets_t & offsets,
|
||||
std::string needle,
|
||||
PaddedPODArray<ResultType> & res)
|
||||
{
|
||||
/// Ищем параметр просто как подстроку вида "name":
|
||||
/// We are looking for a parameter simply as a substring of the form "name"
|
||||
needle = "\"" + needle + "\":";
|
||||
|
||||
const UInt8 * begin = &data[0];
|
||||
const UInt8 * pos = begin;
|
||||
const UInt8 * end = pos + data.size();
|
||||
|
||||
/// Текущий индекс в массиве строк.
|
||||
/// The current index in the string array.
|
||||
size_t i = 0;
|
||||
|
||||
Volnitsky searcher(needle.data(), needle.size(), end - pos);
|
||||
|
||||
/// Искать будем следующее вхождение сразу во всех строках.
|
||||
/// We will search for the next occurrence in all strings at once.
|
||||
while (pos < end && end != (pos = searcher.search(pos, end - pos)))
|
||||
{
|
||||
/// Определим, к какому индексу оно относится.
|
||||
/// Let's determine which index it belongs to.
|
||||
while (begin + offsets[i] <= pos)
|
||||
{
|
||||
res[i] = 0;
|
||||
++i;
|
||||
}
|
||||
|
||||
/// Проверяем, что вхождение не переходит через границы строк.
|
||||
/// We check that the entry does not pass through the boundaries of strings.
|
||||
if (pos + needle.size() < begin + offsets[i])
|
||||
res[i] = ParamExtractor::extract(pos + needle.size(), begin + offsets[i]);
|
||||
else
|
||||
@ -358,7 +328,7 @@ struct ExtractParamImpl
|
||||
};
|
||||
|
||||
|
||||
/** Для случая когда тип поля, которое нужно извлечь - строка.
|
||||
/** For the case where the type of field to extract is a string.
|
||||
*/
|
||||
template<typename ParamExtractor>
|
||||
struct ExtractParamToStringImpl
|
||||
@ -367,26 +337,26 @@ struct ExtractParamToStringImpl
|
||||
std::string needle,
|
||||
ColumnString::Chars_t & res_data, ColumnString::Offsets_t & res_offsets)
|
||||
{
|
||||
/// Константа 5 взята из функции, выполняющей похожую задачу FunctionsStringSearch.h::ExtractImpl
|
||||
/// Constant 5 is taken from a function that performs a similar task FunctionsStringSearch.h::ExtractImpl
|
||||
res_data.reserve(data.size() / 5);
|
||||
res_offsets.resize(offsets.size());
|
||||
|
||||
/// Ищем параметр просто как подстроку вида "name":
|
||||
/// We are looking for a parameter simply as a substring of the form "name"
|
||||
needle = "\"" + needle + "\":";
|
||||
|
||||
const UInt8 * begin = &data[0];
|
||||
const UInt8 * pos = begin;
|
||||
const UInt8 * end = pos + data.size();
|
||||
|
||||
/// Текущий индекс в массиве строк.
|
||||
/// The current index in the string array.
|
||||
size_t i = 0;
|
||||
|
||||
Volnitsky searcher(needle.data(), needle.size(), end - pos);
|
||||
|
||||
/// Искать будем следующее вхождение сразу во всех строках.
|
||||
/// We will search for the next occurrence in all strings at once.
|
||||
while (pos < end && end != (pos = searcher.search(pos, end - pos)))
|
||||
{
|
||||
/// Определим, к какому индексу оно относится.
|
||||
/// Determine which index it belongs to.
|
||||
while (begin + offsets[i] <= pos)
|
||||
{
|
||||
res_data.push_back(0);
|
||||
@ -394,7 +364,7 @@ struct ExtractParamToStringImpl
|
||||
++i;
|
||||
}
|
||||
|
||||
/// Проверяем, что вхождение не переходит через границы строк.
|
||||
/// We check that the entry does not pass through the boundaries of strings.
|
||||
if (pos + needle.size() < begin + offsets[i])
|
||||
ParamExtractor::extract(pos + needle.size(), begin + offsets[i], res_data);
|
||||
|
||||
|
@ -24,29 +24,29 @@ namespace ErrorCodes
|
||||
struct ExpressionAction;
|
||||
|
||||
|
||||
/** Интерфейс для обычных функций.
|
||||
* Обычные функции - это функции, которые не меняют количество строк в таблице,
|
||||
* и результат работы которых для каждой строчки не зависит от других строк.
|
||||
/** Interface for normal functions.
|
||||
* Normal functions are functions that do not change the number of rows in the table,
|
||||
* and the result of which for each row does not depend on other rows.
|
||||
*
|
||||
* Функция может принимать произвольное количество аргументов; возвращает ровно одно значение.
|
||||
* Тип результата зависит от типов и количества аргументов.
|
||||
* A function can take an arbitrary number of arguments; returns exactly one value.
|
||||
* The type of the result depends on the type and number of arguments.
|
||||
*
|
||||
* Функция диспетчеризуется для целого блока. Это позволяет производить всевозможные проверки редко,
|
||||
* и делать основную работу в виде эффективного цикла.
|
||||
* The function is dispatched for the whole block. This allows you to perform all kinds of checks rarely,
|
||||
* and do the main job as an efficient loop.
|
||||
*
|
||||
* Функция применяется к одному или нескольким столбцам блока, и записывает свой результат,
|
||||
* добавляя новый столбец к блоку. Функция не модифицирует свои агрументы.
|
||||
* The function is applied to one or more columns of the block, and writes its result,
|
||||
* adding a new column to the block. The function does not modify its arguments.
|
||||
*/
|
||||
class IFunction
|
||||
{
|
||||
public:
|
||||
/** Наследник IFunction должен реализовать:
|
||||
/** The successor of IFunction must implement:
|
||||
* - getName
|
||||
* - либо getReturnType, либо getReturnTypeAndPrerequisites
|
||||
* - одну из перегрузок execute.
|
||||
* - either getReturnType, or getReturnTypeAndPrerequisites
|
||||
* - one of the overloads of `execute`.
|
||||
*/
|
||||
|
||||
/// Получить основное имя функции.
|
||||
/// Get the main function name.
|
||||
virtual String getName() const = 0;
|
||||
|
||||
/// Override and return true if function could take different number of arguments.
|
||||
@ -97,8 +97,8 @@ public:
|
||||
*/
|
||||
virtual bool isDeterministicInScopeOfQuery() { return true; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
/// Перегрузка для тех, кому не нужны prerequisites и значения константных аргументов. Снаружи не вызывается.
|
||||
/// Get the result type by argument type. If the function does not apply to these arguments, throw an exception.
|
||||
/// Overloading for those who do not need prerequisites and values of constant arguments. Not called from outside.
|
||||
DataTypePtr getReturnType(const DataTypes & arguments) const;
|
||||
|
||||
virtual DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const
|
||||
@ -106,11 +106,11 @@ public:
|
||||
throw Exception("getReturnType is not implemented for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/** Получить тип результата по типам аргументов и значениям константных аргументов.
|
||||
* Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
* Еще можно вернуть описание дополнительных столбцов, которые требуются для выполнения функции.
|
||||
* Для неконстантных столбцов arguments[i].column = nullptr.
|
||||
* Осмысленные типы элементов в out_prerequisites: APPLY_FUNCTION, ADD_COLUMN.
|
||||
/** Get the result type by argument types and constant argument values.
|
||||
* If the function does not apply to these arguments, throw an exception.
|
||||
* You can also return a description of the additional columns that are required to perform the function.
|
||||
* For non-constant columns `arguments[i].column = nullptr`.
|
||||
* Meaningful element types in out_prerequisites: APPLY_FUNCTION, ADD_COLUMN.
|
||||
*/
|
||||
void getReturnTypeAndPrerequisites(
|
||||
const ColumnsWithTypeAndName & arguments,
|
||||
@ -138,12 +138,12 @@ public:
|
||||
throw Exception("Function " + getName() + " can't have lambda-expressions as arguments", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком. Замечание: может вызываться одновременно из нескольких потоков, для одного объекта.
|
||||
/// Перегрузка для тех, кому не нужны prerequisites. Снаружи не вызывается.
|
||||
/// Execute the function on the block. Note: can be called simultaneously from several threads, for one object.
|
||||
/// Overloading for those who do not need `prerequisites`. Not called from outside.
|
||||
void execute(Block & block, const ColumnNumbers & arguments, size_t result);
|
||||
|
||||
/// Выполнить функцию над блоком. Замечание: может вызываться одновременно из нескольких потоков, для одного объекта.
|
||||
/// prerequisites идут в том же порядке, что и out_prerequisites, полученные из getReturnTypeAndPrerequisites.
|
||||
/// Execute the function above the block. Note: can be called simultaneously from several threads, for one object.
|
||||
/// `prerequisites` go in the same order as `out_prerequisites` obtained from getReturnTypeAndPrerequisites.
|
||||
void execute(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & prerequisites, size_t result);
|
||||
|
||||
virtual void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result)
|
||||
@ -160,25 +160,25 @@ public:
|
||||
/// that correspond to nullable columns and null columns.
|
||||
virtual bool hasSpecialSupportForNulls() const { return false; }
|
||||
|
||||
/** Позволяет узнать, является ли функция монотонной в некотором диапазоне значений.
|
||||
* Это используется для работы с индексом в сортированном куске данных.
|
||||
* И позволяет использовать индекс не только, когда написано, например date >= const, но и, например, toMonth(date) >= 11.
|
||||
* Всё это рассматривается только для функций одного аргумента.
|
||||
/** Lets you know if the function is monotonic in a range of values.
|
||||
* This is used to work with the index in a sorted chunk of data.
|
||||
* And allows to use the index not only when it is written, for example `date >= const`, but also, for example, `toMonth(date) >= 11`.
|
||||
* All this is considered only for functions of one argument.
|
||||
*/
|
||||
virtual bool hasInformationAboutMonotonicity() const { return false; }
|
||||
|
||||
/// Свойство монотонности на некотором диапазоне.
|
||||
/// The property of monotonicity for a certain range.
|
||||
struct Monotonicity
|
||||
{
|
||||
bool is_monotonic = false; /// Является ли функция монотонной (неубывающей или невозрастающей).
|
||||
bool is_positive = true; /// true, если функция неубывающая, false, если невозрастающая. Если is_monotonic = false, то не важно.
|
||||
bool is_monotonic = false; /// Is the function monotonous (nondecreasing or nonincreasing).
|
||||
bool is_positive = true; /// true if the function is nondecreasing, false, if notincreasing. If is_monotonic = false, then it does not matter.
|
||||
|
||||
Monotonicity(bool is_monotonic_ = false, bool is_positive_ = true)
|
||||
: is_monotonic(is_monotonic_), is_positive(is_positive_) {}
|
||||
};
|
||||
|
||||
/** Получить информацию о монотонности на отрезке значений. Вызывайте только если hasInformationAboutMonotonicity.
|
||||
* В качестве одного из аргументов может быть передан NULL. Это значит, что соответствующий диапазон неограничен слева или справа.
|
||||
/** Get information about monotonicity on a range of values. Call only if hasInformationAboutMonotonicity.
|
||||
* NULL can be passed as one of the arguments. This means that the corresponding range is unlimited on the left or on the right.
|
||||
*/
|
||||
virtual Monotonicity getMonotonicityForRange(const IDataType & type, const Field & left, const Field & right) const
|
||||
{
|
||||
|
@ -18,8 +18,8 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Позволяет получить тип результата применения функций +, -, *, /, %, div (целочисленное деление).
|
||||
* Правила отличаются от используемых в C++.
|
||||
/** Allows get the result type of the functions +, -, *, /, %, div (integer division).
|
||||
* The rules are different from those used in C++.
|
||||
*/
|
||||
|
||||
namespace NumberTraits
|
||||
@ -162,11 +162,11 @@ struct UpdateNullity
|
||||
>::Type;
|
||||
};
|
||||
|
||||
/** Результат сложения или умножения вычисляется по следующим правилам:
|
||||
* - если один из аргументов с плавающей запятой, то результат - с плавающей запятой, иначе - целый;
|
||||
* - если одно из аргументов со знаком, то результат - со знаком, иначе - без знака;
|
||||
* - результат содержит больше бит (не только значащих), чем максимум в аргументах
|
||||
* (например, UInt8 + Int32 = Int64).
|
||||
/** The result of addition or multiplication is calculated according to the following rules:
|
||||
* - if one of the arguments is floating-point, the result is a floating point, otherwise - the whole;
|
||||
* - if one of the arguments is signed, the result is signed, otherwise it is unsigned;
|
||||
* - the result contains more bits (not only meaningful) than the maximum in the arguments
|
||||
* (for example, UInt8 + Int32 = Int64).
|
||||
*/
|
||||
template <typename A, typename B> struct ResultOfAdditionMultiplication
|
||||
{
|
||||
@ -186,14 +186,14 @@ template <typename A, typename B> struct ResultOfSubtraction
|
||||
typename boost::mpl::or_<typename Traits<A>::Nullity, typename Traits<B>::Nullity>::type>::Type Type;
|
||||
};
|
||||
|
||||
/** При делении всегда получается число с плавающей запятой.
|
||||
/** When dividing, you always get a floating-point number.
|
||||
*/
|
||||
template <typename A, typename B> struct ResultOfFloatingPointDivision
|
||||
{
|
||||
using Type = Float64;
|
||||
};
|
||||
|
||||
/** При целочисленном делении получается число, битность которого равна делимому.
|
||||
/** For integer division, we get a number with the same number of bits as in divisible.
|
||||
*/
|
||||
template <typename A, typename B> struct ResultOfIntegerDivision
|
||||
{
|
||||
@ -204,7 +204,7 @@ template <typename A, typename B> struct ResultOfIntegerDivision
|
||||
typename boost::mpl::or_<typename Traits<A>::Nullity, typename Traits<B>::Nullity>::type>::Type Type;
|
||||
};
|
||||
|
||||
/** При взятии остатка получается число, битность которого равна делителю.
|
||||
/** Division with remainder you get a number with the same number of bits as in divisor.
|
||||
*/
|
||||
template <typename A, typename B> struct ResultOfModulo
|
||||
{
|
||||
@ -236,7 +236,7 @@ template <typename A> struct ResultOfAbs
|
||||
typename Traits<A>::Nullity>::Type Type;
|
||||
};
|
||||
|
||||
/** При побитовых операциях получается целое число, битность которого равна максимальной из битностей аргументов.
|
||||
/** For bitwise operations, an integer is obtained with number of bits is equal to the maximum of the arguments.
|
||||
*/
|
||||
template <typename A, typename B> struct ResultOfBit
|
||||
{
|
||||
@ -265,7 +265,7 @@ template <typename A> struct ResultOfBitNot
|
||||
};
|
||||
|
||||
|
||||
/** Приведение типов для функции if:
|
||||
/** Type casting for `if` function:
|
||||
* 1) void, Type -> Type
|
||||
* 2) UInt<x>, UInt<y> -> UInt<max(x,y)>
|
||||
* 3) Int<x>, Int<y> -> Int<max(x,y)>
|
||||
@ -294,7 +294,7 @@ struct ResultOfIf
|
||||
typename Construct<
|
||||
Signed,
|
||||
Floating,
|
||||
typename boost::mpl::max< /// Этот максимум нужен только потому что if_ всегда вычисляет все аргументы.
|
||||
typename boost::mpl::max< /// This maximum is needed only because `if_` always evaluates all arguments.
|
||||
typename boost::mpl::max<
|
||||
typename boost::mpl::if_<
|
||||
typename Traits<A>::Floatness,
|
||||
@ -334,7 +334,7 @@ struct ResultOfIf
|
||||
>::Type>::type>::type>::type>::type Type;
|
||||
};
|
||||
|
||||
/** Перед применением оператора % и побитовых операций, операнды приводятся к целым числам. */
|
||||
/** Before applying operator `%` and bitwise operations, operands are casted to whole numbers. */
|
||||
template <typename A> struct ToInteger
|
||||
{
|
||||
typedef typename Construct<
|
||||
|
@ -12,17 +12,17 @@ namespace DB
|
||||
{
|
||||
|
||||
|
||||
/** Записывает данные асинхронно с помощью двойной буферизации.
|
||||
/** Writes data asynchronously using double buffering.
|
||||
*/
|
||||
class AsynchronousWriteBuffer : public WriteBuffer
|
||||
{
|
||||
private:
|
||||
WriteBuffer & out; /// Основной буфер, отвечает за запись данных.
|
||||
std::vector<char> memory; /// Кусок памяти для дублирования буфера.
|
||||
ThreadPool pool; /// Для асинхронной записи данных.
|
||||
bool started; /// Была ли запущена асинхронная запись данных.
|
||||
WriteBuffer & out; /// The main buffer, responsible for writing data.
|
||||
std::vector <char> memory; /// A piece of memory for duplicating the buffer.
|
||||
ThreadPool pool; /// For asynchronous data writing.
|
||||
bool started; /// Has an asynchronous data write started?
|
||||
|
||||
/// Менять местами основной и дублирующий буферы.
|
||||
/// Swap the main and duplicate buffers.
|
||||
void swapBuffers()
|
||||
{
|
||||
buffer().swap(out.buffer());
|
||||
@ -41,14 +41,14 @@ private:
|
||||
|
||||
swapBuffers();
|
||||
|
||||
/// Данные будут записываться в отельном потоке.
|
||||
/// The data will be written in separate stream.
|
||||
pool.schedule([this] { thread(); });
|
||||
}
|
||||
|
||||
public:
|
||||
AsynchronousWriteBuffer(WriteBuffer & out_) : WriteBuffer(nullptr, 0), out(out_), memory(out.buffer().size()), pool(1), started(false)
|
||||
{
|
||||
/// Данные пишутся в дублирующий буфер.
|
||||
/// Data is written to the duplicate buffer.
|
||||
set(memory.data(), memory.size());
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// То, что выполняется в отдельном потоке
|
||||
/// That is executed in a separate thread
|
||||
void thread()
|
||||
{
|
||||
out.next();
|
||||
|
@ -8,30 +8,30 @@ namespace DB
|
||||
{
|
||||
|
||||
|
||||
/** Базовый класс для ReadBuffer и WriteBuffer.
|
||||
* Содержит общие типы, переменные и функции.
|
||||
/** Base class for ReadBuffer and WriteBuffer.
|
||||
* Contains mutual types, variables, and functions.
|
||||
*
|
||||
* ReadBuffer и WriteBuffer похожи на istream и ostream, соответственно.
|
||||
* Их приходится использовать, так как с использованием iostream-ов невозможно эффективно реализовать некоторые операции.
|
||||
* Например, используя istream, невозможно быстро читать строковые значения из tab-separated файла,
|
||||
* чтобы после чтения, позиция осталась сразу после считанного значения.
|
||||
* (Единственный вариант - вызывать функцию std::istream::get() на каждый байт, но это тормозит из-за нескольких виртуальных вызовов.)
|
||||
* ReadBuffer and WriteBuffer are similar to istream and ostream, respectively.
|
||||
* They have to be used, because using iostreams it is impossible to effectively implement some operations.
|
||||
* For example, using istream, you can not quickly read string values from a tab-separated file,
|
||||
* so that after reading, the position remains immediately after the read value.
|
||||
* (The only option is to call the std::istream::get() function on each byte, but this slows down due to several virtual calls.)
|
||||
*
|
||||
* Read/WriteBuffer-ы предоставляют прямой доступ к внутреннему буферу, поэтому, необходимые операции реализуются эффективнее.
|
||||
* Используется только одна виртуальная функция nextImpl(), которая вызывается редко:
|
||||
* - в случае ReadBuffer - заполнить буфер новыми данными из источика;
|
||||
* - в случае WriteBuffer - записать данные из буфера в приёмник.
|
||||
* Read/WriteBuffers provide direct access to the internal buffer, so the necessary operations are implemented more efficiently.
|
||||
* Only one virtual function nextImpl() is used, which is rarely called:
|
||||
* - in the case of ReadBuffer - fill in the buffer with new data from the source;
|
||||
* - in the case of WriteBuffer - write data from the buffer into the receiver.
|
||||
*
|
||||
* Read/WriteBuffer-ы могут владеть или не владеть своим куском памяти.
|
||||
* Во втором случае, можно эффективно читать из уже существующего куска памяти / std::string, не копируя его.
|
||||
* Read/WriteBuffer can own or not own an own piece of memory.
|
||||
* In the second case, you can effectively read from an already existing piece of memory / std::string without copying it.
|
||||
*/
|
||||
class BufferBase
|
||||
{
|
||||
public:
|
||||
/** Курсор в буфере. Позиция записи или чтения. */
|
||||
/** Cursor in the buffer. The position of write or read. */
|
||||
using Position = char *;
|
||||
|
||||
/** Ссылка на диапазон памяти. */
|
||||
/** A reference to the range of memory. */
|
||||
struct Buffer
|
||||
{
|
||||
Buffer(Position begin_pos_, Position end_pos_) : begin_pos(begin_pos_), end_pos(end_pos_) {}
|
||||
@ -49,11 +49,11 @@ public:
|
||||
|
||||
private:
|
||||
Position begin_pos;
|
||||
Position end_pos; /// на 1 байт после конца буфера
|
||||
Position end_pos; /// 1 byte after the end of the buffer
|
||||
};
|
||||
|
||||
/** Конструктор принимает диапазон памяти, который следует использовать под буфер.
|
||||
* offset - начальное место курсора. ReadBuffer должен установить его в конец диапазона, а WriteBuffer - в начало.
|
||||
/** The constructor takes a range of memory to use for the buffer.
|
||||
* offset - the starting point of the cursor. ReadBuffer must set it to the end of the range, and WriteBuffer - to the beginning.
|
||||
*/
|
||||
BufferBase(Position ptr, size_t size, size_t offset)
|
||||
: internal_buffer(ptr, ptr + size), working_buffer(ptr, ptr + size), pos(ptr + offset) {}
|
||||
@ -65,19 +65,19 @@ public:
|
||||
pos = ptr + offset;
|
||||
}
|
||||
|
||||
/// получить буфер
|
||||
/// get buffer
|
||||
inline Buffer & internalBuffer() { return internal_buffer; }
|
||||
|
||||
/// получить часть буфера, из которого можно читать / в который можно писать данные
|
||||
/// get the part of the buffer from which you can read / write data
|
||||
inline Buffer & buffer() { return working_buffer; }
|
||||
|
||||
/// получить (для чтения и изменения) позицию в буфере
|
||||
/// get (for reading and modifying) the position in the buffer
|
||||
inline Position & position() { return pos; };
|
||||
|
||||
/// смещение в байтах курсора от начала буфера
|
||||
/// offset in bytes of the cursor from the beginning of the buffer
|
||||
inline size_t offset() const { return pos - working_buffer.begin(); }
|
||||
|
||||
/** Сколько байт было прочитано/записано, считая те, что ещё в буфере. */
|
||||
/** How many bytes have been read/written, counting those that are still in the buffer. */
|
||||
size_t count() const
|
||||
{
|
||||
return bytes + offset();
|
||||
@ -90,21 +90,21 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Ссылка на кусок памяти для буфера.
|
||||
/// A reference to a piece of memory for the buffer.
|
||||
Buffer internal_buffer;
|
||||
|
||||
/** Часть куска памяти, которую можно использовать.
|
||||
* Например, если internal_buffer - 1MB, а из файла для чтения было загружено в буфер
|
||||
* только 10 байт, то working_buffer будет иметь размер 10 байт
|
||||
* (working_buffer.end() будет указывать на позицию сразу после тех 10 байт, которых можно прочитать).
|
||||
/** A piece of memory that you can use.
|
||||
* For example, if internal_buffer is 1MB, and from a file for reading it was loaded into the buffer
|
||||
* only 10 bytes, then working_buffer will be 10 bytes in size
|
||||
* (working_buffer.end() will point to the position immediately after the 10 bytes that can be read).
|
||||
*/
|
||||
Buffer working_buffer;
|
||||
|
||||
/// Позиция чтения/записи.
|
||||
/// Read/write position.
|
||||
Position pos;
|
||||
|
||||
/** Сколько байт было прочитано/записано, не считая тех, что сейчас в буфере.
|
||||
* (считая те, что были уже использованы и "удалены" из буфера)
|
||||
/** How many bytes have been read/written, not counting those that are now in the buffer.
|
||||
* (counting those that were already used and "removed" from the buffer)
|
||||
*/
|
||||
size_t bytes = 0;
|
||||
};
|
||||
|
@ -12,11 +12,11 @@ namespace DB
|
||||
{
|
||||
|
||||
|
||||
/** Буфер для чтения из сжатого файла с использованием кэша разжатых блоков.
|
||||
* Кэш внешний - передаётся в качестве аргумента в конструктор.
|
||||
* Позволяет увеличить производительность в случае, когда часто читаются одни и те же блоки.
|
||||
* Недостатки:
|
||||
* - в случае, если нужно читать много данных подряд, но из них только часть закэширована, приходится делать seek-и.
|
||||
/** A buffer for reading from a compressed file using the cache of decompressed blocks.
|
||||
* The external cache is passed as an argument to the constructor.
|
||||
* Allows you to increase performance in cases where the same blocks are often read.
|
||||
* Disadvantages:
|
||||
* - in case you need to read a lot of data in a row, but of them only a part is cached, you have to do seek-and.
|
||||
*/
|
||||
class CachedCompressedReadBuffer : public CompressedReadBufferBase, public ReadBuffer
|
||||
{
|
||||
@ -30,13 +30,13 @@ private:
|
||||
std::unique_ptr<ReadBufferFromFileBase> file_in;
|
||||
size_t file_pos;
|
||||
|
||||
/// Кусок данных из кэша, или кусок считанных данных, который мы положим в кэш.
|
||||
/// A piece of data from the cache, or a piece of read data that we put into the cache.
|
||||
UncompressedCache::MappedPtr owned_cell;
|
||||
|
||||
void initInput();
|
||||
bool nextImpl() override;
|
||||
|
||||
/// Передаётся в file_in.
|
||||
/// Passed into file_in.
|
||||
ReadBufferFromFileBase::ProfileCallback profile_callback;
|
||||
clockid_t clock_type;
|
||||
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
|
||||
size_t readBig(char * to, size_t n) override;
|
||||
|
||||
/// Сжатый размер текущего блока.
|
||||
/// The compressed size of the current block.
|
||||
size_t getSizeCompressed() const
|
||||
{
|
||||
return size_compressed;
|
||||
|
@ -11,16 +11,16 @@ namespace DB
|
||||
{
|
||||
|
||||
|
||||
/// В отличие от CompressedReadBuffer, умеет делать seek.
|
||||
/// Unlike CompressedReadBuffer, it can do seek.
|
||||
class CompressedReadBufferFromFile : public CompressedReadBufferBase, public BufferWithOwnMemory<ReadBuffer>
|
||||
{
|
||||
private:
|
||||
/** В любой момент выполняется одно из двух:
|
||||
/** At any time, one of two things is true:
|
||||
* a) size_compressed = 0
|
||||
* b)
|
||||
* - working_buffer содержит целиком один блок.
|
||||
* - file_in смотрит в конец этого блока.
|
||||
* - size_compressed содержит сжатый размер этого блока.
|
||||
* - `working_buffer` contains the entire block.
|
||||
* - `file_in` points to the end of this block.
|
||||
* - `size_compressed` contains the compressed size of this block.
|
||||
*/
|
||||
std::unique_ptr<ReadBufferFromFileBase> p_file_in;
|
||||
ReadBufferFromFileBase & file_in;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user