| 318 | |
| 319 | template <typename DataTypeEnum> |
| 320 | static DataTypePtr createExact(const ASTPtr & arguments, bool is_add = false, bool auto_assign = true, std::vector<UInt8> relative_flags = {}) |
| 321 | { |
| 322 | if (!arguments || arguments->children.empty()) |
| 323 | throw Exception(ErrorCodes::EMPTY_DATA_PASSED, "Enum data type cannot be empty"); |
| 324 | |
| 325 | typename DataTypeEnum::Values values; |
| 326 | values.reserve(arguments->children.size()); |
| 327 | |
| 328 | using FieldType = typename DataTypeEnum::FieldType; |
| 329 | |
| 330 | if (auto_assign) |
| 331 | relative_flags = autoAssignNumberForEnum(arguments, is_add); |
| 332 | |
| 333 | /// Children must be functions 'equals' with string literal as left argument and numeric literal as right argument. |
| 334 | for (const ASTPtr & child : arguments->children) |
| 335 | { |
| 336 | const auto literals = getEnumElementLiterals(child); |
| 337 | const String & field_name = literals.name_literal->value.safeGet<String>(); |
| 338 | |
| 339 | /// safeGet<FieldType>() reinterprets the stored bits as Int64, so a UInt64 literal above |
| 340 | /// Int64 max becomes negative (e.g. 18446744073709551615 -> -1) and would slip past the |
| 341 | /// range check below. Reject such a value up front against the Enum's range. |
| 342 | if (literals.value_literal->value.getType() == Field::Types::UInt64) |
| 343 | { |
| 344 | const UInt64 unsigned_value = literals.value_literal->value.safeGet<UInt64>(); |
| 345 | if (unsigned_value > static_cast<UInt64>(std::numeric_limits<FieldType>::max())) |
| 346 | throw Exception(ErrorCodes::ARGUMENT_OUT_OF_BOUND, "Value {} for element '{}' exceeds range of {}", |
| 347 | toString(unsigned_value), field_name, EnumName<FieldType>::value); |
| 348 | } |
| 349 | |
| 350 | const auto value = literals.value_literal->value.safeGet<FieldType>(); |
| 351 | |
| 352 | if (value > std::numeric_limits<FieldType>::max() || value < std::numeric_limits<FieldType>::min()) |
| 353 | throw Exception(ErrorCodes::ARGUMENT_OUT_OF_BOUND, "Value {} for element '{}' exceeds range of {}", |
| 354 | toString(value), field_name, EnumName<FieldType>::value); |
| 355 | |
| 356 | values.emplace_back(field_name, value); |
| 357 | } |
| 358 | |
| 359 | return std::make_shared<DataTypeEnum>(values, is_add, std::move(relative_flags)); |
| 360 | } |
| 361 | |
| 362 | static DataTypePtr create(const ASTPtr & arguments, bool is_add = false) |
| 363 | { |
nothing calls this directly
no test coverage detected