This is an automated email from the ASF dual-hosted git repository.
lihaopeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git
The following commit(s) were added to refs/heads/master by this push:
new 2d83167e50 [Feature] [Lateral-View] support outer combinator of table
function (#9147)
2d83167e50 is described below
commit 2d83167e50069ee575ab8b6f3a9a6cb9657ab3f9
Author: Pxl <[email protected]>
AuthorDate: Sun Apr 24 12:09:40 2022 +0800
[Feature] [Lateral-View] support outer combinator of table function (#9147)
---
be/src/exprs/table_function/table_function.h | 13 ++-
.../table_function/table_function_factory.cpp | 50 ++++-----
.../exprs/table_function/table_function_factory.h | 12 +-
be/src/vec/exprs/table_function/vexplode.cpp | 9 +-
be/src/vec/exprs/table_function/vexplode.h | 4 +-
be/src/vec/functions/function_fake.cpp | 54 +++++++--
be/src/vec/functions/function_fake.h | 70 +-----------
be/src/vec/functions/simple_function_factory.h | 13 ++-
be/test/vec/function/table_function_test.cpp | 13 +--
docs/.vuepress/sidebar/en.js | 3 +-
docs/.vuepress/sidebar/zh-CN.js | 3 +-
.../table-functions/outer-combinator.md | 48 ++++++++
.../table-functions/explode-bitmap.md | 11 +-
.../table-functions/explode-json-array.md | 121 ++-------------------
.../sql-functions/table-functions/explode-split.md | 8 +-
.../table-functions/outer-combinator.md | 48 ++++++++
.../java/org/apache/doris/catalog/FunctionSet.java | 104 ++++++++----------
17 files changed, 269 insertions(+), 315 deletions(-)
diff --git a/be/src/exprs/table_function/table_function.h
b/be/src/exprs/table_function/table_function.h
index 3c2e188950..901572996b 100644
--- a/be/src/exprs/table_function/table_function.h
+++ b/be/src/exprs/table_function/table_function.h
@@ -30,6 +30,8 @@ namespace doris {
// Currently, the memory allocated from table function is from malloc directly.
class TableFunctionState {};
+constexpr auto COMBINATOR_SUFFIX_OUTER = "_outer";
+
class ExprContext;
class TupleRow;
class TableFunction {
@@ -99,6 +101,14 @@ public:
}
bool is_outer() const { return _is_outer; }
+ void set_outer() {
+ if (is_outer()) {
+ return;
+ }
+ _is_outer = true;
+ _fn_name += COMBINATOR_SUFFIX_OUTER;
+ }
+
bool current_empty() const { return _is_current_empty; }
protected:
@@ -115,7 +125,6 @@ protected:
// the size of current result
int64_t _cur_size = 0;
// set _is_outer to false for explode function, and should not return
tuple while array is null or empty
- bool _is_outer = true;
+ bool _is_outer = false;
};
-
} // namespace doris
diff --git a/be/src/exprs/table_function/table_function_factory.cpp
b/be/src/exprs/table_function/table_function_factory.cpp
index e44e3e65ed..2415627ccd 100644
--- a/be/src/exprs/table_function/table_function_factory.cpp
+++ b/be/src/exprs/table_function/table_function_factory.cpp
@@ -17,17 +17,6 @@
#include "exprs/table_function/table_function_factory.h"
-#include "common/object_pool.h"
-#include "exprs/table_function/explode_bitmap.h"
-#include "exprs/table_function/explode_json_array.h"
-#include "exprs/table_function/explode_split.h"
-#include "exprs/table_function/table_function.h"
-#include "vec/exprs/table_function/vexplode.h"
-#include "vec/exprs/table_function/vexplode_bitmap.h"
-#include "vec/exprs/table_function/vexplode_json_array.h"
-#include "vec/exprs/table_function/vexplode_numbers.h"
-#include "vec/exprs/table_function/vexplode_split.h"
-
namespace doris {
template <typename TableFunctionType>
@@ -49,12 +38,6 @@ struct
TableFunctionCreator<vectorized::VExplodeJsonArrayTableFunction> {
}
};
-template <>
-struct TableFunctionCreator<vectorized::VExplodeTableFunction> {
- bool is_outer;
- TableFunction* operator()() { return new
vectorized::VExplodeTableFunction(is_outer); }
-};
-
inline auto ExplodeJsonArrayIntCreator =
TableFunctionCreator<ExplodeJsonArrayTableFunction>
{ExplodeJsonArrayType::INT};
inline auto ExplodeJsonArrayDoubleCreator =
@@ -72,10 +55,7 @@ inline auto VExplodeJsonArrayStringCreator =
TableFunctionCreator<vectorized::VExplodeJsonArrayTableFunction> {
ExplodeJsonArrayType::STRING};
-inline auto VExplodeCreator =
TableFunctionCreator<vectorized::VExplodeTableFunction> {false};
-inline auto VExplodeOuterCreator =
TableFunctionCreator<vectorized::VExplodeTableFunction> {true};
-
-//{fn_name,is_vectorized}->table_function_creator
+// {fn_name, is_vectorized} -> table_function_creator
const std::unordered_map<std::pair<std::string, bool>,
std::function<TableFunction*()>>
TableFunctionFactory::_function_map {
{{"explode_split", false},
TableFunctionCreator<ExplodeSplitTableFunction> {}},
@@ -92,19 +72,37 @@ const std::unordered_map<std::pair<std::string, bool>,
std::function<TableFuncti
{{"explode_json_array_string", true},
VExplodeJsonArrayStringCreator},
{{"explode_bitmap", true},
TableFunctionCreator<vectorized::VExplodeBitmapTableFunction>()},
- {{"explode", true}, VExplodeCreator},
- {{"explode_outer", true}, VExplodeOuterCreator}}; // namespace
doris
+ {{"explode", true},
TableFunctionCreator<vectorized::VExplodeTableFunction> {}}};
-Status TableFunctionFactory::get_fn(const std::string& fn_name, bool
is_vectorized,
+Status TableFunctionFactory::get_fn(const std::string& fn_name_raw, bool
is_vectorized,
ObjectPool* pool, TableFunction** fn) {
- auto fn_iterator = _function_map.find({fn_name, is_vectorized});
+ auto match_suffix = [](const std::string& name, const std::string& suffix)
-> bool {
+ if (name.length() < suffix.length()) {
+ return false;
+ }
+ return name.substr(name.length() - suffix.length()) == suffix;
+ };
+
+ auto remove_suffix = [](const std::string& name, const std::string&
suffix) -> std::string {
+ return name.substr(0, name.length() - suffix.length());
+ };
+
+ bool is_outer = match_suffix(fn_name_raw, COMBINATOR_SUFFIX_OUTER);
+ std::string fn_name_real =
+ is_outer ? remove_suffix(fn_name_raw, COMBINATOR_SUFFIX_OUTER) :
fn_name_raw;
+
+ auto fn_iterator = _function_map.find({fn_name_real, is_vectorized});
if (fn_iterator != _function_map.end()) {
*fn = pool->add(fn_iterator->second());
+ if (is_outer) {
+ (*fn)->set_outer();
+ }
+
return Status::OK();
}
return Status::NotSupported(std::string(is_vectorized ? "vectorized " :
"") +
- "table function " + fn_name + " not support");
+ "table function " + fn_name_raw + " not
support");
}
} // namespace doris
diff --git a/be/src/exprs/table_function/table_function_factory.h
b/be/src/exprs/table_function/table_function_factory.h
index eaa1b86c63..05d4fa2e74 100644
--- a/be/src/exprs/table_function/table_function_factory.h
+++ b/be/src/exprs/table_function/table_function_factory.h
@@ -20,9 +20,17 @@
#include <functional>
#include <unordered_map>
+#include "common/object_pool.h"
#include "common/status.h"
+#include "exprs/table_function/explode_bitmap.h"
+#include "exprs/table_function/explode_json_array.h"
#include "exprs/table_function/explode_split.h"
-#include "exprs/table_function/table_function_factory.h"
+#include "exprs/table_function/table_function.h"
+#include "vec/exprs/table_function/vexplode.h"
+#include "vec/exprs/table_function/vexplode_bitmap.h"
+#include "vec/exprs/table_function/vexplode_json_array.h"
+#include "vec/exprs/table_function/vexplode_numbers.h"
+#include "vec/exprs/table_function/vexplode_split.h"
namespace doris {
@@ -32,7 +40,7 @@ class TableFunctionFactory {
public:
TableFunctionFactory() {}
~TableFunctionFactory() {}
- static Status get_fn(const std::string& fn_name, bool is_vectorized,
ObjectPool* pool,
+ static Status get_fn(const std::string& fn_name_raw, bool is_vectorized,
ObjectPool* pool,
TableFunction** fn);
const static std::unordered_map<std::pair<std::string, bool>,
std::function<TableFunction*()>>
diff --git a/be/src/vec/exprs/table_function/vexplode.cpp
b/be/src/vec/exprs/table_function/vexplode.cpp
index 58f8e7f2e0..adb0db076d 100644
--- a/be/src/vec/exprs/table_function/vexplode.cpp
+++ b/be/src/vec/exprs/table_function/vexplode.cpp
@@ -21,13 +21,8 @@
namespace doris::vectorized {
-VExplodeTableFunction::VExplodeTableFunction(bool is_outer) {
- _is_outer = is_outer;
- if (_is_outer) {
- _fn_name = "vexplode_outer";
- } else {
- _fn_name = "vexplode";
- }
+VExplodeTableFunction::VExplodeTableFunction() {
+ _fn_name = "vexplode";
}
Status VExplodeTableFunction::process_init(vectorized::Block* block) {
diff --git a/be/src/vec/exprs/table_function/vexplode.h
b/be/src/vec/exprs/table_function/vexplode.h
index b7ee993c0e..da4909994b 100644
--- a/be/src/vec/exprs/table_function/vexplode.h
+++ b/be/src/vec/exprs/table_function/vexplode.h
@@ -18,16 +18,16 @@
#pragma once
#include "exprs/table_function/table_function.h"
-#include "vec/common/string_ref.h"
#include "vec/columns/column.h"
#include "vec/columns/column_array.h"
#include "vec/columns/column_nullable.h"
+#include "vec/common/string_ref.h"
namespace doris::vectorized {
class VExplodeTableFunction : public TableFunction {
public:
- VExplodeTableFunction(bool is_outer);
+ VExplodeTableFunction();
virtual ~VExplodeTableFunction() = default;
diff --git a/be/src/vec/functions/function_fake.cpp
b/be/src/vec/functions/function_fake.cpp
index b661960517..1f52297806 100644
--- a/be/src/vec/functions/function_fake.cpp
+++ b/be/src/vec/functions/function_fake.cpp
@@ -17,18 +17,54 @@
#include "vec/functions/function_fake.h"
+#include <boost/metaparse/string.hpp>
+#include <string_view>
+#include <type_traits>
+
namespace doris::vectorized {
+// We can use std::basic_fixed_string with c++20 in the future
+template <const char* Name, typename ReturnType>
+struct FakeFunctionBaseImpl {
+ static constexpr auto name = Name;
+ static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
+ return std::make_shared<ReturnType>();
+ }
+};
+
+#define C_STR(str_) boost::mpl::c_str<BOOST_METAPARSE_STRING(str_)>::value
+
+using FunctionEsquery = FakeFunctionBaseImpl<C_STR("esquery"), DataTypeUInt8>;
+
+using FunctionExplodeSplit = FakeFunctionBaseImpl<C_STR("explode_split"),
DataTypeString>;
+using FunctionExplodeNumbers = FakeFunctionBaseImpl<C_STR("explode_numbers"),
DataTypeInt32>;
+using FunctionExplodeJsonArrayInt =
+ FakeFunctionBaseImpl<C_STR("explode_json_array_int"), DataTypeInt64>;
+using FunctionExplodeJsonArrayString =
+ FakeFunctionBaseImpl<C_STR("explode_json_array_string"),
DataTypeString>;
+using FunctionExplodeJsonArrayDouble =
+ FakeFunctionBaseImpl<C_STR("explode_json_array_double"),
DataTypeFloat64>;
+using FunctionExplodeBitmap = FakeFunctionBaseImpl<C_STR("explode_bitmap"),
DataTypeInt64>;
+
+struct FunctionExplode {
+ static constexpr auto name = "explode";
+ static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
+ DCHECK(is_array(arguments[0])) << arguments[0]->get_name() << " not
supported";
+ return make_nullable(
+
check_and_get_data_type<DataTypeArray>(arguments[0].get())->get_nested_type());
+ }
+};
+
void register_function_fake(SimpleFunctionFactory& factory) {
- factory.register_function<FunctionFake<FunctionEsqueryImpl>>();
- factory.register_function<FunctionFake<FunctionExplodeSplitImpl>>();
- factory.register_function<FunctionFake<FunctionExplodeNumbersImpl>>();
-
factory.register_function<FunctionFake<FunctionExplodeJsonArrayDoubleImpl>>();
- factory.register_function<FunctionFake<FunctionExplodeJsonArrayIntImpl>>();
-
factory.register_function<FunctionFake<FunctionExplodeJsonArrayStringImpl>>();
- factory.register_function<FunctionFake<FunctionExplodeBitmapImpl>>();
- factory.register_function<FunctionFake<FunctionExplodeImpl>>();
- factory.register_function<FunctionFake<FunctionExplodeOuterImpl>>();
+ factory.register_function<FunctionFake<FunctionEsquery>>();
+
+ factory.register_table_function<FunctionFake<FunctionExplodeSplit>>();
+ factory.register_table_function<FunctionFake<FunctionExplodeNumbers>>();
+
factory.register_table_function<FunctionFake<FunctionExplodeJsonArrayDouble>>();
+
factory.register_table_function<FunctionFake<FunctionExplodeJsonArrayInt>>();
+
factory.register_table_function<FunctionFake<FunctionExplodeJsonArrayString>>();
+ factory.register_table_function<FunctionFake<FunctionExplodeBitmap>>();
+ factory.register_table_function<FunctionFake<FunctionExplode>>();
}
} // namespace doris::vectorized
diff --git a/be/src/vec/functions/function_fake.h
b/be/src/vec/functions/function_fake.h
index 56648d8877..eaaecaf843 100644
--- a/be/src/vec/functions/function_fake.h
+++ b/be/src/vec/functions/function_fake.h
@@ -27,75 +27,7 @@
#include "vec/utils/util.hpp"
namespace doris::vectorized {
-
-struct FunctionEsqueryImpl {
- static constexpr auto name = "esquery";
- static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
- return std::make_shared<DataTypeUInt8>();
- }
-};
-
-struct FunctionExplodeSplitImpl {
- static constexpr auto name = "explode_split";
- static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
- return std::make_shared<DataTypeString>();
- }
-};
-
-struct FunctionExplodeNumbersImpl {
- static constexpr auto name = "explode_numbers";
- static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
- return std::make_shared<DataTypeInt32>();
- }
-};
-
-struct FunctionExplodeJsonArrayIntImpl {
- static constexpr auto name = "explode_json_array_int";
- static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
- return std::make_shared<DataTypeInt64>();
- }
-};
-
-struct FunctionExplodeJsonArrayStringImpl {
- static constexpr auto name = "explode_json_array_string";
- static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
- return std::make_shared<DataTypeString>();
- }
-};
-
-struct FunctionExplodeJsonArrayDoubleImpl {
- static constexpr auto name = "explode_json_array_double";
- static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
- return std::make_shared<DataTypeFloat64>();
- }
-};
-
-struct FunctionExplodeBitmapImpl {
- static constexpr auto name = "explode_bitmap";
- static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
- return std::make_shared<DataTypeInt64>();
- }
-};
-
-struct FunctionExplodeImpl {
- static constexpr auto name = "explode";
- static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
- DCHECK(is_array(arguments[0])) << arguments[0]->get_name() << " not
supported";
- return make_nullable(
-
check_and_get_data_type<DataTypeArray>(arguments[0].get())->get_nested_type());
- }
-};
-
-struct FunctionExplodeOuterImpl {
- static constexpr auto name = "explode_outer";
- static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
- DCHECK(is_array(arguments[0])) << arguments[0]->get_name() << " not
supported";
- return make_nullable(
-
check_and_get_data_type<DataTypeArray>(arguments[0].get())->get_nested_type());
- }
-};
-
-//FunctionFake is use for some function call expr only work at prepare/open
phase, do not support execute().
+// FunctionFake is use for some function call expr only work at prepare/open
phase, do not support execute().
template <typename Impl>
class FunctionFake : public IFunction {
public:
diff --git a/be/src/vec/functions/simple_function_factory.h
b/be/src/vec/functions/simple_function_factory.h
index 48266e303b..033682212a 100644
--- a/be/src/vec/functions/simple_function_factory.h
+++ b/be/src/vec/functions/simple_function_factory.h
@@ -23,6 +23,7 @@
#include <mutex>
#include <string>
+#include "exprs/table_function/table_function.h"
#include "vec/functions/function.h"
namespace doris::vectorized {
@@ -103,10 +104,18 @@ public:
template <class Function>
void register_function() {
- if constexpr (std::is_base_of<IFunction, Function>::value)
+ if constexpr (std::is_base_of<IFunction, Function>::value) {
register_function(Function::name,
&createDefaultFunction<Function>);
- else
+ } else {
register_function(Function::name, &Function::create);
+ }
+ }
+
+ template <class Function>
+ void register_table_function() {
+ function_creators[Function::name] = &createDefaultFunction<Function>;
+ function_creators[std::string(Function::name) +
COMBINATOR_SUFFIX_OUTER] =
+ &createDefaultFunction<Function>;
}
void register_alias(const std::string& name, const std::string& alias) {
diff --git a/be/test/vec/function/table_function_test.cpp
b/be/test/vec/function/table_function_test.cpp
index f525138d65..19e53dc8a4 100644
--- a/be/test/vec/function/table_function_test.cpp
+++ b/be/test/vec/function/table_function_test.cpp
@@ -64,7 +64,8 @@ private:
TEST_F(TableFunctionTest, vexplode_outer) {
init_expr_context(1);
- VExplodeTableFunction explode_outer(true);
+ VExplodeTableFunction explode_outer;
+ explode_outer.set_outer();
explode_outer.set_vexpr_context(_ctx.get());
// explode_outer(Array<Int32>)
@@ -95,7 +96,7 @@ TEST_F(TableFunctionTest, vexplode_outer) {
TEST_F(TableFunctionTest, vexplode) {
init_expr_context(1);
- VExplodeTableFunction explode(false);
+ VExplodeTableFunction explode;
explode.set_vexpr_context(_ctx.get());
// explode(Array<Int32>)
@@ -134,8 +135,7 @@ TEST_F(TableFunctionTest, vexplode_numbers) {
InputDataSet input_set = {{Int32(2)}, {Int32(3)}, {Null()},
{Int32(0)}, {Int32(-2)}};
InputTypeSet output_types = {TypeIndex::Int32};
- InputDataSet output_set = {{Int32(0)}, {Int32(1)}, {Int32(0)},
{Int32(1)},
- {Int32(2)}, {Null()}, {Null()},
{Null()}};
+ InputDataSet output_set = {{Int32(0)}, {Int32(1)}, {Int32(0)},
{Int32(1)}, {Int32(2)}};
check_vec_table_function(&tfn, input_types, input_set, output_types,
output_set);
}
@@ -158,9 +158,8 @@ TEST_F(TableFunctionTest, vexplode_split) {
{std::string(""), std::string(",")}};
InputTypeSet output_types = {TypeIndex::String};
- InputDataSet output_set = {{Null()}, {std::string("a")},
{std::string("b")},
- {std::string("c")}, {std::string("")},
{std::string("b,c")},
- {std::string("")}};
+ InputDataSet output_set = {{std::string("a")}, {std::string("b")},
{std::string("c")},
+ {std::string("")}, {std::string("b,c")},
{std::string("")}};
check_vec_table_function(&tfn, input_types, input_set, output_types,
output_set);
}
diff --git a/docs/.vuepress/sidebar/en.js b/docs/.vuepress/sidebar/en.js
index e28083d851..6a3d7ffda3 100644
--- a/docs/.vuepress/sidebar/en.js
+++ b/docs/.vuepress/sidebar/en.js
@@ -544,7 +544,8 @@ module.exports = [
"explode-bitmap",
"explode-split",
"explode-json-array",
- "explode-numbers"
+ "explode-numbers",
+ "outer-combinator"
],
},
"window-function",
diff --git a/docs/.vuepress/sidebar/zh-CN.js b/docs/.vuepress/sidebar/zh-CN.js
index 83e7f22f9b..13ef8c0daf 100644
--- a/docs/.vuepress/sidebar/zh-CN.js
+++ b/docs/.vuepress/sidebar/zh-CN.js
@@ -558,7 +558,8 @@ module.exports = [
"explode-bitmap",
"explode-split",
"explode-json-array",
- "explode-numbers"
+ "explode-numbers",
+ "outer-combinator"
],
},
"window-function",
diff --git
a/docs/en/sql-reference/sql-functions/table-functions/outer-combinator.md
b/docs/en/sql-reference/sql-functions/table-functions/outer-combinator.md
new file mode 100644
index 0000000000..83bed087d9
--- /dev/null
+++ b/docs/en/sql-reference/sql-functions/table-functions/outer-combinator.md
@@ -0,0 +1,48 @@
+---
+{
+ "title": "outer combinator",
+ "language": "en"
+}
+---
+
+<!--
+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.
+-->
+
+# outer combinator
+
+## description
+
+Adding the `_outer` suffix after the function name of the table function
changes the function behavior from `non-outer` to `outer`, and adds a row of
`Null` data when the table function generates 0 rows of data.
+
+## example
+
+```
+mysql> select e1 from (select 1 k1) as t lateral view explode_numbers(0) tmp1
as e1;
+Empty set
+
+mysql> select e1 from (select 1 k1) as t lateral view explode_numbers_outer(0)
tmp1 as e1;
++------+
+| e1 |
++------+
+| NULL |
++------+
+```
+## keyword
+
+ outer
\ No newline at end of file
diff --git
a/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-bitmap.md
b/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-bitmap.md
index 99f79711ac..e6302f46f3 100644
--- a/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-bitmap.md
+++ b/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-bitmap.md
@@ -60,16 +60,7 @@ Lateral View:
```
mysql> select k1, e1 from example1 lateral view explode_bitmap(bitmap_empty())
tmp1 as e1 order by k1, e1;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-| 4 | NULL |
-| 5 | NULL |
-| 6 | NULL |
-+------+------+
+Empty set
mysql> select k1, e1 from example1 lateral view
explode_bitmap(bitmap_from_string("1")) tmp1 as e1 order by k1, e1;
+------+------+
diff --git
a/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-json-array.md
b/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-json-array.md
index 8332d6a8e4..d5a08f8140 100644
---
a/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-json-array.md
+++
b/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-json-array.md
@@ -62,13 +62,7 @@ Lateral View:
```
mysql> select k1, e1 from example1 lateral view explode_json_array_int('[]')
tmp1 as e1 order by k1, e1;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
mysql> select k1, e1 from example1 lateral view
explode_json_array_int('[1,2,3]') tmp1 as e1 order by k1, e1;
+------+------+
@@ -89,79 +83,28 @@ 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;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 1 | NULL |
-| 1 | NULL |
-| 2 | NULL |
-| 2 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-| 3 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
mysql> select k1, e1 from example1 lateral view explode_json_array_int('{"a":
3}') tmp1 as e1 order by k1, e1;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
mysql> select k1, e1 from example1 lateral view
explode_json_array_double('[]') tmp1 as e1 order by k1, e1;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
mysql> select k1, e1 from example1 lateral view
explode_json_array_double('[1,2,3]') tmp1 as e1 order by k1, e1;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 1 | NULL |
-| 1 | NULL |
-| 2 | NULL |
-| 2 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-| 3 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
mysql> select k1, e1 from example1 lateral view
explode_json_array_double('[1,"b",3]') tmp1 as e1 order by k1, e1;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 1 | NULL |
-| 1 | NULL |
-| 2 | NULL |
-| 2 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-| 3 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
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;
+------+------+
@@ -179,52 +122,16 @@ 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;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 1 | NULL |
-| 1 | NULL |
-| 2 | NULL |
-| 2 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-| 3 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
mysql> select k1, e1 from example1 lateral view
explode_json_array_double('["a","b","c"]') tmp1 as e1 order by k1, e1;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 1 | NULL |
-| 1 | NULL |
-| 2 | NULL |
-| 2 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-| 3 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
mysql> select k1, e1 from example1 lateral view
explode_json_array_double('{"a": 3}') tmp1 as e1 order by k1, e1;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
mysql> select k1, e1 from example1 lateral view
explode_json_array_string('[]') tmp1 as e1 order by k1, e1;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
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;
+------+----------+
@@ -272,13 +179,7 @@ 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;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 1 | NULL |
-| 2 | NULL |
-| 3 | NULL |
-+------+------+
+Empty set
```
## keyword
diff --git
a/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-split.md
b/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-split.md
index d7c403186e..6bc0ea3fe7 100644
--- a/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-split.md
+++ b/docs/zh-CN/sql-reference/sql-functions/table-functions/explode-split.md
@@ -67,11 +67,7 @@ mysql> select k1, e1 from example1 lateral view
explode_split(k2, ',') tmp1 as e
+------+------+
mysql> select k1, e1 from example1 lateral view explode_split(k2, ',') tmp1 as
e1 where k1 = 2 order by k1, e1;
-+------+------+
-| k1 | e1 |
-+------+------+
-| 2 | NULL |
-+------+------+
+Empty set
mysql> select k1, e1 from example1 lateral view explode_split(k2, ',') tmp1 as
e1 where k1 = 3 order by k1, e1;
+------+------+
@@ -103,7 +99,7 @@ mysql> select k1, e1 from example1 lateral view
explode_split(k2, ',') tmp1 as e
+------+------+
| 6 | b |
| 6 | c |
-| 6 | a |
+| 6 | a |
+------+------+
```
diff --git
a/docs/zh-CN/sql-reference/sql-functions/table-functions/outer-combinator.md
b/docs/zh-CN/sql-reference/sql-functions/table-functions/outer-combinator.md
new file mode 100644
index 0000000000..ef9f97047e
--- /dev/null
+++ b/docs/zh-CN/sql-reference/sql-functions/table-functions/outer-combinator.md
@@ -0,0 +1,48 @@
+---
+{
+ "title": "outer组合器",
+ "language": "zh-CN"
+}
+---
+
+<!--
+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.
+-->
+
+# outer组合器
+
+## description
+
+在table
function的函数名后面添加`_outer`后缀使得函数行为从`non-outer`变为`outer`,在表函数生成0行数据时添加一行`Null`数据。
+
+## example
+
+```
+mysql> select e1 from (select 1 k1) as t lateral view explode_numbers(0) tmp1
as e1;
+Empty set
+
+mysql> select e1 from (select 1 k1) as t lateral view explode_numbers_outer(0)
tmp1 as e1;
++------+
+| e1 |
++------+
+| NULL |
++------+
+```
+## keyword
+
+ outer
\ No newline at end of file
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 e95b1c66bb..b6c08cba93 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
@@ -25,6 +25,7 @@ import org.apache.doris.analysis.InPredicate;
import org.apache.doris.analysis.IsNullPredicate;
import org.apache.doris.analysis.LikePredicate;
import org.apache.doris.builtins.ScalarBuiltins;
+import org.apache.doris.catalog.Function.NullableMode;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
@@ -2482,81 +2483,62 @@ public class
FunctionSet<min_initIN9doris_udf12DecimalV2ValEEEvPNS2_15FunctionCo
public static final String EXPLODE_JSON_ARRAY_STRING =
"explode_json_array_string";
public static final String EXPLODE_NUMBERS = "explode_numbers";
public static final String EXPLODE = "explode";
- public static final String EXPLODE_OUTER = "explode_outer";
+
+ private void addTableFunction(String name, Type retType, NullableMode
nullableMode, ArrayList<Type> argTypes,
+ boolean hasVarArgs, String symbol) {
+ List<Function> functionList = tableFunctions.get(name);
+ functionList.add(ScalarFunction.createBuiltin(name, retType,
nullableMode, argTypes, hasVarArgs, symbol, null,
+ null, true));
+ }
+
+ private void addTableFunctionWithCombinator(String name, Type retType,
NullableMode nullableMode,
+ ArrayList<Type> argTypes, boolean hasVarArgs, String symbol) {
+ addTableFunction(name, retType, nullableMode, argTypes, hasVarArgs,
symbol);
+ addTableFunction(name + "_outer", retType,
Function.NullableMode.ALWAYS_NULLABLE, argTypes, hasVarArgs, symbol);
+ }
+
+ private void initTableFunctionListWithCombinator(String name) {
+ tableFunctions.put(name, Lists.newArrayList());
+ tableFunctions.put(name + "_outer", Lists.newArrayList());
+ }
private void initTableFunction() {
- List<Function> explodeSplits = Lists.newArrayList();
- explodeSplits.add(ScalarFunction.createBuiltin(
- EXPLODE_SPLIT, Type.VARCHAR,
Function.NullableMode.DEPEND_ON_ARGUMENT,
+ initTableFunctionListWithCombinator(EXPLODE_SPLIT);
+ addTableFunctionWithCombinator(EXPLODE_SPLIT, Type.VARCHAR,
Function.NullableMode.DEPEND_ON_ARGUMENT,
Lists.newArrayList(Type.VARCHAR, Type.VARCHAR), false,
-
"_ZN5doris19DummyTableFunctions13explode_splitEPN9doris_udf15FunctionContextERKNS1_9StringValES6_",
- null, null, true));
- tableFunctions.put(EXPLODE_SPLIT, explodeSplits);
+
"_ZN5doris19DummyTableFunctions13explode_splitEPN9doris_udf15FunctionContextERKNS1_9StringValES6_");
- List<Function> explodeBitmaps = Lists.newArrayList();
- explodeBitmaps.add(ScalarFunction.createBuiltin(
- EXPLODE_BITMAP, Type.BIGINT,
Function.NullableMode.DEPEND_ON_ARGUMENT,
+ initTableFunctionListWithCombinator(EXPLODE_BITMAP);
+ addTableFunctionWithCombinator(EXPLODE_BITMAP, Type.BIGINT,
Function.NullableMode.DEPEND_ON_ARGUMENT,
Lists.newArrayList(Type.BITMAP), false,
-
"_ZN5doris19DummyTableFunctions14explode_bitmapEPN9doris_udf15FunctionContextERKNS1_9StringValE",
- null, null, true));
- tableFunctions.put(EXPLODE_BITMAP, explodeBitmaps);
+
"_ZN5doris19DummyTableFunctions14explode_bitmapEPN9doris_udf15FunctionContextERKNS1_9StringValE");
- List<Function> explodeJsonArrayInts = Lists.newArrayList();
- explodeJsonArrayInts.add(ScalarFunction.createBuiltin(
- EXPLODE_JSON_ARRAY_INT, Type.BIGINT,
Function.NullableMode.DEPEND_ON_ARGUMENT,
+ initTableFunctionListWithCombinator(EXPLODE_JSON_ARRAY_INT);
+ addTableFunctionWithCombinator(EXPLODE_JSON_ARRAY_INT, Type.BIGINT,
Function.NullableMode.DEPEND_ON_ARGUMENT,
Lists.newArrayList(Type.VARCHAR), false,
-
"_ZN5doris19DummyTableFunctions22explode_json_array_intEPN9doris_udf15FunctionContextERKNS1_9StringValE",
- null, null, true));
- tableFunctions.put(EXPLODE_JSON_ARRAY_INT, explodeJsonArrayInts);
+
"_ZN5doris19DummyTableFunctions22explode_json_array_intEPN9doris_udf15FunctionContextERKNS1_9StringValE");
- List<Function> explodeJsonArrayDoubles = Lists.newArrayList();
- explodeJsonArrayDoubles.add(ScalarFunction.createBuiltin(
- EXPLODE_JSON_ARRAY_DOUBLE, Type.DOUBLE,
Function.NullableMode.DEPEND_ON_ARGUMENT,
+ initTableFunctionListWithCombinator(EXPLODE_JSON_ARRAY_DOUBLE);
+ addTableFunctionWithCombinator(EXPLODE_JSON_ARRAY_DOUBLE, Type.DOUBLE,
Function.NullableMode.DEPEND_ON_ARGUMENT,
Lists.newArrayList(Type.VARCHAR), false,
-
"_ZN5doris19DummyTableFunctions25explode_json_array_doubleEPN9doris_udf15FunctionContextERKNS1_9StringValE",
- null, null, true));
- tableFunctions.put(EXPLODE_JSON_ARRAY_DOUBLE, explodeJsonArrayDoubles);
+
"_ZN5doris19DummyTableFunctions25explode_json_array_doubleEPN9doris_udf15FunctionContextERKNS1_9StringValE");
- List<Function> explodeJsonArrayStrings = Lists.newArrayList();
- explodeJsonArrayStrings.add(ScalarFunction.createBuiltin(
- EXPLODE_JSON_ARRAY_STRING, Type.VARCHAR,
Function.NullableMode.DEPEND_ON_ARGUMENT,
- Lists.newArrayList(Type.VARCHAR), false,
-
"_ZN5doris19DummyTableFunctions25explode_json_array_stringEPN9doris_udf15FunctionContextERKNS1_9StringValE",
- null, null, true));
- tableFunctions.put(EXPLODE_JSON_ARRAY_STRING, explodeJsonArrayStrings);
+ initTableFunctionListWithCombinator(EXPLODE_JSON_ARRAY_STRING);
+ addTableFunctionWithCombinator(EXPLODE_JSON_ARRAY_STRING, Type.VARCHAR,
+ Function.NullableMode.DEPEND_ON_ARGUMENT,
Lists.newArrayList(Type.VARCHAR), false,
+
"_ZN5doris19DummyTableFunctions25explode_json_array_stringEPN9doris_udf15FunctionContextERKNS1_9StringValE");
- List<Function> explodeNumbers = Lists.newArrayList();
- explodeNumbers.add(ScalarFunction.createBuiltin(
- EXPLODE_NUMBERS, Type.INT,
Function.NullableMode.DEPEND_ON_ARGUMENT,
+ initTableFunctionListWithCombinator(EXPLODE_NUMBERS);
+ addTableFunctionWithCombinator(EXPLODE_NUMBERS, Type.INT,
Function.NullableMode.DEPEND_ON_ARGUMENT,
Lists.newArrayList(Type.INT), false,
-
"_ZN5doris19DummyTableFunctions22explode_numbersEPN9doris_udf15FunctionContextERKNS1_9IntValE",
- null, null, true));
- tableFunctions.put(EXPLODE_NUMBERS, explodeNumbers);
-
- List<Function> explodes = Lists.newArrayList();
- explodes.add(ScalarFunction.createBuiltin(
- EXPLODE, Type.INT, Function.NullableMode.ALWAYS_NULLABLE,
- Lists.newArrayList(new ArrayType(Type.INT)), false,
-
"_ZN5doris19DummyTableFunctions7explodeEPN9doris_udf15FunctionContextERKNS1_13CollectionValE",
- null, null, true));
- explodes.add(ScalarFunction.createBuiltin(
- EXPLODE, Type.VARCHAR, Function.NullableMode.ALWAYS_NULLABLE,
- Lists.newArrayList(new ArrayType(Type.VARCHAR)), false,
-
"_ZN5doris19DummyTableFunctions7explodeEPN9doris_udf15FunctionContextERKNS1_13CollectionValE",
- null, null, true));
- tableFunctions.put(EXPLODE, explodes);
+
"_ZN5doris19DummyTableFunctions22explode_numbersEPN9doris_udf15FunctionContextERKNS1_9IntValE");
- List<Function> explodeOuters = Lists.newArrayList();
- explodeOuters.add(ScalarFunction.createBuiltin(
- EXPLODE_OUTER, Type.INT, Function.NullableMode.ALWAYS_NULLABLE,
+ initTableFunctionListWithCombinator(EXPLODE);
+ addTableFunctionWithCombinator(EXPLODE, Type.INT,
Function.NullableMode.ALWAYS_NULLABLE,
Lists.newArrayList(new ArrayType(Type.INT)), false,
-
"_ZN5doris19DummyTableFunctions13explode_outerEPN9doris_udf15FunctionContextERKNS1_13CollectionValE",
- null, null, true));
- explodeOuters.add(ScalarFunction.createBuiltin(
- EXPLODE_OUTER, Type.VARCHAR,
Function.NullableMode.ALWAYS_NULLABLE,
+
"_ZN5doris19DummyTableFunctions7explodeEPN9doris_udf15FunctionContextERKNS1_13CollectionValE");
+ addTableFunctionWithCombinator(EXPLODE, Type.VARCHAR,
Function.NullableMode.ALWAYS_NULLABLE,
Lists.newArrayList(new ArrayType(Type.VARCHAR)), false,
-
"_ZN5doris19DummyTableFunctions13explode_outerEPN9doris_udf15FunctionContextERKNS1_13CollectionValE",
- null, null, true));
- tableFunctions.put(EXPLODE_OUTER, explodeOuters);
+
"_ZN5doris19DummyTableFunctions7explodeEPN9doris_udf15FunctionContextERKNS1_13CollectionValE");
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]