From 4999816ae62a0f64b2b4ebc945de0cd0573b69e2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 28 Jun 2025 14:19:48 +0800 Subject: [PATCH] branch-2.1: [fix](map) fix createMap function #52231 (#52401) Cherry-picked from #52231 Co-authored-by: amory --- .../functions/scalar/CreateMap.java | 20 +++++- .../scalar_function/Map.out | 69 +++++++++++++++++++ .../scalar_function/Map.groovy | 27 ++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CreateMap.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CreateMap.java index fe966f4e38..da18ad6480 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CreateMap.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CreateMap.java @@ -24,11 +24,13 @@ import org.apache.doris.nereids.trees.expressions.functions.AlwaysNotNullable; import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; import org.apache.doris.nereids.trees.expressions.functions.ExpressionTrait; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.MapType; import com.google.common.collect.ImmutableList; +import java.util.ArrayList; import java.util.List; /** @@ -51,7 +53,23 @@ public class CreateMap extends ScalarFunction @Override public DataType getDataType() { if (arity() >= 2) { - return MapType.of(child(0).getDataType(), child(1).getDataType()); + // use Array function to get the common key and value type + // first collect all key types in odd position, and value types in even position + // then get the common type of key and value + List keyExpressions = new ArrayList<>(); + List valueExpressions = new ArrayList<>(); + for (int i = 0; i < children.size(); i++) { + if (i % 2 == 0) { + keyExpressions.add(children.get(i)); + } else { + valueExpressions.add(children.get(i)); + } + } + Array keyArr = new Array().withChildren(keyExpressions); + DataType keyType = ((ArrayType) keyArr.getDataType()).getItemType(); + Array valueArr = new Array().withChildren(valueExpressions); + DataType valueType = ((ArrayType) valueArr.getDataType()).getItemType(); + return MapType.of(keyType, valueType); } return MapType.SYSTEM_DEFAULT; } diff --git a/regression-test/data/nereids_function_p0/scalar_function/Map.out b/regression-test/data/nereids_function_p0/scalar_function/Map.out index a272d3cf2c..1da11a27f9 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/Map.out +++ b/regression-test/data/nereids_function_p0/scalar_function/Map.out @@ -3653,3 +3653,72 @@ false false false +-- !map_constructor_basic -- +{"name":"John", "age":"30", "city":"NY", "zip":"10001"} + +-- !map_constructor_string_values -- +{"key1":"value1", "key2":"value2", "key3":"value3"} + +-- !map_constructor_mixed_types -- +{"string_key":"string_value", "int_key":"12345", "float_key":"3.14159"} + +-- !map_constructor_large_numbers -- +{"small":100, "medium":10000, "large":100000, "very_large":1000000} + +-- !map_constructor_json_strings -- +{"{"name":"John"}":"{"age":30}", "{"city":"NY"}":"{"zip":10001}"} + +-- !map_constructor_nested_json -- +{"{"user":{"name":"John","age":30}}":"{"address":{"city":"NY","zip":10001}}"} + +-- !map_constructor_special_chars -- +{"key with spaces":"value with spaces", "key-with-dashes":"value-with-dashes"} + +-- !map_constructor_unicode -- +{"中文键":"中文值", "key_中文":"value_中文"} + +-- !map_constructor_empty_strings -- +{"empty_key":"", "key_empty":"value", "empty_both":""} + +-- !map_constructor_null_values -- +{"null_key":null, "key_null":"value", "both_null":null} + +-- !map_constructor_boolean_values -- +{"true_key":1, "false_key":0, "mixed_key":123} + +-- !map_constructor_decimal_values -- +{"decimal_key":123.456, "integer_key":789.000, "mixed_decimal":10001.000} + +-- !map_constructor_date_values -- +{"date_key":"2023-01-01", "datetime_key":"2023-01-01 12:00:00", "string_key":"text"} + +-- !map_constructor_array_values -- +{"array_key":"[1,2,3]", "string_key":"text", "number_key":"10001"} + +-- !map_constructor_object_values -- +{"object_key":"{"nested":"value"}", "simple_key":"simple_value"} + +-- !map_constructor_long_strings -- +{"long_key":"this is a very long string value that should not be truncated", "short_key":"short"} + +-- !map_constructor_numeric_strings -- +{"numeric_string":"10001", "actual_number":"10001", "mixed":"text"} + +-- !map_constructor_escape_chars -- +{"quoted_key":"value with "quotes"", "backslash_key":"value with backslash"} + +-- !map_constructor_whitespace -- +{" spaced_key ":" spaced_value ", "normal_key":"normal_value"} + +-- !sql -- +{"{"name":"John"}":"{"age":30}", "{"city":"NY"}":"{"zip":10001}"} + +-- !sql -- +{"zip":10001, "code":10002, "number":10003} + +-- !sql -- +{"postal_code":10001, "area_code":10002, "zip_plus_4":10003} + +-- !sql -- +{"{"zip":10001}":"{"city":"NY"}", "{"code":10002}":"{"state":"NY"}"} + diff --git a/regression-test/suites/nereids_function_p0/scalar_function/Map.groovy b/regression-test/suites/nereids_function_p0/scalar_function/Map.groovy index f8b28c8da9..301841e8a4 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/Map.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/Map.groovy @@ -286,5 +286,32 @@ suite("nereids_scalar_fn_map") { order_qt_map_contains_value_tint_date_notnull """ select map_contains_value(km_tint_date, kdt) from fn_test_not_nullable """ order_qt_map_contains_value_tint_dtm_notnull """ select map_contains_value(km_tint_dtm, kdtm) from fn_test_not_nullable """ + // map constructor function tests - bugfix for CreateMap with args not deducible + sql """ set enable_fold_constant_by_be=true;""" + sql """ set debug_skip_fold_constant=false;""" + qt_map_constructor_basic "select map('name', 'John', 'age', 30, 'city', 'NY', 'zip', 10001)" + qt_map_constructor_string_values "select map('key1', 'value1', 'key2', 'value2', 'key3', 'value3')" + qt_map_constructor_mixed_types "select map('string_key', 'string_value', 'int_key', 12345, 'float_key', 3.14159)" + qt_map_constructor_large_numbers "select map('small', 100, 'medium', 10000, 'large', 100000, 'very_large', 1000000)" + qt_map_constructor_json_strings "select map('{\"name\":\"John\"}', '{\"age\":30}', '{\"city\":\"NY\"}', '{\"zip\":10001}')" + qt_map_constructor_nested_json "select map('{\"user\":{\"name\":\"John\",\"age\":30}}', '{\"address\":{\"city\":\"NY\",\"zip\":10001}}')" + qt_map_constructor_special_chars "select map('key with spaces', 'value with spaces', 'key-with-dashes', 'value-with-dashes')" + qt_map_constructor_unicode "select map('中文键', '中文值', 'key_中文', 'value_中文')" + qt_map_constructor_empty_strings "select map('empty_key', '', 'key_empty', 'value', 'empty_both', '')" + qt_map_constructor_null_values "select map('null_key', null, 'key_null', 'value', 'both_null', null)" + qt_map_constructor_boolean_values "select map('true_key', true, 'false_key', false, 'mixed_key', 123)" + qt_map_constructor_decimal_values "select map('decimal_key', 123.456, 'integer_key', 789, 'mixed_decimal', 10001.0)" + qt_map_constructor_date_values "select map('date_key', '2023-01-01', 'datetime_key', '2023-01-01 12:00:00', 'string_key', 'text')" + qt_map_constructor_array_values "select map('array_key', '[1,2,3]', 'string_key', 'text', 'number_key', 10001)" + qt_map_constructor_object_values "select map('object_key', '{\"nested\":\"value\"}', 'simple_key', 'simple_value')" + qt_map_constructor_long_strings "select map('long_key', 'this is a very long string value that should not be truncated', 'short_key', 'short')" + qt_map_constructor_numeric_strings "select map('numeric_string', '10001', 'actual_number', 10001, 'mixed', 'text')" + qt_map_constructor_escape_chars "select map('quoted_key', 'value with \"quotes\"', 'backslash_key', 'value with \\ backslash')" + qt_map_constructor_whitespace "select map(' spaced_key ', ' spaced_value ', 'normal_key', 'normal_value')" + + qt_sql "select map('{\"name\":\"John\"}', '{\"age\":30}', '{\"city\":\"NY\"}', '{\"zip\":10001}')" + qt_sql "select map('zip', 10001, 'code', 10002, 'number', 10003)" + qt_sql "select map('postal_code', 10001, 'area_code', 10002, 'zip_plus_4', 10003)" + qt_sql "select map('{\"zip\":10001}', '{\"city\":\"NY\"}', '{\"code\":10002}', '{\"state\":\"NY\"}')" } \ No newline at end of file