Merge pull request #830 from f1yegor/docs/translate-comments-functions

translate comments: functions
This commit is contained in:
alexey-milovidov 2017-05-27 20:06:00 +04:00 committed by GitHub
commit 3bb0a07e17
17 changed files with 366 additions and 365 deletions

View File

@ -35,28 +35,28 @@ 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 of constants.
* arrayElement(arr, i) - get the array element by index.
* 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 to this, where for each element specified
* how much times this element was encountered before 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...`
*/
@ -142,7 +142,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 +159,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; }
};
@ -1181,8 +1181,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 +1199,7 @@ public:
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
private:
/// Изначально выделить кусок памяти для 512 элементов.
/// Initially allocate a piece of memory for 512 elements.
static constexpr size_t INITIAL_SIZE_DEGREE = 9;
template <typename T>
@ -1239,7 +1239,7 @@ public:
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
private:
/// Изначально выделить кусок памяти для 512 элементов.
/// Initially allocate a piece of memory for 512 elements.
static constexpr size_t INITIAL_SIZE_DEGREE = 9;
template <typename T>

View File

@ -24,22 +24,23 @@
namespace DB
{
/** Функции кодирования:
/** Coding 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, reserves the right to return any garbage.
*
* 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].
*/
/// Включая нулевой символ в конце.
/// Including zero character at the end.
#define MAX_UINT_HEX_LENGTH 20
const auto ipv4_bytes_length = 4;
@ -664,16 +665,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 +689,7 @@ public:
}
}
/// И развернем.
/// And reverse.
std::reverse(begin, out);
*(out++) = '\0';
@ -708,7 +709,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 +848,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 +872,7 @@ public:
}
}
/// И развернем.
/// And reverse.
std::reverse(begin, out);
*(out++) = '\0';
@ -891,7 +892,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;
@ -1015,16 +1016,16 @@ public:
/// 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';
@ -1043,7 +1044,7 @@ public:
}
}
/// И развернем.
/// And reverse.
std::reverse(begin, out);
*(out++) = '\0';
@ -1063,7 +1064,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;
@ -1601,7 +1602,7 @@ public:
{
UInt8 byte = static_cast<UInt8>((x >> offset) & 255);
/// Ведущие нули.
/// Leading zeros.
if (byte == 0 && !was_nonzero && offset)
continue;
@ -1635,7 +1636,7 @@ public:
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);
@ -1724,7 +1725,7 @@ public:
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);

View File

@ -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;
@ -1014,7 +1014,7 @@ public:
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_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)

View File

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

View File

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

View File

@ -31,21 +31,21 @@
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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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.
*/

View File

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

View File

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

View File

@ -16,20 +16,20 @@
#include <IO/ReadHelpers.h>
/** Функции для извлечения параметров визитов.
* Реализованы через шаблоны из FunctionsStringSearch.h.
/** Functions for retrieving visit parameters.
* 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 +55,7 @@ struct ExtractNumericType
{
ReadBufferFromMemory in(begin, end - begin);
/// Учимся читать числа в двойных кавычках
/// Read numbers in double quotes
if (!in.eof() && *in.position() == '"')
++in.position();
@ -236,7 +236,7 @@ struct ExtractString
return false;
pos += 3;
res_data.resize(res_data.size() + 6); /// максимальный размер UTF8 многобайтовой последовательности
res_data.resize(res_data.size() + 6); /// the maximum size of the UTF8 multibyte sequence
Poco::UTF8Encoding utf8;
int length = utf8.convert(unicode, const_cast<UInt8 *>(&res_data[0]) + res_data.size() - 6, 6);
@ -274,47 +274,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 +358,7 @@ struct ExtractParamImpl
};
/** Для случая когда тип поля, которое нужно извлечь - строка.
/** For the case where the type of field to extract is a string.
*/
template<typename ParamExtractor>
struct ExtractParamToStringImpl
@ -367,26 +367,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 +394,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);