From c1ced0d9d8d6a399a86596aa3171aa1393b92e7c Mon Sep 17 00:00:00 2001 From: Konstantin Vedernikov Date: Sat, 20 Jul 2024 19:21:48 +0000 Subject: [PATCH] first version of sultion --- src/Core/Settings.h | 1 + src/DataTypes/EnumValues.cpp | 21 ++++++++++++++++++- .../03202_enum_json_cast.reference | 0 .../0_stateless/03202_enum_json_cast.sql | 10 +++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/queries/0_stateless/03202_enum_json_cast.reference create mode 100644 tests/queries/0_stateless/03202_enum_json_cast.sql diff --git a/src/Core/Settings.h b/src/Core/Settings.h index 3349662cb78..33c906a5f58 100644 --- a/src/Core/Settings.h +++ b/src/Core/Settings.h @@ -1158,6 +1158,7 @@ class IColumn; M(Bool, input_format_values_accurate_types_of_literals, true, "For Values format: when parsing and interpreting expressions using template, check actual type of literal to avoid possible overflow and precision issues.", 0) \ M(Bool, input_format_values_allow_data_after_semicolon, false, "For Values format: allow extra data after semicolon (used by client to interpret comments).", 0) \ M(Bool, input_format_avro_allow_missing_fields, false, "For Avro/AvroConfluent format: when field is not found in schema use default value instead of error", 0) \ + M(Bool, cast_keys_to_string_from_json, false, "Either to cast string to int in enumerating json or not", 0) \ /** This setting is obsolete and do nothing, left for compatibility reasons. */ \ M(Bool, input_format_avro_null_as_default, false, "For Avro/AvroConfluent format: insert default in case of null and non Nullable column", 0) \ M(UInt64, format_binary_max_string_size, 1_GiB, "The maximum allowed size for String in RowBinary format. It prevents allocating large amount of memory in case of corrupted data. 0 means there is no limit", 0) \ diff --git a/src/DataTypes/EnumValues.cpp b/src/DataTypes/EnumValues.cpp index a15136b9335..657bdfdbf6d 100644 --- a/src/DataTypes/EnumValues.cpp +++ b/src/DataTypes/EnumValues.cpp @@ -1,6 +1,9 @@ #include #include #include +#include "Core/Names.h" +#include +#include namespace DB @@ -52,7 +55,23 @@ void EnumValues::fillMaps() template T EnumValues::getValue(StringRef field_name, bool try_treat_as_id) const { - const auto it = name_to_value_map.find(field_name); + ContextPtr query_context; + if (CurrentThread::isInitialized()) + { + query_context = CurrentThread::get().getGlobalContext(); + } + + auto it = name_to_value_map.find(field_name); + if (!it && query_context && query_context->getSettingsRef().cast_keys_to_string_from_json) + { + for (const auto& item : name_to_value_map) + { + if (item.getValue().second == std::stoi(field_name.toString())) + { + it = name_to_value_map.find(item.getKey()); + } + } + } if (!it) { /// It is used in CSV and TSV input formats. If we fail to find given string in diff --git a/tests/queries/0_stateless/03202_enum_json_cast.reference b/tests/queries/0_stateless/03202_enum_json_cast.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/03202_enum_json_cast.sql b/tests/queries/0_stateless/03202_enum_json_cast.sql new file mode 100644 index 00000000000..543b78eef6a --- /dev/null +++ b/tests/queries/0_stateless/03202_enum_json_cast.sql @@ -0,0 +1,10 @@ +SET cast_keys_to_string_from_json=1; +DROP TABLE test; +CREATE TABLE test +( + `answer` Enum8('Question' = 1, 'Answer' = 2, 'Wiki' = 3, 'TagWikiExcerpt' = 4, 'TagWiki' = 5, 'ModeratorNomination' = 6, 'WikiPlaceholder' = 7, 'PrivilegeWiki' = 8) +) +ENGINE = Memory; +INSERT INTO test FORMAT JSONEachRow {"answer": 1}; +INSERT INTO test FORMAT JSONEachRow {"answer": "2"}; +SELECT * FROM test;