From e9909ca3b90b99a0bda81b4c019f37b6321da9b3 Mon Sep 17 00:00:00 2001 From: robot-clickhouse Date: Tue, 1 Oct 2024 15:10:51 +0000 Subject: [PATCH] Backport #69291 to 24.8: Fix insertion of incomplete type into Dynamic during deserialization --- .../Serializations/SerializationDynamic.cpp | 12 +++++++----- ...3231_dynamic_incomplete_type_insert_bug.reference | 5 +++++ .../03231_dynamic_incomplete_type_insert_bug.sql | 11 +++++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 tests/queries/0_stateless/03231_dynamic_incomplete_type_insert_bug.reference create mode 100644 tests/queries/0_stateless/03231_dynamic_incomplete_type_insert_bug.sql diff --git a/src/DataTypes/Serializations/SerializationDynamic.cpp b/src/DataTypes/Serializations/SerializationDynamic.cpp index 32964e17bce..18a75918499 100644 --- a/src/DataTypes/Serializations/SerializationDynamic.cpp +++ b/src/DataTypes/Serializations/SerializationDynamic.cpp @@ -566,7 +566,6 @@ static void deserializeTextImpl( const auto & variant_info = dynamic_column.getVariantInfo(); const auto & variant_types = assert_cast(*variant_info.variant_type).getVariants(); String field = read_field(istr); - auto field_buf = std::make_unique(field); JSONInferenceInfo json_info; auto variant_type = tryInferDataTypeByEscapingRule(field, settings, escaping_rule, &json_info); if (escaping_rule == FormatSettings::EscapingRule::JSON) @@ -580,7 +579,7 @@ static void deserializeTextImpl( size_t shared_variant_discr = dynamic_column.getSharedVariantDiscriminator(); for (size_t i = 0; i != variant_types.size(); ++i) { - field_buf = std::make_unique(field); + auto field_buf = std::make_unique(field); if (i != shared_variant_discr && deserializeVariant( variant_column, @@ -591,21 +590,24 @@ static void deserializeTextImpl( return; } + /// We cannot insert value with incomplete type, insert it as String. variant_type = std::make_shared(); /// To be able to deserialize field as String with Quoted escaping rule, it should be quoted. if (escaping_rule == FormatSettings::EscapingRule::Quoted && (field.size() < 2 || field.front() != '\'' || field.back() != '\'')) field = "'" + field + "'"; } - else if (dynamic_column.addNewVariant(variant_type, variant_type->getName())) + + if (dynamic_column.addNewVariant(variant_type, variant_type->getName())) { + auto field_buf = std::make_unique(field); auto discr = variant_info.variant_name_to_discriminator.at(variant_type->getName()); deserializeVariant(dynamic_column.getVariantColumn(), dynamic_column.getVariantSerialization(variant_type), discr, *field_buf, deserialize_variant); return; } - /// We couldn't infer type or add new variant. Insert it into shared variant. + /// We couldn't add new variant. Insert it into shared variant. auto tmp_variant_column = variant_type->createColumn(); - field_buf = std::make_unique(field); + auto field_buf = std::make_unique(field); auto variant_type_name = variant_type->getName(); deserialize_variant(*dynamic_column.getVariantSerialization(variant_type, variant_type_name), *tmp_variant_column, *field_buf); dynamic_column.insertValueIntoSharedVariant(*tmp_variant_column, variant_type, variant_type_name, 0); diff --git a/tests/queries/0_stateless/03231_dynamic_incomplete_type_insert_bug.reference b/tests/queries/0_stateless/03231_dynamic_incomplete_type_insert_bug.reference new file mode 100644 index 00000000000..e6a32acd0a0 --- /dev/null +++ b/tests/queries/0_stateless/03231_dynamic_incomplete_type_insert_bug.reference @@ -0,0 +1,5 @@ +[] +[] +[['saw']] +['[]'] +['had',1] diff --git a/tests/queries/0_stateless/03231_dynamic_incomplete_type_insert_bug.sql b/tests/queries/0_stateless/03231_dynamic_incomplete_type_insert_bug.sql new file mode 100644 index 00000000000..a6fc2e66480 --- /dev/null +++ b/tests/queries/0_stateless/03231_dynamic_incomplete_type_insert_bug.sql @@ -0,0 +1,11 @@ +SET allow_experimental_dynamic_type = 1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (c0 Array(Dynamic)) ENGINE = MergeTree() ORDER BY tuple(); +INSERT INTO t1 (c0) VALUES ([]); +INSERT INTO t1 (c0) VALUES ([[]]), (['had', 1]); +INSERT INTO t1 (c0) VALUES ([['saw']]); +INSERT INTO t1 (c0) VALUES ([]); +OPTIMIZE TABLE t1 final; +SELECT * FROM t1 ORDER BY ALL; +DROP TABLE t1; +