diff --git a/be/src/vec/CMakeLists.txt b/be/src/vec/CMakeLists.txt index aa9f875385b04c..4db743459c2f86 100644 --- a/be/src/vec/CMakeLists.txt +++ b/be/src/vec/CMakeLists.txt @@ -187,6 +187,7 @@ set(VEC_FILES functions/array/function_array_apply.cpp functions/array/function_array_concat.cpp functions/array/function_array_pushfront.cpp + functions/function_map.cpp exprs/table_function/vexplode_json_array.cpp functions/math.cpp functions/function_bitmap.cpp diff --git a/be/src/vec/columns/column_map.h b/be/src/vec/columns/column_map.h index f6f8ebec504373..9d828a2794a559 100644 --- a/be/src/vec/columns/column_map.h +++ b/be/src/vec/columns/column_map.h @@ -146,12 +146,26 @@ class ColumnMap final : public COWHelper { const IColumn& get_keys() const { return *keys_column; } IColumn& get_keys() { return *keys_column; } + const ColumnPtr get_keys_array_ptr() const { + return ColumnArray::create(keys_column, offsets_column); + } + ColumnPtr get_keys_array_ptr() { return ColumnArray::create(keys_column, offsets_column); } + const ColumnPtr& get_values_ptr() const { return values_column; } ColumnPtr& get_values_ptr() { return values_column; } const IColumn& get_values() const { return *values_column; } IColumn& get_values() { return *values_column; } + const ColumnPtr get_values_array_ptr() const { + return ColumnArray::create(values_column, offsets_column); + } + ColumnPtr get_values_array_ptr() { return ColumnArray::create(values_column, offsets_column); } + + size_t ALWAYS_INLINE size_at(ssize_t i) const { + return get_offsets()[i] - get_offsets()[i - 1]; + } + private: friend class COWHelper; @@ -160,9 +174,6 @@ class ColumnMap final : public COWHelper { WrappedPtr offsets_column; // offset size_t ALWAYS_INLINE offset_at(ssize_t i) const { return get_offsets()[i - 1]; } - size_t ALWAYS_INLINE size_at(ssize_t i) const { - return get_offsets()[i] - get_offsets()[i - 1]; - } ColumnMap(MutableColumnPtr&& keys, MutableColumnPtr&& values, MutableColumnPtr&& offsets); diff --git a/be/src/vec/functions/function_map.cpp b/be/src/vec/functions/function_map.cpp new file mode 100644 index 00000000000000..9cb5c5898d2af2 --- /dev/null +++ b/be/src/vec/functions/function_map.cpp @@ -0,0 +1,330 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "vec/columns/column_array.h" +#include "vec/columns/column_const.h" +#include "vec/columns/column_map.h" +#include "vec/data_types/data_type.h" +#include "vec/data_types/data_type_array.h" +#include "vec/data_types/data_type_map.h" +#include "vec/data_types/data_type_nullable.h" +#include "vec/data_types/data_type_number.h" +#include "vec/data_types/get_least_supertype.h" +#include "vec/functions/array/function_array_index.h" +#include "vec/functions/function.h" +#include "vec/functions/function_helpers.h" +#include "vec/functions/simple_function_factory.h" + +namespace doris::vectorized { + +// construct a map +// map(key1, value2, key2, value2) -> {key1: value2, key2: value2} +class FunctionMap : public IFunction { +public: + static constexpr auto name = "map"; + static FunctionPtr create() { return std::make_shared(); } + + /// Get function name. + String get_name() const override { return name; } + + bool is_variadic() const override { return true; } + + bool use_default_implementation_for_nulls() const override { return false; } + + size_t get_number_of_arguments() const override { return 0; } + + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { + DCHECK(arguments.size() % 2 == 0) + << "function: " << get_name() << ", arguments should not be even number"; + + DataTypes key_types; + DataTypes val_types; + for (size_t i = 0; i < arguments.size(); i += 2) { + key_types.push_back(arguments[i]); + val_types.push_back(arguments[i + 1]); + } + + DataTypePtr key_type; + DataTypePtr val_type; + get_least_supertype(key_types, &key_type); + get_least_supertype(val_types, &val_type); + + return std::make_shared(make_nullable(key_type), make_nullable(val_type)); + } + + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + size_t result, size_t input_rows_count) override { + DCHECK(arguments.size() % 2 == 0) + << "function: " << get_name() << ", arguments should not be even number"; + + size_t num_element = arguments.size(); + + auto result_col = block.get_by_position(result).type->create_column(); + auto map_column = typeid_cast(result_col.get()); + if (!map_column) { + return Status::RuntimeError("unsupported types for function {} return {}", get_name(), + block.get_by_position(result).type->get_name()); + } + + // map keys column + auto& result_col_map_keys_data = map_column->get_keys(); + result_col_map_keys_data.reserve(input_rows_count * num_element / 2); + // map values column + auto& result_col_map_vals_data = map_column->get_values(); + result_col_map_vals_data.reserve(input_rows_count * num_element / 2); + // map offsets column + auto& result_col_map_offsets = map_column->get_offsets(); + result_col_map_offsets.resize(input_rows_count); + + // convert to nullable column + for (size_t i = 0; i < num_element; ++i) { + auto& col = block.get_by_position(arguments[i]).column; + col = col->convert_to_full_column_if_const(); + bool is_nullable = i % 2 == 0 ? result_col_map_keys_data.is_nullable() + : result_col_map_vals_data.is_nullable(); + if (is_nullable && !col->is_nullable()) { + col = ColumnNullable::create(col, ColumnUInt8::create(col->size(), 0)); + } + } + + // insert value into array + ColumnArray::Offset64 offset = 0; + for (size_t row = 0; row < input_rows_count; ++row) { + for (size_t i = 0; i < num_element; i += 2) { + result_col_map_keys_data.insert_from(*block.get_by_position(arguments[i]).column, + row); + result_col_map_vals_data.insert_from( + *block.get_by_position(arguments[i + 1]).column, row); + } + offset += num_element / 2; + result_col_map_offsets[row] = offset; + } + block.replace_by_position(result, std::move(result_col)); + return Status::OK(); + } +}; + +class FunctionMapSize : public IFunction { +public: + static constexpr auto name = "map_size"; + static FunctionPtr create() { return std::make_shared(); } + + /// Get function name. + String get_name() const override { return name; } + + bool is_variadic() const override { return false; } + + size_t get_number_of_arguments() const override { return 1; } + + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { + DataTypePtr datatype = arguments[0]; + if (datatype->is_nullable()) { + datatype = assert_cast(datatype.get())->get_nested_type(); + } + DCHECK(is_map(datatype)) << "first argument for function: " << name + << " should be DataTypeMap"; + return std::make_shared(); + } + + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + size_t result, size_t input_rows_count) override { + auto left_column = + block.get_by_position(arguments[0]).column->convert_to_full_column_if_const(); + const ColumnMap* map_column = nullptr; + // const UInt8* map_null_map = nullptr; + if (left_column->is_nullable()) { + auto nullable_column = reinterpret_cast(left_column.get()); + map_column = check_and_get_column(nullable_column->get_nested_column()); + // map_null_map = nullable_column->get_null_map_column().get_data().data(); + } else { + map_column = check_and_get_column(*left_column.get()); + } + if (!map_column) { + return Status::RuntimeError("unsupported types for function {}({})", get_name(), + block.get_by_position(arguments[0]).type->get_name()); + } + + auto dst_column = ColumnInt64::create(input_rows_count); + auto& dst_data = dst_column->get_data(); + + for (size_t i = 0; i < map_column->size(); i++) { + dst_data[i] = map_column->size_at(i); + } + + block.replace_by_position(result, std::move(dst_column)); + return Status::OK(); + } +}; + +template +class FunctionMapContains : public IFunction { +public: + static constexpr auto name = is_key ? "map_contains_key" : "map_contains_value"; + static FunctionPtr create() { return std::make_shared(); } + + /// Get function name. + String get_name() const override { return name; } + + bool is_variadic() const override { return false; } + + size_t get_number_of_arguments() const override { return 2; } + + bool use_default_implementation_for_nulls() const override { + return array_contains.use_default_implementation_for_nulls(); + } + + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { + DataTypePtr datatype = arguments[0]; + if (datatype->is_nullable()) { + datatype = assert_cast(datatype.get())->get_nested_type(); + } + DCHECK(is_map(datatype)) << "first argument for function: " << name + << " should be DataTypeMap"; + return make_nullable(std::make_shared>()); + } + + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + size_t result, size_t input_rows_count) override { + // backup original argument 0 + auto orig_arg0 = block.get_by_position(arguments[0]); + auto left_column = + block.get_by_position(arguments[0]).column->convert_to_full_column_if_const(); + const ColumnMap* map_column = nullptr; + ColumnPtr nullmap_column = nullptr; + if (left_column->is_nullable()) { + auto nullable_column = reinterpret_cast(left_column.get()); + map_column = check_and_get_column(nullable_column->get_nested_column()); + nullmap_column = nullable_column->get_null_map_column_ptr(); + } else { + map_column = check_and_get_column(*left_column.get()); + } + if (!map_column) { + return Status::RuntimeError("unsupported types for function {}({})", get_name(), + block.get_by_position(arguments[0]).type->get_name()); + } + + DataTypePtr datatype = block.get_by_position(arguments[0]).type; + if (datatype->is_nullable()) { + datatype = assert_cast(datatype.get())->get_nested_type(); + } + const auto datatype_map = static_cast(datatype.get()); + if constexpr (is_key) { + const auto& array_column = map_column->get_keys_array_ptr(); + const auto datatype_array = + std::make_shared(datatype_map->get_key_type()); + if (nullmap_column) { + block.get_by_position(arguments[0]) = { + ColumnNullable::create(array_column, nullmap_column), + make_nullable(datatype_array), + block.get_by_position(arguments[0]).name + ".keys"}; + } else { + block.get_by_position(arguments[0]) = { + array_column, datatype_array, + block.get_by_position(arguments[0]).name + ".keys"}; + } + } else { + const auto& array_column = map_column->get_values_array_ptr(); + const auto datatype_array = + std::make_shared(datatype_map->get_value_type()); + if (nullmap_column) { + block.get_by_position(arguments[0]) = { + ColumnNullable::create(array_column, nullmap_column), + make_nullable(datatype_array), + block.get_by_position(arguments[0]).name + ".values"}; + } else { + block.get_by_position(arguments[0]) = { + array_column, datatype_array, + block.get_by_position(arguments[0]).name + ".values"}; + } + } + + RETURN_IF_ERROR( + array_contains.execute_impl(context, block, arguments, result, input_rows_count)); + + // restore original argument 0 + block.get_by_position(arguments[0]) = orig_arg0; + return Status::OK(); + } + +private: + FunctionArrayIndex> array_contains; +}; + +template +class FunctionMapEntries : public IFunction { +public: + static constexpr auto name = is_key ? "map_keys" : "map_values"; + static FunctionPtr create() { return std::make_shared(); } + + /// Get function name. + String get_name() const override { return name; } + + bool is_variadic() const override { return false; } + + size_t get_number_of_arguments() const override { return 1; } + + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { + DataTypePtr datatype = arguments[0]; + if (datatype->is_nullable()) { + datatype = assert_cast(datatype.get())->get_nested_type(); + } + DCHECK(is_map(datatype)) << "first argument for function: " << name + << " should be DataTypeMap"; + const auto datatype_map = static_cast(datatype.get()); + if (is_key) { + return std::make_shared(datatype_map->get_key_type()); + } else { + return std::make_shared(datatype_map->get_value_type()); + } + } + + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + size_t result, size_t input_rows_count) override { + auto left_column = + block.get_by_position(arguments[0]).column->convert_to_full_column_if_const(); + const ColumnMap* map_column = nullptr; + if (left_column->is_nullable()) { + auto nullable_column = reinterpret_cast(left_column.get()); + map_column = check_and_get_column(nullable_column->get_nested_column()); + } else { + map_column = check_and_get_column(*left_column.get()); + } + if (!map_column) { + return Status::RuntimeError("unsupported types for function {}({})", get_name(), + block.get_by_position(arguments[0]).type->get_name()); + } + + if constexpr (is_key) { + block.replace_by_position(result, map_column->get_keys_array_ptr()); + } else { + block.replace_by_position(result, map_column->get_values_array_ptr()); + } + + return Status::OK(); + } +}; + +void register_function_map(SimpleFunctionFactory& factory) { + factory.register_function(); + factory.register_function(); + factory.register_function>(); + factory.register_function>(); + factory.register_function>(); + factory.register_function>(); +} + +} // namespace doris::vectorized diff --git a/be/src/vec/functions/simple_function_factory.h b/be/src/vec/functions/simple_function_factory.h index 9ab060d11a5b7c..8a9213eae02bea 100644 --- a/be/src/vec/functions/simple_function_factory.h +++ b/be/src/vec/functions/simple_function_factory.h @@ -81,6 +81,7 @@ void register_function_convert_tz(SimpleFunctionFactory& factory); void register_function_least_greast(SimpleFunctionFactory& factory); void register_function_fake(SimpleFunctionFactory& factory); void register_function_array(SimpleFunctionFactory& factory); +void register_function_map(SimpleFunctionFactory& factory); void register_function_geo(SimpleFunctionFactory& factory); void register_function_multi_string_position(SimpleFunctionFactory& factory); void register_function_multi_string_search(SimpleFunctionFactory& factory); @@ -230,6 +231,7 @@ class SimpleFunctionFactory { register_function_regexp_extract(instance); register_function_hex_variadic(instance); register_function_array(instance); + register_function_map(instance); register_function_geo(instance); register_function_url(instance); register_function_multi_string_position(instance); diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java b/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java index a28f3c030236b1..938722528a19e2 100644 --- a/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java +++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java @@ -101,14 +101,18 @@ public boolean hasTemplateType() { @Override public Type specializeTemplateType(Type specificType, Map specializedTypeMap, boolean useSpecializedType) throws TypeException { - if (!(specificType instanceof ArrayType)) { + ArrayType specificArrayType = null; + if (specificType instanceof ArrayType) { + specificArrayType = (ArrayType) specificType; + } else if (!useSpecializedType) { throw new TypeException(specificType + " is not ArrayType"); } - ArrayType o = (ArrayType) specificType; Type newItemType = itemType; if (itemType.hasTemplateType()) { - newItemType = itemType.specializeTemplateType(o.itemType, specializedTypeMap, useSpecializedType); + newItemType = itemType.specializeTemplateType( + specificArrayType != null ? specificArrayType.itemType : specificType, + specializedTypeMap, useSpecializedType); } return new ArrayType(newItemType); diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java b/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java index e72df777100691..a1000b90582eab 100644 --- a/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java +++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java @@ -130,24 +130,29 @@ public boolean hasTemplateType() { @Override public Type specializeTemplateType(Type specificType, Map specializedTypeMap, boolean useSpecializedType) throws TypeException { - if (!(specificType instanceof MapType)) { + MapType specificMapType = null; + if (specificType instanceof MapType) { + specificMapType = (MapType) specificType; + } else if (!useSpecializedType) { throw new TypeException(specificType + " is not MapType"); } - MapType specificMapType = (MapType) specificType; Type newKeyType = keyType; if (keyType.hasTemplateType()) { newKeyType = keyType.specializeTemplateType( - specificMapType.keyType, specializedTypeMap, useSpecializedType); + specificMapType != null ? specificMapType.keyType : specificType, + specializedTypeMap, useSpecializedType); } Type newValueType = valueType; if (valueType.hasTemplateType()) { newValueType = valueType.specializeTemplateType( - specificMapType.valueType, specializedTypeMap, useSpecializedType); + specificMapType != null ? specificMapType.valueType : specificType, + specializedTypeMap, useSpecializedType); } Type newMapType = new MapType(newKeyType, newValueType); - if (Type.canCastTo(specificType, newMapType)) { + if (Type.canCastTo(specificType, newMapType) + || (useSpecializedType && !(specificType instanceof MapType))) { return newMapType; } else { throw new TypeException(specificType + " can not cast to specialize type " + newMapType); diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java index 30b40088dbfbe2..87bb96ccb08923 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java @@ -28,6 +28,7 @@ import org.apache.doris.catalog.Env; import org.apache.doris.catalog.Function; import org.apache.doris.catalog.FunctionSet; +import org.apache.doris.catalog.MapType; import org.apache.doris.catalog.ScalarFunction; import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; @@ -1396,6 +1397,12 @@ && collectChildReturnTypes()[0].isDecimalV3()) { for (int i = 0; i < argTypes.length - orderByElements.size(); ++i) { // For varargs, we must compare with the last type in callArgs.argTypes. int ix = Math.min(args.length - 1, i); + // map varargs special case map(key_type, value_type, ...) + if (i >= args.length && i >= 2 && args.length >= 2 + && fnName.getFunction().equalsIgnoreCase("map")) { + ix = i % 2 == 0 ? 0 : 1; + } + if ((fnName.getFunction().equalsIgnoreCase("money_format") || fnName.getFunction() .equalsIgnoreCase("histogram") || fnName.getFunction().equalsIgnoreCase("hist")) @@ -1515,6 +1522,10 @@ private void analyzeNestedFunction() { if (children.size() > 0) { this.type = new ArrayType(children.get(0).getType()); } + } else if (fnName.getFunction().equalsIgnoreCase("map")) { + if (children.size() > 1) { + this.type = new MapType(children.get(0).getType(), children.get(1).getType()); + } } else if (fnName.getFunction().equalsIgnoreCase("if")) { if (children.get(1).getType().isArrayType() && ( ((ArrayType) children.get(1).getType()).getItemType().isDecimalV3() diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index d0c82f3fc60773..b575dae5884970 100644 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -64,6 +64,16 @@ [['bitnot'], 'BIGINT', ['BIGINT'], ''], [['bitnot'], 'LARGEINT', ['LARGEINT'], ''], + # map functions + [['map'], 'MAP', ['K', 'V', '...'], 'ALWAYS_NOT_NULLABLE', ['K', 'V']], + [['element_at', '%element_extract%'], 'V', ['MAP', 'K'], 'ALWAYS_NULLABLE', ['K', 'V']], + [['size', 'map_size'], 'BIGINT', ['MAP'], '', ['K', 'V']], + [['map_contains_key'], 'BOOLEAN', ['MAP', 'K'], 'ALWAYS_NULLABLE', ['K', 'V']], + [['map_contains_value'], 'BOOLEAN', ['MAP', 'V'], 'ALWAYS_NULLABLE', ['K', 'V']], + #[['map_contains_key_like'], 'BOOLEAN', ['MAP', 'K'], '', ['K', 'V']], + [['map_keys'], 'ARRAY', ['MAP'], '', ['K', 'V']], + [['map_values'], 'ARRAY', ['MAP'], '', ['K', 'V']], + # array functions [['array'], 'ARRAY', ['BOOLEAN', '...'], 'ALWAYS_NOT_NULLABLE'], [['array'], 'ARRAY', ['TINYINT', '...'], 'ALWAYS_NOT_NULLABLE'], @@ -103,9 +113,6 @@ [['element_at', '%element_extract%'], 'VARCHAR', ['ARRAY_VARCHAR', 'BIGINT'], 'ALWAYS_NULLABLE'], [['element_at', '%element_extract%'], 'STRING', ['ARRAY_STRING', 'BIGINT'], 'ALWAYS_NULLABLE'], - # map element - [['element_at', '%element_extract%'], 'V', ['MAP', 'K'], 'ALWAYS_NULLABLE', ['K', 'V']], - [['arrays_overlap'], 'BOOLEAN', ['ARRAY_BOOLEAN', 'ARRAY_BOOLEAN'], 'ALWAYS_NULLABLE'], [['arrays_overlap'], 'BOOLEAN', ['ARRAY_TINYINT', 'ARRAY_TINYINT'], 'ALWAYS_NULLABLE'], [['arrays_overlap'], 'BOOLEAN', ['ARRAY_SMALLINT', 'ARRAY_SMALLINT'], 'ALWAYS_NULLABLE'], diff --git a/regression-test/data/load_p0/stream_load/test_map_load_and_function.out b/regression-test/data/load_p0/stream_load/test_map_load_and_function.out index 94ef70fdeaa5e6..70f7d3c7d19b5b 100644 --- a/regression-test/data/load_p0/stream_load/test_map_load_and_function.out +++ b/regression-test/data/load_p0/stream_load/test_map_load_and_function.out @@ -35,6 +35,1003 @@ 17 \N 18 130 +-- !select2 -- +1 \N +2 {" 11amory ":23, "beat":20, " clever ":66} +3 {"k1":31, "k2":300} +4 {} +5 \N +6 {"k1":41, "k2":400} +7 {" 33,amory ":2, " bet ":20, " cler ":26} +8 {} +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} +10 {} +11 \N +12 {"k3":23, null:20, "k4":null} +13 {"null":1} +15 {"":2, "k2":0} +16 {null:null} +17 \N +18 {"k1":100, "k2":130} + +-- !select_map1 -- +{"k11":1000, "k22":2000} + +-- !select_map2 -- +{1000:"k11", 2000:"k22"} + +-- !select_element1 -- +1000 + +-- !select_element2 -- +2000 + +-- !select_element3 -- +\N + +-- !select_element4 -- +\N + +-- !select_element5 -- +k11 + +-- !select_element6 -- +k22 + +-- !select_element7 -- +\N + +-- !select_element8 -- +\N + +-- !select_element101 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} 31 +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} 41 +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} 100 + +-- !select_element102 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} 300 +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} 400 +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} 0 +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} 130 + +-- !select_element103 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} 23 +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element104 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} 20 +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element105 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} 66 +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element106 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} 2 +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element107 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} 20 +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element108 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} 26 +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element109 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} 2 +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element110 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} 90 +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element111 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} 1 +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element112 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} 20 +13 {"null":1} \N +15 {"":2, "k2":0} 2 +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element113 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_element114 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} \N +3 {"k1":31, "k2":300} \N +4 {} \N +5 \N \N +6 {"k1":41, "k2":400} \N +7 {" 33,amory ":2, " bet ":20, " cler ":26} \N +8 {} \N +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N +10 {} \N +11 \N \N +12 {"k3":23, null:20, "k4":null} \N +13 {"null":1} \N +15 {"":2, "k2":0} \N +16 {null:null} \N +17 \N \N +18 {"k1":100, "k2":130} \N + +-- !select_map_size1 -- +2 + +-- !select_map_size2 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} 3 +3 {"k1":31, "k2":300} 2 +4 {} 0 +5 \N \N +6 {"k1":41, "k2":400} 2 +7 {" 33,amory ":2, " bet ":20, " cler ":26} 3 +8 {} 0 +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} 3 +10 {} 0 +11 \N \N +12 {"k3":23, null:20, "k4":null} 3 +13 {"null":1} 1 +15 {"":2, "k2":0} 2 +16 {null:null} 1 +17 \N \N +18 {"k1":100, "k2":130} 2 + +-- !select_map_contains_key1 -- +true + +-- !select_map_contains_key2 -- +true + +-- !select_map_contains_key3 -- +false + +-- !select_map_contains_key4 -- +false + +-- !select_map_contains_key5 -- +false + +-- !select_map_contains_key101 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} true +4 {} false +5 \N \N +6 {"k1":41, "k2":400} true +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} true + +-- !select_map_contains_key102 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} true +4 {} false +5 \N \N +6 {"k1":41, "k2":400} true +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} true +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} true + +-- !select_map_contains_key103 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} true +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key104 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} true +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key105 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} true +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key106 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} true +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key107 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} true +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key108 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} true +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key109 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} true +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key110 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} true +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key111 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} true +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key112 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} true +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key113 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} true +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} true +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_key114 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value1 -- +true + +-- !select_map_contains_value2 -- +true + +-- !select_map_contains_value3 -- +false + +-- !select_map_contains_value4 -- +false + +-- !select_map_contains_value101 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} true +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} true +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value102 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} true +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} true +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} true +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value103 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} true +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value104 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} true +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value105 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} true +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value106 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} true +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value107 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} true +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value108 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} true +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value109 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} true +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} true +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} true +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value110 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} true +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value111 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} true +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value112 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} true +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value113 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} true +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value114 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} true +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} true +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} true +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value115 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} true +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value116 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} false +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} false +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_contains_value117 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} false +3 {"k1":31, "k2":300} false +4 {} false +5 \N \N +6 {"k1":41, "k2":400} false +7 {" 33,amory ":2, " bet ":20, " cler ":26} false +8 {} false +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} false +10 {} false +11 \N \N +12 {"k3":23, null:20, "k4":null} true +13 {"null":1} false +15 {"":2, "k2":0} false +16 {null:null} true +17 \N \N +18 {"k1":100, "k2":130} false + +-- !select_map_keys1 -- +['k11', 'k22'] + +-- !select_map_keys2 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} [' 11amory ', 'beat', ' clever '] +3 {"k1":31, "k2":300} ['k1', 'k2'] +4 {} [] +5 \N \N +6 {"k1":41, "k2":400} ['k1', 'k2'] +7 {" 33,amory ":2, " bet ":20, " cler ":26} [' 33,amory ', ' bet ', ' cler '] +8 {} [] +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} [' 1,amy ', ' k2 ', ' k7 '] +10 {} [] +11 \N \N +12 {"k3":23, null:20, "k4":null} ['k3', NULL, 'k4'] +13 {"null":1} ['null'] +15 {"":2, "k2":0} ['', 'k2'] +16 {null:null} [NULL] +17 \N \N +18 {"k1":100, "k2":130} ['k1', 'k2'] + +-- !select_map_values1 -- +[1000, 2000] + +-- !select_map_values2 -- +1 \N \N +2 {" 11amory ":23, "beat":20, " clever ":66} [23, 20, 66] +3 {"k1":31, "k2":300} [31, 300] +4 {} [] +5 \N \N +6 {"k1":41, "k2":400} [41, 400] +7 {" 33,amory ":2, " bet ":20, " cler ":26} [2, 20, 26] +8 {} [] +9 {" 1,amy ":2, " k2 ":90, " k7 ":33} [2, 90, 33] +10 {} [] +11 \N \N +12 {"k3":23, null:20, "k4":null} [23, 20, NULL] +13 {"null":1} [1] +15 {"":2, "k2":0} [2, 0] +16 {null:null} [NULL] +17 \N \N +18 {"k1":100, "k2":130} [100, 130] + -- !select_m1 -- 1 100 200 \N @@ -49,3 +1046,4 @@ -- !select_m5 -- 1 100 200 \N + diff --git a/regression-test/suites/load_p0/stream_load/test_map_load_and_function.groovy b/regression-test/suites/load_p0/stream_load/test_map_load_and_function.groovy index 38e4d295ca1a5a..a328f61ec66bf1 100644 --- a/regression-test/suites/load_p0/stream_load/test_map_load_and_function.groovy +++ b/regression-test/suites/load_p0/stream_load/test_map_load_and_function.groovy @@ -72,6 +72,93 @@ suite("test_map_load_and_function", "p0") { // map element_at qt_select_m "SELECT id, m['k2'] FROM ${testTable} ORDER BY id" + // check result + qt_select2 "SELECT * FROM ${testTable} ORDER BY id" + + // map construct + qt_select_map1 "SELECT map('k11', 1000, 'k22', 2000)" + qt_select_map2 "SELECT map(1000, 'k11', 2000, 'k22')" + + // map element_at + qt_select_element1 "SELECT map('k11', 1000, 'k22', 2000)['k11']" + qt_select_element2 "SELECT map('k11', 1000, 'k22', 2000)['k22']" + qt_select_element3 "SELECT map('k11', 1000, 'k22', 2000)['nokey']" + qt_select_element4 "SELECT map('k11', 1000, 'k22', 2000)['']" + qt_select_element5 "SELECT map(1000, 'k11', 2000, 'k22')[1000]" + qt_select_element6 "SELECT map(1000, 'k11', 2000, 'k22')[2000]" + qt_select_element7 "SELECT map(1000, 'k11', 2000, 'k22')[3000]" + qt_select_element8 "SELECT map('k11', 1000, 'k22', 2000)[NULL]" + qt_select_element101 "SELECT id, m, m['k1'] FROM ${testTable} ORDER BY id" + qt_select_element102 "SELECT id, m, m['k2'] FROM ${testTable} ORDER BY id" + qt_select_element103 "SELECT id, m, m[' 11amory '] FROM ${testTable} ORDER BY id" + qt_select_element104 "SELECT id, m, m['beat'] FROM ${testTable} ORDER BY id" + qt_select_element105 "SELECT id, m, m[' clever '] FROM ${testTable} ORDER BY id" + qt_select_element106 "SELECT id, m, m[' 33,amory '] FROM ${testTable} ORDER BY id" + qt_select_element107 "SELECT id, m, m[' bet '] FROM ${testTable} ORDER BY id" + qt_select_element108 "SELECT id, m, m[' cler '] FROM ${testTable} ORDER BY id" + qt_select_element109 "SELECT id, m, m[' 1,amy '] FROM ${testTable} ORDER BY id" + qt_select_element110 "SELECT id, m, m[' k2 '] FROM ${testTable} ORDER BY id" + qt_select_element111 "SELECT id, m, m['null'] FROM ${testTable} ORDER BY id" + qt_select_element112 "SELECT id, m, m[''] FROM ${testTable} ORDER BY id" + qt_select_element113 "SELECT id, m, m[NULL] FROM ${testTable} ORDER BY id" + qt_select_element114 "SELECT id, m, m['nokey'] FROM ${testTable} ORDER BY id" + + // map size + qt_select_map_size1 "SELECT map_size(map('k11', 1000, 'k22', 2000))" + qt_select_map_size2 "SELECT id, m, map_size(m) FROM ${testTable} ORDER BY id" + + // map_contains_key + qt_select_map_contains_key1 "SELECT map_contains_key(map('k11', 1000, 'k22', 2000), 'k11')" + qt_select_map_contains_key2 "SELECT map_contains_key(map('k11', 1000, 'k22', 2000), 'k22')" + qt_select_map_contains_key3 "SELECT map_contains_key(map('k11', 1000, 'k22', 2000), 'nokey')" + qt_select_map_contains_key4 "SELECT map_contains_key(map('k11', 1000, 'k22', 2000), '')" + qt_select_map_contains_key5 "SELECT map_contains_key(map('k11', 1000, 'k22', 2000), NULL)" + qt_select_map_contains_key101 "SELECT id, m, map_contains_key(m, 'k1') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key102 "SELECT id, m, map_contains_key(m, 'k2') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key103 "SELECT id, m, map_contains_key(m, ' 11amory ') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key104 "SELECT id, m, map_contains_key(m, 'beat') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key105 "SELECT id, m, map_contains_key(m, ' clever ') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key106 "SELECT id, m, map_contains_key(m, ' 33,amory ') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key107 "SELECT id, m, map_contains_key(m, ' bet ') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key108 "SELECT id, m, map_contains_key(m, ' cler ') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key109 "SELECT id, m, map_contains_key(m, ' 1,amy ') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key110 "SELECT id, m, map_contains_key(m, ' k2 ') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key111 "SELECT id, m, map_contains_key(m, 'null') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key112 "SELECT id, m, map_contains_key(m, '') FROM ${testTable} ORDER BY id" + qt_select_map_contains_key113 "SELECT id, m, map_contains_key(m, NULL) FROM ${testTable} ORDER BY id" + qt_select_map_contains_key114 "SELECT id, m, map_contains_key(m, 'nokey') FROM ${testTable} ORDER BY id" + + // map_contains_value + qt_select_map_contains_value1 "SELECT map_contains_value(map('k11', 1000, 'k22', 2000), 1000)" + qt_select_map_contains_value2 "SELECT map_contains_value(map('k11', 1000, 'k22', 2000), 2000)" + qt_select_map_contains_value3 "SELECT map_contains_value(map('k11', 1000, 'k22', 2000), 100)" + qt_select_map_contains_value4 "SELECT map_contains_value(map('k11', 1000, 'k22', 2000), NULL)" + qt_select_map_contains_value101 "SELECT id, m, map_contains_value(m, 23) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value102 "SELECT id, m, map_contains_value(m, 20) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value103 "SELECT id, m, map_contains_value(m, 66) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value104 "SELECT id, m, map_contains_value(m, 31) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value105 "SELECT id, m, map_contains_value(m, 300) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value106 "SELECT id, m, map_contains_value(m, 41) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value107 "SELECT id, m, map_contains_value(m, 400) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value108 "SELECT id, m, map_contains_value(m, 33) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value109 "SELECT id, m, map_contains_value(m, 2) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value110 "SELECT id, m, map_contains_value(m, 26) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value111 "SELECT id, m, map_contains_value(m, 90) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value112 "SELECT id, m, map_contains_value(m, 33) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value113 "SELECT id, m, map_contains_value(m, 1) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value114 "SELECT id, m, map_contains_value(m, 2) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value115 "SELECT id, m, map_contains_value(m, 0) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value116 "SELECT id, m, map_contains_value(m, -1) FROM ${testTable} ORDER BY id" + qt_select_map_contains_value117 "SELECT id, m, map_contains_value(m, NULL) FROM ${testTable} ORDER BY id" + + // map_keys + qt_select_map_keys1 "SELECT map_keys(map('k11', 1000, 'k22', 2000))" + qt_select_map_keys2 "SELECT id, m, map_keys(m) FROM ${testTable} ORDER BY id" + + // map_values + qt_select_map_values1 "SELECT map_values(map('k11', 1000, 'k22', 2000))" + qt_select_map_values2 "SELECT id, m, map_values(m) FROM ${testTable} ORDER BY id" + testTable = "tbl_test_map2" sql "DROP TABLE IF EXISTS ${testTable}"