This is an automated email from the ASF dual-hosted git repository. kxiao pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/doris.git
commit ec36d27fc0ce00dac962c41cbcd17d7541a1e5d7 Author: zy-kkk <[email protected]> AuthorDate: Mon Jul 17 11:40:02 2023 +0800 [Feature](table function) support explode_json_array_json (#21795) --- .../table_function/table_function_factory.cpp | 3 + .../exprs/table_function/vexplode_json_array.cpp | 25 ++++ .../vec/exprs/table_function/vexplode_json_array.h | 7 +- be/src/vec/functions/function_fake.cpp | 3 + .../table-functions/explode-json-array.md | 16 +++ .../table-functions/explode-json-array.md | 150 +++++++++++++++++---- .../catalog/BuiltinTableGeneratingFunctions.java | 6 +- .../java/org/apache/doris/catalog/FunctionSet.java | 6 + .../functions/generator/ExplodeJsonArrayJson.java | 66 +++++++++ .../generator/ExplodeJsonArrayJsonOuter.java | 66 +++++++++ .../visitor/TableGeneratingFunctionVisitor.java | 11 ++ .../doris/planner/TableFunctionPlanTest.java | 6 + .../table_function/explode_json_array.out | 14 ++ .../table_function/explode_json_array.groovy | 3 + 14 files changed, 355 insertions(+), 27 deletions(-) diff --git a/be/src/vec/exprs/table_function/table_function_factory.cpp b/be/src/vec/exprs/table_function/table_function_factory.cpp index 06b69a27c7..bafe47b69e 100644 --- a/be/src/vec/exprs/table_function/table_function_factory.cpp +++ b/be/src/vec/exprs/table_function/table_function_factory.cpp @@ -49,6 +49,8 @@ inline auto VExplodeJsonArrayDoubleCreator = TableFunctionCreator<VExplodeJsonArrayTableFunction> {ExplodeJsonArrayType::DOUBLE}; inline auto VExplodeJsonArrayStringCreator = TableFunctionCreator<VExplodeJsonArrayTableFunction> {ExplodeJsonArrayType::STRING}; +inline auto VExplodeJsonArrayJsonCreator = + TableFunctionCreator<VExplodeJsonArrayTableFunction> {ExplodeJsonArrayType::JSON}; const std::unordered_map<std::string, std::function<std::unique_ptr<TableFunction>()>> TableFunctionFactory::_function_map { @@ -57,6 +59,7 @@ const std::unordered_map<std::string, std::function<std::unique_ptr<TableFunctio {"explode_json_array_int", VExplodeJsonArrayIntCreator}, {"explode_json_array_double", VExplodeJsonArrayDoubleCreator}, {"explode_json_array_string", VExplodeJsonArrayStringCreator}, + {"explode_json_array_json", VExplodeJsonArrayJsonCreator}, {"explode_bitmap", TableFunctionCreator<VExplodeBitmapTableFunction>()}, {"explode", TableFunctionCreator<VExplodeTableFunction> {}}}; diff --git a/be/src/vec/exprs/table_function/vexplode_json_array.cpp b/be/src/vec/exprs/table_function/vexplode_json_array.cpp index 16f6c39bf7..840923d018 100644 --- a/be/src/vec/exprs/table_function/vexplode_json_array.cpp +++ b/be/src/vec/exprs/table_function/vexplode_json_array.cpp @@ -24,6 +24,8 @@ #include <algorithm> #include "common/status.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" #include "vec/columns/column.h" #include "vec/core/block.h" #include "vec/core/column_with_type_and_name.h" @@ -125,6 +127,29 @@ int ParsedData::set_output(ExplodeJsonArrayType type, rapidjson::Document& docum } break; } + case ExplodeJsonArrayType::JSON: { + _data_string.clear(); + _backup_string.clear(); + _string_nulls.clear(); + for (auto& v : document.GetArray()) { + if (v.IsObject()) { + rapidjson::StringBuffer buffer; + rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); + v.Accept(writer); + _backup_string.emplace_back(buffer.GetString(), buffer.GetSize()); + _string_nulls.push_back(false); + } else { + _data_string.push_back({}); + _string_nulls.push_back(true); + } + } + // Must set _data_string at the end, so that we can + // save the real addr of string in `_backup_string` to `_data_string`. + for (auto& str : _backup_string) { + _data_string.emplace_back(str); + } + break; + } default: CHECK(false) << type; break; diff --git a/be/src/vec/exprs/table_function/vexplode_json_array.h b/be/src/vec/exprs/table_function/vexplode_json_array.h index 2bdae9ed8e..db1784e5ad 100644 --- a/be/src/vec/exprs/table_function/vexplode_json_array.h +++ b/be/src/vec/exprs/table_function/vexplode_json_array.h @@ -40,7 +40,7 @@ class Block; namespace doris::vectorized { -enum ExplodeJsonArrayType { INT = 0, DOUBLE, STRING }; +enum ExplodeJsonArrayType { INT = 0, DOUBLE, STRING, JSON }; struct ParsedData { static std::string true_value; @@ -66,6 +66,7 @@ struct ParsedData { _data.clear(); _backup_double.clear(); break; + case ExplodeJsonArrayType::JSON: case ExplodeJsonArrayType::STRING: _data_string.clear(); _backup_string.clear(); @@ -82,6 +83,7 @@ struct ParsedData { case ExplodeJsonArrayType::INT: case ExplodeJsonArrayType::DOUBLE: return _data[offset]; + case ExplodeJsonArrayType::JSON: case ExplodeJsonArrayType::STRING: return _string_nulls[offset] ? nullptr : real ? reinterpret_cast<void*>(_backup_string[offset].data()) @@ -92,7 +94,8 @@ struct ParsedData { } int64 get_value_length(ExplodeJsonArrayType type, int64_t offset) { - if (type == ExplodeJsonArrayType::STRING && !_string_nulls[offset]) { + if ((type == ExplodeJsonArrayType::STRING || type == ExplodeJsonArrayType::JSON) && + !_string_nulls[offset]) { return _backup_string[offset].size(); } return 0; diff --git a/be/src/vec/functions/function_fake.cpp b/be/src/vec/functions/function_fake.cpp index 4fd626d17b..26896c028c 100644 --- a/be/src/vec/functions/function_fake.cpp +++ b/be/src/vec/functions/function_fake.cpp @@ -26,6 +26,7 @@ #include "vec/aggregate_functions/aggregate_function.h" #include "vec/data_types/data_type_array.h" +#include "vec/data_types/data_type_jsonb.h" #include "vec/data_types/data_type_nullable.h" #include "vec/data_types/data_type_number.h" #include "vec/data_types/data_type_string.h" @@ -102,6 +103,8 @@ void register_function_fake(SimpleFunctionFactory& factory) { register_table_function_expand_outer_default<DataTypeInt64>(factory, "explode_json_array_int"); register_table_function_expand_outer_default<DataTypeString>(factory, "explode_json_array_string"); + register_table_function_expand_outer_default<DataTypeString>(factory, + "explode_json_array_json"); register_table_function_expand_outer_default<DataTypeFloat64>(factory, "explode_json_array_double"); register_table_function_expand_outer_default<DataTypeInt64>(factory, "explode_bitmap"); diff --git a/docs/en/docs/sql-manual/sql-functions/table-functions/explode-json-array.md b/docs/en/docs/sql-manual/sql-functions/table-functions/explode-json-array.md index ee4cfe1d8f..daff67381f 100644 --- a/docs/en/docs/sql-manual/sql-functions/table-functions/explode-json-array.md +++ b/docs/en/docs/sql-manual/sql-functions/table-functions/explode-json-array.md @@ -38,6 +38,7 @@ Expand a json array. According to the array element type, there are three functi explode_json_array_int(json_str) explode_json_array_double(json_str) explode_json_array_string(json_str) +explode_json_array_json(json_str) ``` ### example @@ -276,6 +277,21 @@ mysql> select k1, e1 from example1 lateral view explode_json_array_string('{"a": | 2 | NULL | | 3 | NULL | +------+------+ + +mysql> select k1, e1 from example1 lateral view explode_json_array_json('[{"id":1,"name":"John"},{"id":2,"name":"Mary"},{"id":3,"name":"Bob"}]') tmp1 as e1 order by k1, e1; ++------+------------------------+ +| k1 | e1 | ++------+------------------------+ +| 1 | {"id":1,"name":"John"} | +| 1 | {"id":2,"name":"Mary"} | +| 1 | {"id":3,"name":"Bob"} | +| 2 | {"id":1,"name":"John"} | +| 2 | {"id":2,"name":"Mary"} | +| 2 | {"id":3,"name":"Bob"} | +| 3 | {"id":1,"name":"John"} | +| 3 | {"id":2,"name":"Mary"} | +| 3 | {"id":3,"name":"Bob"} | ++------+------------------------+ ``` ### keywords diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/table-functions/explode-json-array.md b/docs/zh-CN/docs/sql-manual/sql-functions/table-functions/explode-json-array.md index 15591a595c..c7f09139e1 100644 --- a/docs/zh-CN/docs/sql-manual/sql-functions/table-functions/explode-json-array.md +++ b/docs/zh-CN/docs/sql-manual/sql-functions/table-functions/explode-json-array.md @@ -37,28 +37,22 @@ under the License. explode_json_array_int(json_str) explode_json_array_double(json_str) explode_json_array_string(json_str) +explode_json_array_json(json_str) ``` ### example 原表数据: -``` -mysql> select k1 from example1 order by k1; -+------+ -| k1 | -+------+ -| 1 | -| 2 | -| 3 | -+------+ -``` - -Lateral View: - ``` mysql> select k1, e1 from example1 lateral view explode_json_array_int('[]') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 2 | NULL | +| 3 | NULL | ++------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_int('[1,2,3]') tmp1 as e1 order by k1, e1; +------+------+ @@ -79,28 +73,79 @@ mysql> select k1, e1 from example1 lateral view explode_json_array_int('[1,"b",3 +------+------+ | k1 | e1 | +------+------+ +| 1 | NULL | | 1 | 1 | | 1 | 3 | +| 2 | NULL | | 2 | 1 | | 2 | 3 | +| 3 | NULL | | 3 | 1 | | 3 | 3 | +------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_int('["a","b","c"]') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 1 | NULL | +| 1 | NULL | +| 2 | NULL | +| 2 | NULL | +| 2 | NULL | +| 3 | NULL | +| 3 | NULL | +| 3 | NULL | ++------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_int('{"a": 3}') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 2 | NULL | +| 3 | NULL | ++------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_double('[]') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 2 | NULL | +| 3 | NULL | ++------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_double('[1,2,3]') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 1 | NULL | +| 1 | NULL | +| 2 | NULL | +| 2 | NULL | +| 2 | NULL | +| 3 | NULL | +| 3 | NULL | +| 3 | NULL | ++------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_double('[1,"b",3]') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 1 | NULL | +| 1 | NULL | +| 2 | NULL | +| 2 | NULL | +| 2 | NULL | +| 3 | NULL | +| 3 | NULL | +| 3 | NULL | ++------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_double('[1.0,2.0,3.0]') tmp1 as e1 order by k1, e1; +------+------+ @@ -118,16 +163,52 @@ mysql> select k1, e1 from example1 lateral view explode_json_array_double('[1.0, +------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_double('[1,"b",3]') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 1 | NULL | +| 1 | NULL | +| 2 | NULL | +| 2 | NULL | +| 2 | NULL | +| 3 | NULL | +| 3 | NULL | +| 3 | NULL | ++------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_double('["a","b","c"]') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 1 | NULL | +| 1 | NULL | +| 2 | NULL | +| 2 | NULL | +| 2 | NULL | +| 3 | NULL | +| 3 | NULL | +| 3 | NULL | ++------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_double('{"a": 3}') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 2 | NULL | +| 3 | NULL | ++------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_string('[]') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 2 | NULL | +| 3 | NULL | ++------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_string('[1.0,2.0,3.0]') tmp1 as e1 order by k1, e1; +------+----------+ @@ -175,7 +256,28 @@ mysql> select k1, e1 from example1 lateral view explode_json_array_string('["a", +------+------+ mysql> select k1, e1 from example1 lateral view explode_json_array_string('{"a": 3}') tmp1 as e1 order by k1, e1; -Empty set ++------+------+ +| k1 | e1 | ++------+------+ +| 1 | NULL | +| 2 | NULL | +| 3 | NULL | ++------+------+ + +mysql> select k1, e1 from example1 lateral view explode_json_array_json('[{"id":1,"name":"John"},{"id":2,"name":"Mary"},{"id":3,"name":"Bob"}]') tmp1 as e1 order by k1, e1; ++------+------------------------+ +| k1 | e1 | ++------+------------------------+ +| 1 | {"id":1,"name":"John"} | +| 1 | {"id":2,"name":"Mary"} | +| 1 | {"id":3,"name":"Bob"} | +| 2 | {"id":1,"name":"John"} | +| 2 | {"id":2,"name":"Mary"} | +| 2 | {"id":3,"name":"Bob"} | +| 3 | {"id":1,"name":"John"} | +| 3 | {"id":2,"name":"Mary"} | +| 3 | {"id":3,"name":"Bob"} | ++------+------------------------+ ``` ### keywords diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinTableGeneratingFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinTableGeneratingFunctions.java index fc82eafcbb..b1dd9c8306 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinTableGeneratingFunctions.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinTableGeneratingFunctions.java @@ -23,6 +23,8 @@ import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJso import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayDoubleOuter; import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayInt; import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayIntOuter; +import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayJson; +import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayJsonOuter; import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayString; import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayStringOuter; import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeNumbers; @@ -53,7 +55,9 @@ public class BuiltinTableGeneratingFunctions implements FunctionHelper { tableGenerating(ExplodeJsonArrayDouble.class, "explode_json_array_double"), tableGenerating(ExplodeJsonArrayDoubleOuter.class, "explode_json_array_double_outer"), tableGenerating(ExplodeJsonArrayString.class, "explode_json_array_string"), - tableGenerating(ExplodeJsonArrayStringOuter.class, "explode_json_array_string_outer") + tableGenerating(ExplodeJsonArrayStringOuter.class, "explode_json_array_string_outer"), + tableGenerating(ExplodeJsonArrayJson.class, "explode_json_array_json"), + tableGenerating(ExplodeJsonArrayJsonOuter.class, "explode_json_array_json_outer") ); public static final BuiltinTableGeneratingFunctions INSTANCE = new BuiltinTableGeneratingFunctions(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java index f86bba5006..558d328de2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java @@ -1588,6 +1588,7 @@ public class FunctionSet<T> { public static final String EXPLODE_JSON_ARRAY_INT = "explode_json_array_int"; public static final String EXPLODE_JSON_ARRAY_DOUBLE = "explode_json_array_double"; public static final String EXPLODE_JSON_ARRAY_STRING = "explode_json_array_string"; + public static final String EXPLODE_JSON_ARRAY_JSON = "explode_json_array_json"; public static final String EXPLODE_NUMBERS = "explode_numbers"; public static final String EXPLODE = "explode"; @@ -1635,6 +1636,11 @@ public class FunctionSet<T> { Function.NullableMode.DEPEND_ON_ARGUMENT, Lists.newArrayList(Type.VARCHAR), false, "_ZN5doris19DummyTableFunctions25explode_json_array_stringEPN9doris_udf15FunctionContextERKNS1_9StringValE"); + initTableFunctionListWithCombinator(EXPLODE_JSON_ARRAY_JSON); + addTableFunctionWithCombinator(EXPLODE_JSON_ARRAY_JSON, Type.VARCHAR, + Function.NullableMode.DEPEND_ON_ARGUMENT, Lists.newArrayList(Type.VARCHAR), false, + "_ZN5doris19DummyTableFunctions25explode_json_array_jsonEPN9doris_udf15FunctionContextERKNS1_9StringValE"); + initTableFunctionListWithCombinator(EXPLODE_NUMBERS); addTableFunctionWithCombinator(EXPLODE_NUMBERS, Type.INT, Function.NullableMode.DEPEND_ON_ARGUMENT, Lists.newArrayList(Type.INT), false, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/generator/ExplodeJsonArrayJson.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/generator/ExplodeJsonArrayJson.java new file mode 100644 index 0000000000..a07e0e5d8f --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/generator/ExplodeJsonArrayJson.java @@ -0,0 +1,66 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions.generator; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * explode_json_array_json("[{"id":1,"name":"John"},{"id":2,"name":"Mary"},{"id":3,"name":"Bob"}]"), + * generate 3 lines include '{"id":1,"name":"John"}', '{"id":2,"name":"Mary"}' and '{"id":3,"name":"Bob"}'. + */ +public class ExplodeJsonArrayJson extends TableGeneratingFunction implements UnaryExpression, PropagateNullable { + public static final List<FunctionSignature> SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(VarcharType.SYSTEM_DEFAULT) + ); + + /** + * constructor with 1 argument. + */ + public ExplodeJsonArrayJson(Expression arg) { + super("explode_json_array_json", arg); + } + + /** + * withChildren. + */ + @Override + public ExplodeJsonArrayJson withChildren(List<Expression> children) { + Preconditions.checkArgument(children.size() == 1); + return new ExplodeJsonArrayJson(children.get(0)); + } + + @Override + public List<FunctionSignature> getSignatures() { + return SIGNATURES; + } + + @Override + public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { + return visitor.visitExplodeJsonArrayJson(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/generator/ExplodeJsonArrayJsonOuter.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/generator/ExplodeJsonArrayJsonOuter.java new file mode 100644 index 0000000000..bb4a34905a --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/generator/ExplodeJsonArrayJsonOuter.java @@ -0,0 +1,66 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions.generator; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * explode_json_array_json_outer("[{"id":1,"name":"John"},{"id":2,"name":"Mary"},{"id":3,"name":"Bob"}]"), + * generate 3 lines include '{"id":1,"name":"John"}', '{"id":2,"name":"Mary"}' and '{"id":3,"name":"Bob"}'. + */ +public class ExplodeJsonArrayJsonOuter extends TableGeneratingFunction implements UnaryExpression, PropagateNullable { + public static final List<FunctionSignature> SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(VarcharType.SYSTEM_DEFAULT) + ); + + /** + * constructor with 1 argument. + */ + public ExplodeJsonArrayJsonOuter(Expression arg) { + super("explode_json_array_json_outer", arg); + } + + /** + * withChildren. + */ + @Override + public ExplodeJsonArrayJsonOuter withChildren(List<Expression> children) { + Preconditions.checkArgument(children.size() == 1); + return new ExplodeJsonArrayJsonOuter(children.get(0)); + } + + @Override + public List<FunctionSignature> getSignatures() { + return SIGNATURES; + } + + @Override + public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { + return visitor.visitExplodeJsonArrayJsonOuter(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/TableGeneratingFunctionVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/TableGeneratingFunctionVisitor.java index a869ab0d7e..040b279df8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/TableGeneratingFunctionVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/TableGeneratingFunctionVisitor.java @@ -23,6 +23,8 @@ import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJso import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayDoubleOuter; import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayInt; import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayIntOuter; +import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayJson; +import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayJsonOuter; import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayString; import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeJsonArrayStringOuter; import org.apache.doris.nereids.trees.expressions.functions.generator.ExplodeNumbers; @@ -84,4 +86,13 @@ public interface TableGeneratingFunctionVisitor<R, C> { default R visitExplodeJsonArrayStringOuter(ExplodeJsonArrayStringOuter explodeJsonArrayStringOuter, C context) { return visitTableGeneratingFunction(explodeJsonArrayStringOuter, context); } + + default R visitExplodeJsonArrayJson(ExplodeJsonArrayJson explodeJsonArrayJson, C context) { + return visitTableGeneratingFunction(explodeJsonArrayJson, context); + } + + default R visitExplodeJsonArrayJsonOuter(ExplodeJsonArrayJsonOuter explodeJsonArrayJsonOuter, C context) { + return visitTableGeneratingFunction(explodeJsonArrayJsonOuter, context); + } + } diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java index 0b1308c9b1..f1e187ccc0 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java @@ -447,6 +447,12 @@ public class TableFunctionPlanTest { System.out.println(explainString); Assert.assertTrue(explainString.contains("table function: explode_json_array_double('[1.1, 2.2, 3.3]')")); Assert.assertTrue(explainString.contains("output slot id: 0 1")); + + sql = "desc select /*+ SET_VAR(enable_nereids_planner=false) */ k1, e1 from db1.tbl2 lateral view explode_json_array_json('[{\"id\":1,\"name\":\"John\"},{\"id\":2,\"name\":\"Mary\"},{\"id\":3,\"name\":\"Bob\"}]') tmp1 as e1 "; + explainString = UtFrameUtils.getSQLPlanOrErrorMsg(ctx, sql, true); + System.out.println(explainString); + Assert.assertTrue(explainString.contains("table function: explode_json_array_json('[{\"id\":1,\"name\":\"John\"},{\"id\":2,\"name\":\"Mary\"},{\"id\":3,\"name\":\"Bob\"}]')")); + Assert.assertTrue(explainString.contains("output slot id: 0 1")); } /* diff --git a/regression-test/data/query_p0/sql_functions/table_function/explode_json_array.out b/regression-test/data/query_p0/sql_functions/table_function/explode_json_array.out index a9f68ee30c..0b1994a22c 100644 --- a/regression-test/data/query_p0/sql_functions/table_function/explode_json_array.out +++ b/regression-test/data/query_p0/sql_functions/table_function/explode_json_array.out @@ -75,3 +75,17 @@ \N 80 3 \N 80 b +-- !outer_join_explode_json_array11 -- +\N \N {"id":1,"name":"John"} +\N \N {"id":2,"name":"Mary"} +\N \N {"id":3,"name":"Bob"} +\N 30 {"id":1,"name":"John"} +\N 30 {"id":2,"name":"Mary"} +\N 30 {"id":3,"name":"Bob"} +\N 50 {"id":1,"name":"John"} +\N 50 {"id":2,"name":"Mary"} +\N 50 {"id":3,"name":"Bob"} +\N 80 {"id":1,"name":"John"} +\N 80 {"id":2,"name":"Mary"} +\N 80 {"id":3,"name":"Bob"} + diff --git a/regression-test/suites/query_p0/sql_functions/table_function/explode_json_array.groovy b/regression-test/suites/query_p0/sql_functions/table_function/explode_json_array.groovy index fc94aa5655..7ee801702b 100644 --- a/regression-test/suites/query_p0/sql_functions/table_function/explode_json_array.groovy +++ b/regression-test/suites/query_p0/sql_functions/table_function/explode_json_array.groovy @@ -57,4 +57,7 @@ suite("explode_json_array") { qt_outer_join_explode_json_array11 """SELECT id, age, e1 FROM (SELECT id, age, e1 FROM (SELECT b.id, a.age FROM ${tableName} a LEFT JOIN ${tableName} b ON a.id=b.age)T LATERAL VIEW EXPLODE_JSON_ARRAY_STRING('[1, "b", 3]') TMP AS e1) AS T ORDER BY age, e1""" + qt_outer_join_explode_json_array11 """SELECT id, age, e1 FROM (SELECT id, age, e1 FROM (SELECT b.id, a.age FROM + ${tableName} a LEFT JOIN ${tableName} b ON a.id=b.age)T LATERAL VIEW EXPLODE_JSON_ARRAY_JSON('[{"id":1,"name":"John"},{"id":2,"name":"Mary"},{"id":3,"name":"Bob"}]') + TMP AS e1) AS T ORDER BY age, e1""" } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
