mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 09:32:06 +00:00
Squashed commit of the following:
commitc567d4e1fe
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 20:35:01 2017 +0300 Style [#METR-2944]. commit26bf3e1228
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 20:33:11 2017 +0300 Miscellaneous [#METR-2944]. commiteb946f4c6f
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 20:30:19 2017 +0300 Miscellaneous [#METR-2944]. commit78c867a147
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 20:11:41 2017 +0300 Miscellaneous [#METR-2944]. commit6604c5c83c
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:56:15 2017 +0300 Miscellaneous [#METR-2944]. commit23fbf05c1d
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:47:52 2017 +0300 Miscellaneous [#METR-2944]. commit98772faf11
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:46:05 2017 +0300 Miscellaneous [#METR-2944]. commit3dc636ab9f
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:39:46 2017 +0300 Miscellaneous [#METR-2944]. commit3e16aee954
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:38:03 2017 +0300 Miscellaneous [#METR-2944]. commitae7e7e90eb
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:34:15 2017 +0300 Miscellaneous [#METR-2944].
This commit is contained in:
parent
2f7ff07e1f
commit
d89ee33ce2
@ -64,7 +64,7 @@ public:
|
||||
if (params.size() != 1)
|
||||
throw Exception("Aggregate function " + getName() + " requires exactly one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
level = apply_visitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
level = applyVisitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
}
|
||||
|
||||
|
||||
@ -141,7 +141,7 @@ public:
|
||||
levels.resize(size);
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
levels[i] = apply_visitor(FieldVisitorConvertToNumber<Float64>(), params[i]);
|
||||
levels[i] = applyVisitor(FieldVisitorConvertToNumber<Float64>(), params[i]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
if (params.size() != 1)
|
||||
throw Exception("Aggregate function " + getName() + " requires exactly one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
level = apply_visitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
level = applyVisitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
}
|
||||
|
||||
|
||||
@ -154,7 +154,7 @@ public:
|
||||
levels.resize(size);
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
levels[i] = apply_visitor(FieldVisitorConvertToNumber<Float64>(), params[i]);
|
||||
levels[i] = applyVisitor(FieldVisitorConvertToNumber<Float64>(), params[i]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
if (params.size() != 1)
|
||||
throw Exception("Aggregate function " + getName() + " requires exactly one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
level = apply_visitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
level = applyVisitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
}
|
||||
|
||||
void addImpl(AggregateDataPtr place, const IColumn & column, size_t row_num, Arena *) const
|
||||
|
@ -71,7 +71,7 @@ public:
|
||||
if (params.size() != 1)
|
||||
throw Exception("Aggregate function " + getName() + " requires exactly one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
level = apply_visitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
level = applyVisitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
}
|
||||
|
||||
void addImpl(AggregateDataPtr place, const IColumn & column_value, const IColumn & column_weight, size_t row_num, Arena *) const
|
||||
|
@ -379,7 +379,7 @@ public:
|
||||
if (params.size() != 1)
|
||||
throw Exception("Aggregate function " + getName() + " requires exactly one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
level = apply_visitor(FieldVisitorConvertToNumber<Float32>(), params[0]);
|
||||
level = applyVisitor(FieldVisitorConvertToNumber<Float32>(), params[0]);
|
||||
}
|
||||
|
||||
void addImpl(AggregateDataPtr place, const IColumn & column, size_t row_num, Arena *) const
|
||||
@ -446,7 +446,7 @@ public:
|
||||
if (params.size() != 1)
|
||||
throw Exception("Aggregate function " + getName() + " requires exactly one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
level = apply_visitor(FieldVisitorConvertToNumber<Float32>(), params[0]);
|
||||
level = applyVisitor(FieldVisitorConvertToNumber<Float32>(), params[0]);
|
||||
}
|
||||
|
||||
void addImpl(AggregateDataPtr place, const IColumn & column_value, const IColumn & column_weight, size_t row_num, Arena *) const
|
||||
|
@ -811,7 +811,7 @@ public:
|
||||
if (params.size() != 1)
|
||||
throw Exception("Aggregate function " + getName() + " requires exactly one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
level = apply_visitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
level = applyVisitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
}
|
||||
|
||||
|
||||
@ -870,7 +870,7 @@ public:
|
||||
if (params.size() != 1)
|
||||
throw Exception("Aggregate function " + getName() + " requires exactly one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
level = apply_visitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
level = applyVisitor(FieldVisitorConvertToNumber<Float64>(), params[0]);
|
||||
}
|
||||
|
||||
void addImpl(AggregateDataPtr place, const IColumn & column_value, const IColumn & column_weight, size_t row_num, Arena *) const
|
||||
|
@ -142,7 +142,7 @@ public:
|
||||
if (params.size() != 1)
|
||||
throw Exception("Aggregate function " + getName() + " requires exactly one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
UInt64 threshold_param = apply_visitor(FieldVisitorConvertToNumber<UInt64>(), params[0]);
|
||||
UInt64 threshold_param = applyVisitor(FieldVisitorConvertToNumber<UInt64>(), params[0]);
|
||||
|
||||
if (threshold_param > uniq_upto_max_threshold)
|
||||
throw Exception("Too large parameter for aggregate function " + getName() + ". Maximum: " + toString(uniq_upto_max_threshold),
|
||||
@ -215,7 +215,7 @@ public:
|
||||
if (params.size() != 1)
|
||||
throw Exception("Aggregate function " + getName() + " requires exactly one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
UInt64 threshold_param = apply_visitor(FieldVisitorConvertToNumber<UInt64>(), params[0]);
|
||||
UInt64 threshold_param = applyVisitor(FieldVisitorConvertToNumber<UInt64>(), params[0]);
|
||||
|
||||
if (threshold_param > uniq_upto_max_threshold)
|
||||
throw Exception("Too large parameter for aggregate function " + getName() + ". Maximum: " + toString(uniq_upto_max_threshold),
|
||||
|
@ -40,7 +40,7 @@ struct QuantileLevels
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
levels[i] = apply_visitor(FieldVisitorConvertToNumber<Float64>(), params[i]);
|
||||
levels[i] = applyVisitor(FieldVisitorConvertToNumber<Float64>(), params[i]);
|
||||
permutation[i] = i;
|
||||
}
|
||||
|
||||
|
@ -21,13 +21,12 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
class Field;
|
||||
using Array = std::vector<Field>; /// Значение типа "массив"
|
||||
using Array = std::vector<Field>;
|
||||
using TupleBackend = std::vector<Field>;
|
||||
STRONG_TYPEDEF(TupleBackend, Tuple); /// Значение типа "кортеж"
|
||||
STRONG_TYPEDEF(TupleBackend, Tuple); /// Array and Tuple are different types with equal representation inside Field.
|
||||
|
||||
|
||||
/** 32 хватает с запасом (достаточно 28), но выбрано круглое число,
|
||||
* чтобы арифметика при использовании массивов из Field была проще (не содержала умножения).
|
||||
/** 32 is enough. Round number is used for alignment and for better arithmetic inside std::vector.
|
||||
*/
|
||||
#define DBMS_MIN_FIELD_SIZE 32
|
||||
|
||||
|
@ -2,12 +2,8 @@
|
||||
|
||||
#include <DB/Core/Field.h>
|
||||
|
||||
#include <DB/IO/ReadBuffer.h>
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/IO/ReadBufferFromString.h>
|
||||
#include <DB/IO/WriteBufferFromString.h>
|
||||
|
||||
class SipHash;
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -19,9 +15,9 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
|
||||
/** StaticVisitor (его наследники) - класс с перегруженными для разных типов операторами ().
|
||||
* Вызвать visitor для field можно с помощью функции apply_visitor.
|
||||
* Также поддерживается visitor, в котором оператор () принимает два аргумента.
|
||||
/** StaticVisitor (and its descendants) - class with overloaded operator() for all types of fields.
|
||||
* You could call visitor for field using function 'applyVisitor'.
|
||||
* Also "binary visitor" is supported - its operator() takes two arguments.
|
||||
*/
|
||||
template <typename R = void>
|
||||
struct StaticVisitor
|
||||
@ -30,65 +26,38 @@ struct StaticVisitor
|
||||
};
|
||||
|
||||
|
||||
/// F is template parameter, to allow universal reference for field, that is useful for const and non-const values.
|
||||
template <typename Visitor, typename F>
|
||||
typename Visitor::ResultType apply_visitor_impl(Visitor & visitor, F & field)
|
||||
typename std::decay<Visitor>::type::ResultType applyVisitor(Visitor && visitor, F && field)
|
||||
{
|
||||
switch (field.getType())
|
||||
{
|
||||
case Field::Types::Null: return visitor(field.template get<Null>());
|
||||
case Field::Types::UInt64: return visitor(field.template get<UInt64>());
|
||||
case Field::Types::Int64: return visitor(field.template get<Int64>());
|
||||
case Field::Types::Float64: return visitor(field.template get<Float64>());
|
||||
case Field::Types::String: return visitor(field.template get<String>());
|
||||
case Field::Types::Array: return visitor(field.template get<Array>());
|
||||
case Field::Types::Tuple: return visitor(field.template get<Tuple>());
|
||||
case Field::Types::Null: return visitor(field.template get<Null>());
|
||||
case Field::Types::UInt64: return visitor(field.template get<UInt64>());
|
||||
case Field::Types::Int64: return visitor(field.template get<Int64>());
|
||||
case Field::Types::Float64: return visitor(field.template get<Float64>());
|
||||
case Field::Types::String: return visitor(field.template get<String>());
|
||||
case Field::Types::Array: return visitor(field.template get<Array>());
|
||||
case Field::Types::Tuple: return visitor(field.template get<Tuple>());
|
||||
|
||||
default:
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
}
|
||||
}
|
||||
|
||||
/** Эти штуки нужны, чтобы принимать временный объект по константной ссылке.
|
||||
* В шаблон выше, типы форвардятся уже с const-ом.
|
||||
*/
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, const Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, const Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
|
||||
template <typename Visitor, typename F1, typename F2>
|
||||
typename Visitor::ResultType apply_binary_visitor_impl2(Visitor & visitor, F1 & field1, F2 & field2)
|
||||
static typename std::decay<Visitor>::type::ResultType applyBinaryVisitorImpl(Visitor && visitor, F1 && field1, F2 && field2)
|
||||
{
|
||||
switch (field2.getType())
|
||||
{
|
||||
case Field::Types::Null: return visitor(field1, field2.template get<Null>());
|
||||
case Field::Types::UInt64: return visitor(field1, field2.template get<UInt64>());
|
||||
case Field::Types::Int64: return visitor(field1, field2.template get<Int64>());
|
||||
case Field::Types::Float64: return visitor(field1, field2.template get<Float64>());
|
||||
case Field::Types::String: return visitor(field1, field2.template get<String>());
|
||||
case Field::Types::Array: return visitor(field1, field2.template get<Array>());
|
||||
case Field::Types::Tuple: return visitor(field1, field2.template get<Tuple>());
|
||||
case Field::Types::Null: return visitor(field1, field2.template get<Null>());
|
||||
case Field::Types::UInt64: return visitor(field1, field2.template get<UInt64>());
|
||||
case Field::Types::Int64: return visitor(field1, field2.template get<Int64>());
|
||||
case Field::Types::Float64: return visitor(field1, field2.template get<Float64>());
|
||||
case Field::Types::String: return visitor(field1, field2.template get<String>());
|
||||
case Field::Types::Array: return visitor(field1, field2.template get<Array>());
|
||||
case Field::Types::Tuple: return visitor(field1, field2.template get<Tuple>());
|
||||
|
||||
default:
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
@ -96,130 +65,67 @@ typename Visitor::ResultType apply_binary_visitor_impl2(Visitor & visitor, F1 &
|
||||
}
|
||||
|
||||
template <typename Visitor, typename F1, typename F2>
|
||||
typename Visitor::ResultType apply_binary_visitor_impl1(Visitor & visitor, F1 & field1, F2 & field2)
|
||||
typename std::decay<Visitor>::type::ResultType applyVisitor(Visitor && visitor, F1 && field1, F2 && field2)
|
||||
{
|
||||
switch (field1.getType())
|
||||
{
|
||||
case Field::Types::Null: return apply_binary_visitor_impl2(visitor, field1.template get<Null>(), field2);
|
||||
case Field::Types::UInt64: return apply_binary_visitor_impl2(visitor, field1.template get<UInt64>(), field2);
|
||||
case Field::Types::Int64: return apply_binary_visitor_impl2(visitor, field1.template get<Int64>(), field2);
|
||||
case Field::Types::Float64: return apply_binary_visitor_impl2(visitor, field1.template get<Float64>(), field2);
|
||||
case Field::Types::String: return apply_binary_visitor_impl2(visitor, field1.template get<String>(), field2);
|
||||
case Field::Types::Array: return apply_binary_visitor_impl2(visitor, field1.template get<Array>(), field2);
|
||||
case Field::Types::Tuple: return apply_binary_visitor_impl2(visitor, field1.template get<Tuple>(), field2);
|
||||
case Field::Types::Null:
|
||||
return applyBinaryVisitorImpl(
|
||||
std::forward<Visitor>(visitor), field1.template get<Null>(), std::forward<F2>(field2));
|
||||
case Field::Types::UInt64:
|
||||
return applyBinaryVisitorImpl(
|
||||
std::forward<Visitor>(visitor), field1.template get<UInt64>(), std::forward<F2>(field2));
|
||||
case Field::Types::Int64:
|
||||
return applyBinaryVisitorImpl(
|
||||
std::forward<Visitor>(visitor), field1.template get<Int64>(), std::forward<F2>(field2));
|
||||
case Field::Types::Float64:
|
||||
return applyBinaryVisitorImpl(
|
||||
std::forward<Visitor>(visitor), field1.template get<Float64>(), std::forward<F2>(field2));
|
||||
case Field::Types::String:
|
||||
return applyBinaryVisitorImpl(
|
||||
std::forward<Visitor>(visitor), field1.template get<String>(), std::forward<F2>(field2));
|
||||
case Field::Types::Array:
|
||||
return applyBinaryVisitorImpl(
|
||||
std::forward<Visitor>(visitor), field1.template get<Array>(), std::forward<F2>(field2));
|
||||
case Field::Types::Tuple:
|
||||
return applyBinaryVisitorImpl(
|
||||
std::forward<Visitor>(visitor), field1.template get<Tuple>(), std::forward<F2>(field2));
|
||||
|
||||
default:
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, Field & field1, const Field & field2)
|
||||
/** Prints Field as literal in SQL query */
|
||||
class FieldVisitorToString : public StaticVisitor<String>
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, const Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, const Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, const Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, const Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
|
||||
/** Возвращает строковый дамп типа */
|
||||
class FieldVisitorDump : public StaticVisitor<String>
|
||||
{
|
||||
private:
|
||||
template <typename T>
|
||||
static inline String formatQuotedWithPrefix(T x, const char * prefix)
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
wb.write(prefix, strlen(prefix));
|
||||
writeQuoted(x, wb);
|
||||
return res;
|
||||
}
|
||||
public:
|
||||
String operator() (const Null & x) const { return "NULL"; }
|
||||
String operator() (const UInt64 & x) const { return formatQuotedWithPrefix(x, "UInt64_"); }
|
||||
String operator() (const Int64 & x) const { return formatQuotedWithPrefix(x, "Int64_"); }
|
||||
String operator() (const Float64 & x) const { return formatQuotedWithPrefix(x, "Float64_"); }
|
||||
String operator() (const Null & x) const;
|
||||
String operator() (const UInt64 & x) const;
|
||||
String operator() (const Int64 & x) const;
|
||||
String operator() (const Float64 & x) const;
|
||||
String operator() (const String & x) const;
|
||||
String operator() (const Array & x) const;
|
||||
String operator() (const Tuple & x) const;
|
||||
};
|
||||
|
||||
|
||||
/** Выводит текстовое представление типа, как литерала в SQL запросе */
|
||||
class FieldVisitorToString : public StaticVisitor<String>
|
||||
/** Print readable and unique text dump of field type and value. */
|
||||
class FieldVisitorDump : public StaticVisitor<String>
|
||||
{
|
||||
private:
|
||||
template <typename T>
|
||||
static inline String formatQuoted(T x)
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
writeQuoted(x, wb);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** В отличие от writeFloatText (и writeQuoted), если число после форматирования выглядит целым, всё равно добавляет десятичную точку.
|
||||
* - для того, чтобы это число могло обратно распарситься как Float64 парсером запроса (иначе распарсится как целое).
|
||||
*
|
||||
* При этом, не оставляет завершающие нули справа.
|
||||
*
|
||||
* NOTE: При таком roundtrip-е, точность может теряться.
|
||||
*/
|
||||
static String formatFloat(const Float64 x);
|
||||
|
||||
public:
|
||||
String operator() (const Null & x) const { return "NULL"; }
|
||||
String operator() (const UInt64 & x) const { return formatQuoted(x); }
|
||||
String operator() (const Int64 & x) const { return formatQuoted(x); }
|
||||
String operator() (const Float64 & x) const { return formatFloat(x); }
|
||||
String operator() (const String & x) const { return formatQuoted(x); }
|
||||
String operator() (const Null & x) const;
|
||||
String operator() (const UInt64 & x) const;
|
||||
String operator() (const Int64 & x) const;
|
||||
String operator() (const Float64 & x) const;
|
||||
String operator() (const String & x) const;
|
||||
String operator() (const Array & x) const;
|
||||
String operator() (const Tuple & x) const;
|
||||
};
|
||||
|
||||
|
||||
/** Числовой тип преобразует в указанный. */
|
||||
/** Converts numberic value of any type to specified type. */
|
||||
template <typename T>
|
||||
class FieldVisitorConvertToNumber : public StaticVisitor<T>
|
||||
{
|
||||
@ -250,6 +156,23 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/** Updates SipHash by type and value of Field */
|
||||
class FieldVisitorHash : public StaticVisitor<>
|
||||
{
|
||||
private:
|
||||
SipHash & hash;
|
||||
public:
|
||||
FieldVisitorHash(SipHash & hash);
|
||||
|
||||
void operator() (const Null & x) const;
|
||||
void operator() (const UInt64 & x) const;
|
||||
void operator() (const Int64 & x) const;
|
||||
void operator() (const Float64 & x) const;
|
||||
void operator() (const String & x) const;
|
||||
void operator() (const Array & x) const;
|
||||
};
|
||||
|
||||
|
||||
/// Converts string with date or datetime (in format 'YYYY-MM-DD hh:mm:ss') to UInt64 containing numeric value of date (or datetime)
|
||||
UInt64 stringToDateOrDateTime(const String & s);
|
||||
|
||||
|
@ -886,8 +886,8 @@ template <> struct FunctionUnaryArithmeticMonotonicity<NameAbs>
|
||||
static bool has() { return true; }
|
||||
static IFunction::Monotonicity get(const Field & left, const Field & right)
|
||||
{
|
||||
Float64 left_float = left.isNull() ? -std::numeric_limits<Float64>::infinity() : apply_visitor(FieldVisitorConvertToNumber<Float64>(), left);
|
||||
Float64 right_float = right.isNull() ? std::numeric_limits<Float64>::infinity() : apply_visitor(FieldVisitorConvertToNumber<Float64>(), right);
|
||||
Float64 left_float = left.isNull() ? -std::numeric_limits<Float64>::infinity() : applyVisitor(FieldVisitorConvertToNumber<Float64>(), left);
|
||||
Float64 right_float = right.isNull() ? std::numeric_limits<Float64>::infinity() : applyVisitor(FieldVisitorConvertToNumber<Float64>(), right);
|
||||
|
||||
if ((left_float < 0 && right_float > 0) || (left_float > 0 && right_float < 0))
|
||||
return {};
|
||||
|
@ -897,7 +897,7 @@ private:
|
||||
|
||||
for (size_t i = 0, size = arr.size(); i < size; ++i)
|
||||
{
|
||||
if (apply_visitor(FieldVisitorAccurateEquals(), arr[i], value))
|
||||
if (applyVisitor(FieldVisitorAccurateEquals(), arr[i], value))
|
||||
{
|
||||
if (!IndexConv::apply(i, current))
|
||||
break;
|
||||
@ -940,7 +940,7 @@ private:
|
||||
if (null_map && ((*null_map)[row] == 1))
|
||||
hit = true;
|
||||
}
|
||||
else if (apply_visitor(FieldVisitorAccurateEquals(), arr[i], value))
|
||||
else if (applyVisitor(FieldVisitorAccurateEquals(), arr[i], value))
|
||||
hit = true;
|
||||
|
||||
if (hit)
|
||||
|
@ -12,10 +12,13 @@
|
||||
#include <DB/DataTypes/DataTypeString.h>
|
||||
#include <DB/DataTypes/DataTypeFixedString.h>
|
||||
#include <DB/DataTypes/DataTypeTuple.h>
|
||||
#include <DB/DataTypes/DataTypeEnum.h>
|
||||
|
||||
#include <DB/Functions/FunctionsLogical.h>
|
||||
#include <DB/Functions/IFunction.h>
|
||||
#include <DB/DataTypes/DataTypeEnum.h>
|
||||
|
||||
#include <DB/IO/ReadBufferFromString.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -959,7 +959,7 @@ private:
|
||||
if (!column.isConst())
|
||||
throw Exception(which_argument + String(" argument for function ") + getName() + " must be constant.", ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
return apply_visitor(FieldVisitorConvertToNumber<T>(), column[0]);
|
||||
return applyVisitor(FieldVisitorConvertToNumber<T>(), column[0]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -781,13 +781,13 @@ private:
|
||||
{
|
||||
converted_to.resize(to.size());
|
||||
for (size_t i = 0, size = to.size(); i < size; ++i)
|
||||
converted_to[i] = apply_visitor(FieldVisitorConvertToNumber<Float64>(), to[i]);
|
||||
converted_to[i] = applyVisitor(FieldVisitorConvertToNumber<Float64>(), to[i]);
|
||||
used_to = &converted_to;
|
||||
}
|
||||
else if (!default_col_is_float && to_is_float)
|
||||
{
|
||||
if (const_default_col)
|
||||
const_default_value = apply_visitor(FieldVisitorConvertToNumber<Float64>(), const_default_value);
|
||||
const_default_value = applyVisitor(FieldVisitorConvertToNumber<Float64>(), const_default_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ protected:
|
||||
frame.need_parens = false;
|
||||
|
||||
const std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
|
||||
settings.ostr << settings.nl_or_ws << indent_str << '\'' << name << "' = " << apply_visitor(FieldVisitorToString{}, value);
|
||||
settings.ostr << settings.nl_or_ws << indent_str << '\'' << name << "' = " << applyVisitor(FieldVisitorToString{}, value);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -21,14 +21,14 @@ public:
|
||||
String getColumnName() const override;
|
||||
|
||||
/** Получить текст, который идентифицирует этот элемент. */
|
||||
String getID() const override { return "Literal_" + apply_visitor(FieldVisitorDump(), value); }
|
||||
String getID() const override { return "Literal_" + applyVisitor(FieldVisitorDump(), value); }
|
||||
|
||||
ASTPtr clone() const override { return std::make_shared<ASTLiteral>(*this); }
|
||||
|
||||
protected:
|
||||
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
|
||||
{
|
||||
settings.ostr << apply_visitor(FieldVisitorToString(), value);
|
||||
settings.ostr << applyVisitor(FieldVisitorToString(), value);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -43,7 +43,7 @@ protected:
|
||||
if (it != changes.begin())
|
||||
settings.ostr << ", ";
|
||||
|
||||
settings.ostr << it->name << " = " << apply_visitor(FieldVisitorToString(), it->value);
|
||||
settings.ostr << it->name << " = " << applyVisitor(FieldVisitorToString(), it->value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -190,12 +190,12 @@ public:
|
||||
if (!left_bounded)
|
||||
str << "(-inf, ";
|
||||
else
|
||||
str << (left_included ? '[' : '(') << apply_visitor(FieldVisitorToString(), left) << ", ";
|
||||
str << (left_included ? '[' : '(') << applyVisitor(FieldVisitorToString(), left) << ", ";
|
||||
|
||||
if (!right_bounded)
|
||||
str << "+inf)";
|
||||
else
|
||||
str << apply_visitor(FieldVisitorToString(), right) << (right_included ? ']' : ')');
|
||||
str << applyVisitor(FieldVisitorToString(), right) << (right_included ? ']' : ')');
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <DB/Parsers/ASTLiteral.h>
|
||||
#include <DB/Parsers/ASTOrderByElement.h>
|
||||
#include <DB/Common/typeid_cast.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -56,7 +56,7 @@ static void processLiteral(const String & column_name, const ASTPtr & ast, TypeA
|
||||
expression_info.node = ast;
|
||||
expression_info.is_constant_expression = true;
|
||||
expression_info.value = literal->value;
|
||||
expression_info.data_type = apply_visitor(FieldToDataType(), expression_info.value);
|
||||
expression_info.data_type = applyVisitor(FieldToDataType(), expression_info.value);
|
||||
info.emplace(column_name, std::move(expression_info));
|
||||
}
|
||||
|
||||
@ -368,7 +368,7 @@ void TypeAndConstantInference::dump(WriteBuffer & out) const
|
||||
if (it->second.is_constant_expression)
|
||||
{
|
||||
writeCString(" = ", out);
|
||||
String value = apply_visitor(FieldVisitorToString(), it->second.value);
|
||||
String value = applyVisitor(FieldVisitorToString(), it->second.value);
|
||||
writeString(value, out);
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,12 @@
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
|
||||
/// This is for Yandex.Metrica code.
|
||||
namespace mysqlxx
|
||||
{
|
||||
std::ostream & operator<< (mysqlxx::EscapeManipResult res, const DB::Array & value)
|
||||
{
|
||||
return res.ostr << apply_visitor(DB::FieldVisitorToString(), value);
|
||||
return res.ostr << DB::applyVisitor(DB::FieldVisitorToString(), DB::Field(value));
|
||||
}
|
||||
|
||||
std::ostream & operator<< (mysqlxx::QuoteManipResult res, const DB::Array & value)
|
||||
@ -30,14 +31,11 @@ namespace mysqlxx
|
||||
{
|
||||
throw Poco::Exception("Cannot unquote Array with mysqlxx::unquote.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace mysqlxx
|
||||
{
|
||||
std::ostream & operator<< (mysqlxx::EscapeManipResult res, const DB::Tuple & value)
|
||||
{
|
||||
return res.ostr << apply_visitor(DB::FieldVisitorToString(), value);
|
||||
return res.ostr << DB::applyVisitor(DB::FieldVisitorToString(), DB::Field(value));
|
||||
}
|
||||
|
||||
std::ostream & operator<< (mysqlxx::QuoteManipResult res, const DB::Tuple & value)
|
||||
@ -171,7 +169,7 @@ namespace DB
|
||||
|
||||
void writeText(const Array & x, WriteBuffer & buf)
|
||||
{
|
||||
DB::String res = apply_visitor(DB::FieldVisitorToString(), DB::Field(x));
|
||||
DB::String res = applyVisitor(DB::FieldVisitorToString(), DB::Field(x));
|
||||
buf.write(res.data(), res.size());
|
||||
}
|
||||
}
|
||||
@ -293,7 +291,7 @@ namespace DB
|
||||
|
||||
void writeText(const Tuple & x, WriteBuffer & buf)
|
||||
{
|
||||
DB::String res = apply_visitor(DB::FieldVisitorToString(), DB::Field(x));
|
||||
DB::String res = applyVisitor(DB::FieldVisitorToString(), DB::Field(x));
|
||||
buf.write(res.data(), res.size());
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,19 @@
|
||||
#include <DB/IO/ReadBuffer.h>
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/IO/ReadBufferFromString.h>
|
||||
#include <DB/IO/WriteBufferFromString.h>
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/Common/SipHash.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
String FieldVisitorDump::operator() (const String & x) const
|
||||
template <typename T>
|
||||
static inline String formatQuoted(T x)
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
@ -13,45 +21,76 @@ String FieldVisitorDump::operator() (const String & x) const
|
||||
return res;
|
||||
}
|
||||
|
||||
String FieldVisitorDump::operator() (const Array & x) const
|
||||
template <typename T>
|
||||
static inline String formatQuotedWithPrefix(T x, const char * prefix)
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
FieldVisitorDump visitor;
|
||||
|
||||
wb.write("Array_[", 7);
|
||||
for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
if (it != x.begin())
|
||||
wb.write(", ", 2);
|
||||
writeString(apply_visitor(visitor, *it), wb);
|
||||
}
|
||||
writeChar(']', wb);
|
||||
|
||||
wb.write(prefix, strlen(prefix));
|
||||
writeQuoted(x, wb);
|
||||
return res;
|
||||
}
|
||||
|
||||
String FieldVisitorDump::operator() (const Tuple & x_def) const
|
||||
|
||||
String FieldVisitorDump::operator() (const Null & x) const { return "NULL"; }
|
||||
String FieldVisitorDump::operator() (const UInt64 & x) const { return formatQuotedWithPrefix(x, "UInt64_"); }
|
||||
String FieldVisitorDump::operator() (const Int64 & x) const { return formatQuotedWithPrefix(x, "Int64_"); }
|
||||
String FieldVisitorDump::operator() (const Float64 & x) const { return formatQuotedWithPrefix(x, "Float64_"); }
|
||||
|
||||
|
||||
String FieldVisitorDump::operator() (const String & x) const
|
||||
{
|
||||
auto & x = x_def.t;
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
FieldVisitorDump visitor;
|
||||
writeQuoted(x, wb);
|
||||
return res;
|
||||
}
|
||||
|
||||
wb.write("Tuple_[", 7);
|
||||
String FieldVisitorDump::operator() (const Array & x) const
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
|
||||
wb.write("Array_[", 7);
|
||||
for (auto it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
if (it != x.begin())
|
||||
wb.write(", ", 2);
|
||||
writeString(apply_visitor(visitor, *it), wb);
|
||||
writeString(applyVisitor(*this, *it), wb);
|
||||
}
|
||||
writeChar(']', wb);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
String FieldVisitorDump::operator() (const Tuple & x_def) const
|
||||
{
|
||||
auto & x = x_def.t;
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
|
||||
String FieldVisitorToString::formatFloat(const Float64 x)
|
||||
wb.write("Tuple_(", 7);
|
||||
for (auto it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
if (it != x.begin())
|
||||
wb.write(", ", 2);
|
||||
writeString(applyVisitor(*this, *it), wb);
|
||||
}
|
||||
writeChar(')', wb);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/** In contrast to writeFloatText (and writeQuoted),
|
||||
* even if number looks like integer after formatting, prints decimal point nevertheless (for example, Float64(1) is printed as 1.).
|
||||
* - because resulting text must be able to be parsed back as Float64 by query parser (otherwise it will be parsed as integer).
|
||||
*
|
||||
* Trailing zeros after decimal point are omitted.
|
||||
*
|
||||
* NOTE: Roundtrip may lead to loss of precision.
|
||||
*/
|
||||
static String formatFloat(const Float64 x)
|
||||
{
|
||||
DoubleConverter<true>::BufferType buffer;
|
||||
double_conversion::StringBuilder builder{buffer, sizeof(buffer)};
|
||||
@ -64,37 +103,43 @@ String FieldVisitorToString::formatFloat(const Float64 x)
|
||||
return { buffer, buffer + builder.position() };
|
||||
}
|
||||
|
||||
String FieldVisitorToString::operator() (const Array & x) const
|
||||
|
||||
String FieldVisitorToString::operator() (const Null & x) const { return "NULL"; }
|
||||
String FieldVisitorToString::operator() (const UInt64 & x) const { return formatQuoted(x); }
|
||||
String FieldVisitorToString::operator() (const Int64 & x) const { return formatQuoted(x); }
|
||||
String FieldVisitorToString::operator() (const Float64 & x) const { return formatFloat(x); }
|
||||
String FieldVisitorToString::operator() (const String & x) const { return formatQuoted(x); }
|
||||
|
||||
|
||||
String FieldVisitorToString::operator() (const Array & x) const
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
FieldVisitorToString visitor;
|
||||
|
||||
writeChar('[', wb);
|
||||
for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
if (it != x.begin())
|
||||
wb.write(", ", 2);
|
||||
writeString(apply_visitor(visitor, *it), wb);
|
||||
writeString(applyVisitor(*this, *it), wb);
|
||||
}
|
||||
writeChar(']', wb);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
String FieldVisitorToString::operator() (const Tuple & x_def) const
|
||||
String FieldVisitorToString::operator() (const Tuple & x_def) const
|
||||
{
|
||||
auto & x = x_def.t;
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
FieldVisitorToString visitor;
|
||||
|
||||
writeChar('(', wb);
|
||||
for (auto it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
if (it != x.begin())
|
||||
wb.write(", ", 2);
|
||||
writeString(apply_visitor(visitor, *it), wb);
|
||||
writeString(applyVisitor(*this, *it), wb);
|
||||
}
|
||||
writeChar(')', wb);
|
||||
|
||||
@ -102,6 +147,56 @@ String FieldVisitorToString::operator() (const Tuple & x_def) const
|
||||
}
|
||||
|
||||
|
||||
FieldVisitorHash::FieldVisitorHash(SipHash & hash) : hash(hash) {}
|
||||
|
||||
void FieldVisitorHash::operator() (const Null & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Null;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const UInt64 & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::UInt64;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const Int64 & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Int64;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const Float64 & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Float64;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const String & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::String;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
size_t size = x.size();
|
||||
hash.update(reinterpret_cast<const char *>(&size), sizeof(size));
|
||||
hash.update(x.data(), x.size());
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const Array & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Array;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
size_t size = x.size();
|
||||
hash.update(reinterpret_cast<const char *>(&size), sizeof(size));
|
||||
|
||||
for (const auto & elem : x)
|
||||
applyVisitor(*this, elem);
|
||||
}
|
||||
|
||||
|
||||
UInt64 stringToDateOrDateTime(const String & s)
|
||||
{
|
||||
if (s.size() == strlen("YYYY-MM-DD"))
|
||||
|
@ -8,35 +8,38 @@
|
||||
#include <DB/Common/Stopwatch.h>
|
||||
#include <DB/DataStreams/TabSeparatedRowOutputStream.h>
|
||||
#include <DB/IO/WriteBufferFromFileDescriptor.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
#include <DB/DataTypes/DataTypeString.h>
|
||||
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
DB::FieldVisitorToString to_string;
|
||||
using namespace DB;
|
||||
|
||||
DB::Field field = DB::UInt64(0);
|
||||
std::cerr << DB::apply_visitor(to_string, field) << std::endl;
|
||||
FieldVisitorToString to_string;
|
||||
|
||||
Field field = UInt64(0);
|
||||
std::cerr << applyVisitor(to_string, field) << std::endl;
|
||||
|
||||
field = std::string("Hello, world!");
|
||||
std::cerr << DB::apply_visitor(to_string, field) << std::endl;
|
||||
std::cerr << applyVisitor(to_string, field) << std::endl;
|
||||
|
||||
field = DB::Null();
|
||||
std::cerr << DB::apply_visitor(to_string, field) << std::endl;
|
||||
field = Null();
|
||||
std::cerr << applyVisitor(to_string, field) << std::endl;
|
||||
|
||||
DB::Field field2;
|
||||
Field field2;
|
||||
field2 = field;
|
||||
std::cerr << DB::apply_visitor(to_string, field2) << std::endl;
|
||||
std::cerr << applyVisitor(to_string, field2) << std::endl;
|
||||
|
||||
DB::Array array;
|
||||
array.push_back(DB::UInt64(123));
|
||||
array.push_back(DB::Int64(-123));
|
||||
array.push_back(DB::String("Hello"));
|
||||
Array array;
|
||||
array.push_back(UInt64(123));
|
||||
array.push_back(Int64(-123));
|
||||
array.push_back(String("Hello"));
|
||||
field = array;
|
||||
std::cerr << DB::apply_visitor(to_string, field) << std::endl;
|
||||
std::cerr << applyVisitor(to_string, field) << std::endl;
|
||||
|
||||
DB::get<DB::Array &>(field).push_back(field);
|
||||
std::cerr << DB::apply_visitor(to_string, field) << std::endl;
|
||||
get<Array &>(field).push_back(field);
|
||||
std::cerr << applyVisitor(to_string, field) << std::endl;
|
||||
|
||||
std::cerr << (field < field2) << std::endl;
|
||||
std::cerr << (field2 < field) << std::endl;
|
||||
@ -44,18 +47,18 @@ int main(int argc, char ** argv)
|
||||
|
||||
try
|
||||
{
|
||||
size_t n = argc == 2 ? DB::parse<UInt64>(argv[1]) : 10000000;
|
||||
size_t n = argc == 2 ? parse<UInt64>(argv[1]) : 10000000;
|
||||
|
||||
Stopwatch watch;
|
||||
|
||||
{
|
||||
DB::Array array(n);
|
||||
Array array(n);
|
||||
|
||||
{
|
||||
Stopwatch watch;
|
||||
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
array[i] = DB::String(i % 32, '!');
|
||||
array[i] = String(i % 32, '!');
|
||||
|
||||
watch.stop();
|
||||
std::cerr << std::fixed << std::setprecision(2)
|
||||
@ -69,7 +72,7 @@ int main(int argc, char ** argv)
|
||||
|
||||
size_t sum = 0;
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
sum += DB::safeGet<const DB::String &>(array[i]).size();
|
||||
sum += safeGet<const String &>(array[i]).size();
|
||||
|
||||
watch.stop();
|
||||
std::cerr << std::fixed << std::setprecision(2)
|
||||
@ -86,17 +89,17 @@ int main(int argc, char ** argv)
|
||||
watch.stop();
|
||||
|
||||
std::cerr << std::fixed << std::setprecision(2)
|
||||
<< "Destroyed " << n << " fields (" << n * sizeof(DB::Array::value_type) / 1000000.0 << " MB) in " << watch.elapsedSeconds() << " sec., "
|
||||
<< n / watch.elapsedSeconds() << " elem/sec. (" << n * sizeof(DB::Array::value_type) / watch.elapsedSeconds() / 1000000 << " MB/s.)"
|
||||
<< "Destroyed " << n << " fields (" << n * sizeof(Array::value_type) / 1000000.0 << " MB) in " << watch.elapsedSeconds() << " sec., "
|
||||
<< n / watch.elapsedSeconds() << " elem/sec. (" << n * sizeof(Array::value_type) / watch.elapsedSeconds() / 1000000 << " MB/s.)"
|
||||
<< std::endl;
|
||||
}
|
||||
catch (const DB::Exception & e)
|
||||
catch (const Exception & e)
|
||||
{
|
||||
std::cerr << e.what() << ", " << e.displayText() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cerr << "sizeof(Field) = " << sizeof(DB::Field) << std::endl;
|
||||
std::cerr << "sizeof(Field) = " << sizeof(Field) << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ void CollapsingSortedBlockInputStream::reportIncorrectData()
|
||||
{
|
||||
if (i != 0)
|
||||
s << ", ";
|
||||
s << apply_visitor(FieldVisitorToString(), (*current_key.columns[i])[current_key.row_num]);
|
||||
s << applyVisitor(FieldVisitorToString(), (*current_key.columns[i])[current_key.row_num]);
|
||||
}
|
||||
|
||||
s << ").";
|
||||
|
@ -316,7 +316,7 @@ bool SummingSortedBlockInputStream::mergeMap(const MapDescription & desc, Row &
|
||||
bool has_non_zero = false;
|
||||
size_t size = dst.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
if (apply_visitor(FieldVisitorSum(src[i]), dst[i]))
|
||||
if (applyVisitor(FieldVisitorSum(src[i]), dst[i]))
|
||||
has_non_zero = true;
|
||||
return has_non_zero;
|
||||
};
|
||||
@ -373,7 +373,7 @@ bool SummingSortedBlockInputStream::addRow(Row & row, TSortCursor & cursor)
|
||||
for (size_t i = 0, size = column_numbers_to_sum.size(); i < size; ++i)
|
||||
{
|
||||
size_t j = column_numbers_to_sum[i];
|
||||
if (apply_visitor(FieldVisitorSum((*cursor->all_columns[j])[cursor->pos]), row[j]))
|
||||
if (applyVisitor(FieldVisitorSum((*cursor->all_columns[j])[cursor->pos]), row[j]))
|
||||
res = true;
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ bool ValuesRowInputStream::read(Block & block)
|
||||
}
|
||||
|
||||
if (!is_null_allowed)
|
||||
throw Exception{"Expression returns value " + apply_visitor(FieldVisitorToString(), value)
|
||||
throw Exception{"Expression returns value " + applyVisitor(FieldVisitorToString(), value)
|
||||
+ ", that is out of range of type " + type.getName()
|
||||
+ ", at: " + String(prev_istr_position, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, istr.buffer().end() - prev_istr_position)),
|
||||
ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE};
|
||||
|
@ -24,7 +24,7 @@ std::string DataTypeAggregateFunction::getName() const
|
||||
{
|
||||
if (i)
|
||||
stream << ", ";
|
||||
stream << apply_visitor(DB::FieldVisitorToString(), parameters[i]);
|
||||
stream << applyVisitor(DB::FieldVisitorToString(), parameters[i]);
|
||||
}
|
||||
stream << ")";
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ inline DataTypePtr parseEnum(const String & name, const String & base_name, cons
|
||||
|
||||
if (value > std::numeric_limits<FieldType>::max() || value < std::numeric_limits<FieldType>::min())
|
||||
throw Exception{
|
||||
"Value " + apply_visitor(FieldVisitorToString{}, e.value) + " for element '" + e.name + "' exceeds range of " + base_name,
|
||||
"Value " + applyVisitor(FieldVisitorToString{}, e.value) + " for element '" + e.name + "' exceeds range of " + base_name,
|
||||
ErrorCodes::ARGUMENT_OUT_OF_BOUND
|
||||
};
|
||||
|
||||
|
@ -22,7 +22,7 @@ static void convertArrayToCommonType(Array & arr)
|
||||
for (auto & elem : arr)
|
||||
{
|
||||
if (!elem.isNull())
|
||||
elem = apply_visitor(FieldVisitorConvertToNumber<T>(), elem);
|
||||
elem = applyVisitor(FieldVisitorConvertToNumber<T>(), elem);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +217,7 @@ DataTypePtr FieldToDataType::operator() (Tuple & x) const
|
||||
element_types.reserve(ext::size(tuple));
|
||||
|
||||
for (auto & element : tuple)
|
||||
element_types.push_back(apply_visitor(FieldToDataType{}, element));
|
||||
element_types.push_back(applyVisitor(FieldToDataType{}, element));
|
||||
|
||||
return std::make_shared<DataTypeTuple>(element_types);
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ BlockInputStreamPtr MongoDBDictionarySource::loadKeys(
|
||||
|
||||
case AttributeUnderlyingType::Float32:
|
||||
case AttributeUnderlyingType::Float64:
|
||||
key.add(attr.second.name, apply_visitor(FieldVisitorConvertToNumber<Float64>(), (*key_columns[attr.first])[row_idx]));
|
||||
key.add(attr.second.name, applyVisitor(FieldVisitorConvertToNumber<Float64>(), (*key_columns[attr.first])[row_idx]));
|
||||
break;
|
||||
|
||||
case AttributeUnderlyingType::String:
|
||||
|
@ -116,7 +116,7 @@ bool tryAddField(DataTypePtr type_res, const Field & f, Array & arr)
|
||||
if (f.isNull())
|
||||
arr.emplace_back();
|
||||
else
|
||||
arr.push_back(apply_visitor(FieldVisitorConvertToNumber<typename T1::FieldType>(), f));
|
||||
arr.push_back(applyVisitor(FieldVisitorConvertToNumber<typename T1::FieldType>(), f));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1994,7 +1994,7 @@ void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool onl
|
||||
}
|
||||
else if (ASTLiteral * node = typeid_cast<ASTLiteral *>(ast.get()))
|
||||
{
|
||||
DataTypePtr type = apply_visitor(FieldToDataType(), node->value);
|
||||
DataTypePtr type = applyVisitor(FieldToDataType(), node->value);
|
||||
|
||||
ColumnWithTypeAndName column;
|
||||
column.column = type->createConstColumn(1, node->value);
|
||||
|
@ -522,7 +522,7 @@ std::string Set::describe() const
|
||||
ss << "{";
|
||||
for (const Field & f : *ordered_set_elements)
|
||||
{
|
||||
ss << (first ? "" : ", ") << apply_visitor(FieldVisitorToString(), f);
|
||||
ss << (first ? "" : ", ") << applyVisitor(FieldVisitorToString(), f);
|
||||
first = false;
|
||||
}
|
||||
ss << "}";
|
||||
|
@ -10,6 +10,12 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
|
||||
std::string getClusterName(const IAST & node)
|
||||
{
|
||||
if (const ASTIdentifier * ast_id = typeid_cast<const ASTIdentifier *>(&node))
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <DB/Common/typeid_cast.h>
|
||||
#include <DB/Parsers/ASTLiteral.h>
|
||||
#include <DB/Parsers/ASTFunction.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/IO/WriteBufferFromString.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -1,83 +1,28 @@
|
||||
#include <DB/Common/SipHash.h>
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/Parsers/ASTLiteral.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
/** Обновляет SipHash по данным Field */
|
||||
class FieldVisitorHash : public StaticVisitor<>
|
||||
{
|
||||
private:
|
||||
SipHash & hash;
|
||||
public:
|
||||
FieldVisitorHash(SipHash & hash) : hash(hash) {}
|
||||
|
||||
void operator() (const Null & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Null;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
}
|
||||
|
||||
void operator() (const UInt64 & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::UInt64;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
|
||||
}
|
||||
|
||||
void operator() (const Int64 & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Int64;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
|
||||
}
|
||||
|
||||
void operator() (const Float64 & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Float64;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
|
||||
}
|
||||
|
||||
void operator() (const String & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::String;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
size_t size = x.size();
|
||||
hash.update(reinterpret_cast<const char *>(&size), sizeof(size));
|
||||
hash.update(x.data(), x.size());
|
||||
}
|
||||
|
||||
void operator() (const Array & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Array;
|
||||
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
||||
size_t size = x.size();
|
||||
hash.update(reinterpret_cast<const char *>(&size), sizeof(size));
|
||||
|
||||
for (const auto & elem : x)
|
||||
apply_visitor(*this, elem);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
String ASTLiteral::getColumnName() const
|
||||
{
|
||||
/// Отдельный случай для очень больших массивов. Вместо указания всех элементов, будем использовать хэш от содержимого.
|
||||
/// Special case for very large arrays. Instead of listing all elements, will use hash of them.
|
||||
/// (Otherwise column name will be too long, that will lead to significant slowdown of expression analysis.)
|
||||
if (value.getType() == Field::Types::Array
|
||||
&& value.get<const Array &>().size() > 100) /// 100 - наугад.
|
||||
&& value.get<const Array &>().size() > 100) /// 100 - just arbitary value.
|
||||
{
|
||||
SipHash hash;
|
||||
apply_visitor(FieldVisitorHash(hash), value);
|
||||
applyVisitor(FieldVisitorHash(hash), value);
|
||||
UInt64 low, high;
|
||||
hash.get128(low, high);
|
||||
return "__array_" + toString(low) + "_" + toString(high);
|
||||
}
|
||||
|
||||
return apply_visitor(FieldVisitorToString(), value);
|
||||
return applyVisitor(FieldVisitorToString(), value);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -318,7 +318,7 @@ void ASTSelectQuery::formatImpl(const FormatSettings & s, FormatState & state, F
|
||||
if (it != ast_set.changes.begin())
|
||||
s.ostr << ", ";
|
||||
|
||||
s.ostr << it->name << " = " << apply_visitor(FieldVisitorToString(), it->value);
|
||||
s.ostr << it->name << " = " << applyVisitor(FieldVisitorToString(), it->value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ bool ParserOptimizeQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max
|
||||
if (table)
|
||||
query->table = typeid_cast<const ASTIdentifier &>(*table).name;
|
||||
if (partition)
|
||||
query->partition = apply_visitor(FieldVisitorToString(), typeid_cast<const ASTLiteral &>(*partition).value);
|
||||
query->partition = applyVisitor(FieldVisitorToString(), typeid_cast<const ASTLiteral &>(*partition).value);
|
||||
query->final = final;
|
||||
|
||||
return true;
|
||||
|
@ -172,8 +172,8 @@ const PKCondition::AtomMap PKCondition::atom_map{
|
||||
};
|
||||
|
||||
|
||||
inline bool Range::equals(const Field & lhs, const Field & rhs) { return apply_visitor(FieldVisitorAccurateEquals(), lhs, rhs); }
|
||||
inline bool Range::less(const Field & lhs, const Field & rhs) { return apply_visitor(FieldVisitorAccurateLess(), lhs, rhs); }
|
||||
inline bool Range::equals(const Field & lhs, const Field & rhs) { return applyVisitor(FieldVisitorAccurateEquals(), lhs, rhs); }
|
||||
inline bool Range::less(const Field & lhs, const Field & rhs) { return applyVisitor(FieldVisitorAccurateLess(), lhs, rhs); }
|
||||
|
||||
|
||||
Block PKCondition::getBlockWithConstants(
|
||||
@ -666,13 +666,13 @@ bool PKCondition::mayBeTrueInRange(
|
||||
|
||||
/* std::cerr << "Checking for: [";
|
||||
for (size_t i = 0; i != used_key_size; ++i)
|
||||
std::cerr << (i != 0 ? ", " : "") << apply_visitor(FieldVisitorToString(), left_pk[i]);
|
||||
std::cerr << (i != 0 ? ", " : "") << applyVisitor(FieldVisitorToString(), left_pk[i]);
|
||||
std::cerr << " ... ";
|
||||
|
||||
if (right_bounded)
|
||||
{
|
||||
for (size_t i = 0; i != used_key_size; ++i)
|
||||
std::cerr << (i != 0 ? ", " : "") << apply_visitor(FieldVisitorToString(), right_pk[i]);
|
||||
std::cerr << (i != 0 ? ", " : "") << applyVisitor(FieldVisitorToString(), right_pk[i]);
|
||||
std::cerr << "]\n";
|
||||
}
|
||||
else
|
||||
@ -726,8 +726,8 @@ bool PKCondition::mayBeTrueInRangeImpl(const std::vector<Range> & key_ranges, co
|
||||
/* std::cerr << "Function " << func->getName() << " is " << (monotonicity.is_monotonic ? "" : "not ")
|
||||
<< "monotonic " << (monotonicity.is_monotonic ? (monotonicity.is_positive ? "(positive) " : "(negative) ") : "")
|
||||
<< "in range "
|
||||
<< "[" << apply_visitor(FieldVisitorToString(), key_range_transformed.left)
|
||||
<< ", " << apply_visitor(FieldVisitorToString(), key_range_transformed.right) << "]\n";*/
|
||||
<< "[" << applyVisitor(FieldVisitorToString(), key_range_transformed.left)
|
||||
<< ", " << applyVisitor(FieldVisitorToString(), key_range_transformed.right) << "]\n";*/
|
||||
|
||||
if (!monotonicity.is_monotonic)
|
||||
{
|
||||
|
@ -498,14 +498,14 @@ StoragePtr StorageFactory::get(
|
||||
String destination_database = static_cast<const ASTLiteral &>(*args[0]).value.safeGet<String>();
|
||||
String destination_table = static_cast<const ASTLiteral &>(*args[1]).value.safeGet<String>();
|
||||
|
||||
size_t num_buckets = apply_visitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[2]).value);
|
||||
size_t num_buckets = applyVisitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[2]).value);
|
||||
|
||||
time_t min_time = apply_visitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[3]).value);
|
||||
time_t max_time = apply_visitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[4]).value);
|
||||
size_t min_rows = apply_visitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[5]).value);
|
||||
size_t max_rows = apply_visitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[6]).value);
|
||||
size_t min_bytes = apply_visitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[7]).value);
|
||||
size_t max_bytes = apply_visitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[8]).value);
|
||||
time_t min_time = applyVisitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[3]).value);
|
||||
time_t max_time = applyVisitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[4]).value);
|
||||
size_t min_rows = applyVisitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[5]).value);
|
||||
size_t max_rows = applyVisitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[6]).value);
|
||||
size_t min_bytes = applyVisitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[7]).value);
|
||||
size_t max_bytes = applyVisitor(FieldVisitorConvertToNumber<size_t>(), typeid_cast<ASTLiteral &>(*args[8]).value);
|
||||
|
||||
return StorageBuffer::create(
|
||||
table_name, columns,
|
||||
|
@ -402,7 +402,7 @@ void StorageMergeTree::dropPartition(ASTPtr query, const Field & partition, bool
|
||||
data.replaceParts({part}, {}, false);
|
||||
}
|
||||
|
||||
LOG_INFO(log, (detach ? "Detached " : "Removed ") << removed_parts << " parts inside " << apply_visitor(FieldVisitorToString(), partition) << ".");
|
||||
LOG_INFO(log, (detach ? "Detached " : "Removed ") << removed_parts << " parts inside " << applyVisitor(FieldVisitorToString(), partition) << ".");
|
||||
}
|
||||
|
||||
|
||||
|
@ -2574,7 +2574,7 @@ void StorageReplicatedMergeTree::dropUnreplicatedPartition(const Field & partiti
|
||||
unreplicated_data->replaceParts({part}, {}, false);
|
||||
}
|
||||
|
||||
LOG_INFO(log, (detach ? "Detached " : "Removed ") << removed_parts << " unreplicated parts inside " << apply_visitor(FieldVisitorToString(), partition) << ".");
|
||||
LOG_INFO(log, (detach ? "Detached " : "Removed ") << removed_parts << " unreplicated parts inside " << applyVisitor(FieldVisitorToString(), partition) << ".");
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user