mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-26 17:41:59 +00:00
Unindent contents of anonymous namespace
This commit is contained in:
parent
6d710d06a6
commit
6db2a42d19
@ -23,216 +23,216 @@ namespace ErrorCodes
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
const std::unordered_map<std::string_view, UInt64> size_unit_to_bytes =
|
const std::unordered_map<std::string_view, UInt64> size_unit_to_bytes =
|
||||||
|
{
|
||||||
|
{"b", 1},
|
||||||
|
// ISO/IEC 80000-13 binary units
|
||||||
|
{"kib", 1024}, // 1024
|
||||||
|
{"mib", 1048576}, // 1024 * 1024
|
||||||
|
{"gib", 1073741824}, // 1024 * 1024 * 1024
|
||||||
|
{"tib", 1099511627776}, // 1024 * 1024 * 1024 * 1024
|
||||||
|
{"pib", 1125899906842624}, // 1024 * 1024 * 1024 * 1024 * 1024
|
||||||
|
{"eib", 1152921504606846976}, // 1024 * 1024 * 1024 * 1024 * 1024 * 1024
|
||||||
|
|
||||||
|
// SI units
|
||||||
|
{"kb", 1000}, // 10e3
|
||||||
|
{"mb", 1000000}, // 10e6
|
||||||
|
{"gb", 1000000000}, // 10e9
|
||||||
|
{"tb", 1000000000000}, // 10e12
|
||||||
|
{"pb", 1000000000000000}, // 10e15
|
||||||
|
{"eb", 1000000000000000000}, // 10e18
|
||||||
|
};
|
||||||
|
constexpr UInt64 MAX_UINT64 = std::numeric_limits<UInt64>::max();
|
||||||
|
|
||||||
|
class FunctionFromReadableSize : public IFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto name = "fromReadableSize";
|
||||||
|
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionFromReadableSize>(); }
|
||||||
|
|
||||||
|
String getName() const override { return name; }
|
||||||
|
|
||||||
|
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
|
||||||
|
|
||||||
|
size_t getNumberOfArguments() const override { return 1; }
|
||||||
|
|
||||||
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||||
{
|
{
|
||||||
{"b", 1},
|
if (arguments.empty())
|
||||||
// ISO/IEC 80000-13 binary units
|
throw Exception(
|
||||||
{"kib", 1024}, // 1024
|
ErrorCodes::TOO_FEW_ARGUMENTS_FOR_FUNCTION,
|
||||||
{"mib", 1048576}, // 1024 * 1024
|
"Number of arguments for function {} doesn't match: passed {}, should be 1.",
|
||||||
{"gib", 1073741824}, // 1024 * 1024 * 1024
|
getName(),
|
||||||
{"tib", 1099511627776}, // 1024 * 1024 * 1024 * 1024
|
arguments.size());
|
||||||
{"pib", 1125899906842624}, // 1024 * 1024 * 1024 * 1024 * 1024
|
|
||||||
{"eib", 1152921504606846976}, // 1024 * 1024 * 1024 * 1024 * 1024 * 1024
|
|
||||||
|
|
||||||
// SI units
|
if (arguments.size() > 1)
|
||||||
{"kb", 1000}, // 10e3
|
throw Exception(
|
||||||
{"mb", 1000000}, // 10e6
|
ErrorCodes::TOO_MANY_ARGUMENTS_FOR_FUNCTION,
|
||||||
{"gb", 1000000000}, // 10e9
|
"Number of arguments for function {} doesn't match: passed {}, should be 1.",
|
||||||
{"tb", 1000000000000}, // 10e12
|
getName(),
|
||||||
{"pb", 1000000000000000}, // 10e15
|
arguments.size());
|
||||||
{"eb", 1000000000000000000}, // 10e18
|
|
||||||
};
|
|
||||||
constexpr UInt64 MAX_UINT64 = std::numeric_limits<UInt64>::max();
|
|
||||||
|
|
||||||
class FunctionFromReadableSize : public IFunction
|
const IDataType & type = *arguments[0];
|
||||||
|
|
||||||
|
if (!isString(type))
|
||||||
|
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Cannot format {} as time string.", type.getName());
|
||||||
|
|
||||||
|
return std::make_shared<DataTypeUInt64>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useDefaultImplementationForConstants() const override { return true; }
|
||||||
|
|
||||||
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||||
{
|
{
|
||||||
public:
|
auto col_to = ColumnUInt64::create();
|
||||||
static constexpr auto name = "fromReadableSize";
|
auto & res_data = col_to->getData();
|
||||||
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionFromReadableSize>(); }
|
|
||||||
|
|
||||||
String getName() const override { return name; }
|
for (size_t i = 0; i < input_rows_count; ++i)
|
||||||
|
|
||||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
|
|
||||||
|
|
||||||
size_t getNumberOfArguments() const override { return 1; }
|
|
||||||
|
|
||||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
|
||||||
{
|
{
|
||||||
if (arguments.empty())
|
std::string_view str{arguments[0].column->getDataAt(i)};
|
||||||
throw Exception(
|
Int64 token_tail = 0;
|
||||||
ErrorCodes::TOO_FEW_ARGUMENTS_FOR_FUNCTION,
|
Int64 token_front = 0;
|
||||||
"Number of arguments for function {} doesn't match: passed {}, should be 1.",
|
Int64 last_pos = str.length() - 1;
|
||||||
getName(),
|
UInt64 result = 0;
|
||||||
arguments.size());
|
|
||||||
|
|
||||||
if (arguments.size() > 1)
|
/// ignore '.' and ' ' at the end of string
|
||||||
throw Exception(
|
while (last_pos >= 0 && (str[last_pos] == ' ' || str[last_pos] == '.'))
|
||||||
ErrorCodes::TOO_MANY_ARGUMENTS_FOR_FUNCTION,
|
--last_pos;
|
||||||
"Number of arguments for function {} doesn't match: passed {}, should be 1.",
|
|
||||||
getName(),
|
|
||||||
arguments.size());
|
|
||||||
|
|
||||||
const IDataType & type = *arguments[0];
|
/// no valid characters
|
||||||
|
if (last_pos < 0)
|
||||||
if (!isString(type))
|
|
||||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Cannot format {} as time string.", type.getName());
|
|
||||||
|
|
||||||
return std::make_shared<DataTypeUInt64>();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool useDefaultImplementationForConstants() const override { return true; }
|
|
||||||
|
|
||||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
|
||||||
{
|
|
||||||
auto col_to = ColumnUInt64::create();
|
|
||||||
auto & res_data = col_to->getData();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < input_rows_count; ++i)
|
|
||||||
{
|
{
|
||||||
std::string_view str{arguments[0].column->getDataAt(i)};
|
throw Exception(
|
||||||
Int64 token_tail = 0;
|
ErrorCodes::BAD_ARGUMENTS,
|
||||||
Int64 token_front = 0;
|
"Invalid expression for function {}, don't find valid characters, str: \"{}\".",
|
||||||
Int64 last_pos = str.length() - 1;
|
getName(),
|
||||||
UInt64 result = 0;
|
String(str));
|
||||||
|
}
|
||||||
|
|
||||||
/// ignore '.' and ' ' at the end of string
|
/// last pos character must be character and not be separator or number after ignoring '.' and ' '
|
||||||
while (last_pos >= 0 && (str[last_pos] == ' ' || str[last_pos] == '.'))
|
if (!isalpha(str[last_pos]))
|
||||||
--last_pos;
|
{
|
||||||
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Invalid expression for function {}, str: \"{}\".", getName(), String(str));
|
||||||
|
}
|
||||||
|
|
||||||
/// no valid characters
|
/// scan spaces at the beginning
|
||||||
if (last_pos < 0)
|
scanSpaces(str, token_tail, last_pos);
|
||||||
{
|
token_front = token_tail;
|
||||||
throw Exception(
|
/// scan unsigned integer
|
||||||
ErrorCodes::BAD_ARGUMENTS,
|
if (!scanUnsignedInteger(str, token_tail, last_pos))
|
||||||
"Invalid expression for function {}, don't find valid characters, str: \"{}\".",
|
{
|
||||||
getName(),
|
throw Exception(
|
||||||
String(str));
|
ErrorCodes::BAD_ARGUMENTS,
|
||||||
}
|
"Invalid expression for function {}, find number failed, str: \"{}\".",
|
||||||
|
getName(),
|
||||||
|
String(str));
|
||||||
|
}
|
||||||
|
|
||||||
/// last pos character must be character and not be separator or number after ignoring '.' and ' '
|
/// if there is a '.', then scan another integer to get a float number
|
||||||
if (!isalpha(str[last_pos]))
|
if (token_tail <= last_pos && str[token_tail] == '.')
|
||||||
{
|
{
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Invalid expression for function {}, str: \"{}\".", getName(), String(str));
|
token_tail++;
|
||||||
}
|
|
||||||
|
|
||||||
/// scan spaces at the beginning
|
|
||||||
scanSpaces(str, token_tail, last_pos);
|
|
||||||
token_front = token_tail;
|
|
||||||
/// scan unsigned integer
|
|
||||||
if (!scanUnsignedInteger(str, token_tail, last_pos))
|
if (!scanUnsignedInteger(str, token_tail, last_pos))
|
||||||
{
|
{
|
||||||
throw Exception(
|
throw Exception(
|
||||||
ErrorCodes::BAD_ARGUMENTS,
|
ErrorCodes::BAD_ARGUMENTS,
|
||||||
"Invalid expression for function {}, find number failed, str: \"{}\".",
|
"Invalid expression for function {}, find number after '.' failed, str: \"{}\".",
|
||||||
getName(),
|
getName(),
|
||||||
String(str));
|
String(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// if there is a '.', then scan another integer to get a float number
|
|
||||||
if (token_tail <= last_pos && str[token_tail] == '.')
|
|
||||||
{
|
|
||||||
token_tail++;
|
|
||||||
if (!scanUnsignedInteger(str, token_tail, last_pos))
|
|
||||||
{
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::BAD_ARGUMENTS,
|
|
||||||
"Invalid expression for function {}, find number after '.' failed, str: \"{}\".",
|
|
||||||
getName(),
|
|
||||||
String(str));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// convert float/integer string to float
|
|
||||||
Float64 base = 0;
|
|
||||||
std::string_view base_str = str.substr(token_front, token_tail - token_front);
|
|
||||||
auto value = boost::convert<Float64>(base_str, boost::cnv::strtol());
|
|
||||||
if (!value.has_value())
|
|
||||||
{
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::BAD_ARGUMENTS,
|
|
||||||
"Invalid expression for function {}, convert string to float64 failed: \"{}\".",
|
|
||||||
getName(),
|
|
||||||
String(base_str));
|
|
||||||
}
|
|
||||||
base = value.get();
|
|
||||||
|
|
||||||
scanSpaces(str, token_tail, last_pos);
|
|
||||||
token_front = token_tail;
|
|
||||||
|
|
||||||
/// scan a unit
|
|
||||||
if (!scanUnit(str, token_tail, last_pos))
|
|
||||||
{
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::BAD_ARGUMENTS,
|
|
||||||
"Invalid expression for function {}, find unit failed, str: \"{}\".",
|
|
||||||
getName(),
|
|
||||||
String(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string unit = std::string{str.substr(token_front, token_tail - token_front)};
|
|
||||||
boost::algorithm::to_lower(unit);
|
|
||||||
auto iter = size_unit_to_bytes.find(unit);
|
|
||||||
if (iter == size_unit_to_bytes.end()) /// not find unit
|
|
||||||
{
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::BAD_ARGUMENTS, "Invalid expression for function {}, parse unit failed: \"{}\".", getName(), unit);
|
|
||||||
}
|
|
||||||
Float64 raw_num_bytes = base * iter->second;
|
|
||||||
if (raw_num_bytes > MAX_UINT64)
|
|
||||||
{
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::BAD_ARGUMENTS,
|
|
||||||
"Invalid expression for function {}, result is too big for output data type (UInt64): \"{}\".",
|
|
||||||
getName(),
|
|
||||||
raw_num_bytes
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// As the input might be an arbitrary decimal number we might end up with a non-integer amount of bytes when parsing binary (eg MiB) units.
|
|
||||||
// This doesn't make sense so we round up to indicate the byte size that can fit the passed size.
|
|
||||||
result = static_cast<UInt64>(std::ceil(raw_num_bytes));
|
|
||||||
|
|
||||||
res_data.emplace_back(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return col_to;
|
/// convert float/integer string to float
|
||||||
}
|
Float64 base = 0;
|
||||||
|
std::string_view base_str = str.substr(token_front, token_tail - token_front);
|
||||||
/// scan an unsigned integer number
|
auto value = boost::convert<Float64>(base_str, boost::cnv::strtol());
|
||||||
static bool scanUnsignedInteger(std::string_view & str, Int64 & index, Int64 last_pos)
|
if (!value.has_value())
|
||||||
{
|
|
||||||
int64_t begin_index = index;
|
|
||||||
while (index <= last_pos && isdigit(str[index]))
|
|
||||||
{
|
{
|
||||||
index++;
|
throw Exception(
|
||||||
|
ErrorCodes::BAD_ARGUMENTS,
|
||||||
|
"Invalid expression for function {}, convert string to float64 failed: \"{}\".",
|
||||||
|
getName(),
|
||||||
|
String(base_str));
|
||||||
}
|
}
|
||||||
return index != begin_index;
|
base = value.get();
|
||||||
}
|
|
||||||
|
|
||||||
/// scan a unit
|
scanSpaces(str, token_tail, last_pos);
|
||||||
static bool scanUnit(std::string_view & str, Int64 & index, Int64 last_pos)
|
token_front = token_tail;
|
||||||
{
|
|
||||||
int64_t begin_index = index;
|
/// scan a unit
|
||||||
while (index <= last_pos && !isdigit(str[index]) && !isSeparator(str[index]))
|
if (!scanUnit(str, token_tail, last_pos))
|
||||||
{
|
{
|
||||||
index++;
|
throw Exception(
|
||||||
|
ErrorCodes::BAD_ARGUMENTS,
|
||||||
|
"Invalid expression for function {}, find unit failed, str: \"{}\".",
|
||||||
|
getName(),
|
||||||
|
String(str));
|
||||||
}
|
}
|
||||||
return index != begin_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// scan spaces
|
std::string unit = std::string{str.substr(token_front, token_tail - token_front)};
|
||||||
static void scanSpaces(std::string_view & str, Int64 & index, Int64 last_pos)
|
boost::algorithm::to_lower(unit);
|
||||||
{
|
auto iter = size_unit_to_bytes.find(unit);
|
||||||
while (index <= last_pos && (str[index] == ' '))
|
if (iter == size_unit_to_bytes.end()) /// not find unit
|
||||||
{
|
{
|
||||||
index++;
|
throw Exception(
|
||||||
|
ErrorCodes::BAD_ARGUMENTS, "Invalid expression for function {}, parse unit failed: \"{}\".", getName(), unit);
|
||||||
}
|
}
|
||||||
|
Float64 raw_num_bytes = base * iter->second;
|
||||||
|
if (raw_num_bytes > MAX_UINT64)
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::BAD_ARGUMENTS,
|
||||||
|
"Invalid expression for function {}, result is too big for output data type (UInt64): \"{}\".",
|
||||||
|
getName(),
|
||||||
|
raw_num_bytes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// As the input might be an arbitrary decimal number we might end up with a non-integer amount of bytes when parsing binary (eg MiB) units.
|
||||||
|
// This doesn't make sense so we round up to indicate the byte size that can fit the passed size.
|
||||||
|
result = static_cast<UInt64>(std::ceil(raw_num_bytes));
|
||||||
|
|
||||||
|
res_data.emplace_back(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isSeparator(char symbol)
|
return col_to;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// scan an unsigned integer number
|
||||||
|
static bool scanUnsignedInteger(std::string_view & str, Int64 & index, Int64 last_pos)
|
||||||
|
{
|
||||||
|
int64_t begin_index = index;
|
||||||
|
while (index <= last_pos && isdigit(str[index]))
|
||||||
{
|
{
|
||||||
return symbol == ';' || symbol == '-' || symbol == '+' || symbol == ',' || symbol == ':' || symbol == ' ';
|
index++;
|
||||||
}
|
}
|
||||||
};
|
return index != begin_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// scan a unit
|
||||||
|
static bool scanUnit(std::string_view & str, Int64 & index, Int64 last_pos)
|
||||||
|
{
|
||||||
|
int64_t begin_index = index;
|
||||||
|
while (index <= last_pos && !isdigit(str[index]) && !isSeparator(str[index]))
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return index != begin_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// scan spaces
|
||||||
|
static void scanSpaces(std::string_view & str, Int64 & index, Int64 last_pos)
|
||||||
|
{
|
||||||
|
while (index <= last_pos && (str[index] == ' '))
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isSeparator(char symbol)
|
||||||
|
{
|
||||||
|
return symbol == ';' || symbol == '-' || symbol == '+' || symbol == ',' || symbol == ':' || symbol == ' ';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user