This is an automated email from the ASF dual-hosted git repository.
morningman 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 d2374dbd5e [fix](Lateral-View) fix outer combinator not work on
non-vectorized (#9212)
d2374dbd5e is described below
commit d2374dbd5ef19000c7ec8b56b8788cf3afd498e1
Author: Pxl <[email protected]>
AuthorDate: Sun May 1 22:09:50 2022 +0800
[fix](Lateral-View) fix outer combinator not work on non-vectorized (#9212)
---
be/src/exec/table_function_node.cpp | 18 +++++-
be/src/exec/table_function_node.h | 11 ++--
be/src/vec/exec/vtable_function_node.cpp | 14 +---
be/src/vec/exec/vtable_function_node.h | 2 -
be/src/vec/functions/function_fake.cpp | 75 ++++++++++++++--------
be/src/vec/functions/function_fake.h | 3 +-
be/src/vec/functions/simple_function_factory.h | 6 +-
.../table_function/explode_json_array.out | 4 --
8 files changed, 77 insertions(+), 56 deletions(-)
diff --git a/be/src/exec/table_function_node.cpp
b/be/src/exec/table_function_node.cpp
index 01a023b07b..50351438c3 100644
--- a/be/src/exec/table_function_node.cpp
+++ b/be/src/exec/table_function_node.cpp
@@ -78,6 +78,16 @@ Status TableFunctionNode::_prepare_output_slot_ids(const
TPlanNode& tnode) {
return Status::OK();
}
+bool TableFunctionNode::_is_inner_and_empty() {
+ for (int i = 0; i < _fn_num; i++) {
+ // if any table function is not outer and has empty result, go to next
child row
+ if (!_fns[i]->is_outer() && _fns[i]->current_empty()) {
+ return true;
+ }
+ }
+ return false;
+}
+
Status TableFunctionNode::prepare(RuntimeState* state) {
RETURN_IF_ERROR(ExecNode::prepare(state));
SCOPED_SWITCH_TASK_THREAD_LOCAL_MEM_TRACKER(mem_tracker());
@@ -230,9 +240,10 @@ Status TableFunctionNode::get_next(RuntimeState* state,
RowBatch* row_batch, boo
}
}
+ bool skip_child_row = false;
while (true) {
int idx = _find_last_fn_eos_idx();
- if (idx == 0) {
+ if (idx == 0 || skip_child_row) {
// all table functions' results are exhausted, process next
child row
RETURN_IF_ERROR(_process_next_child_row());
if (_child_batch_exhausted) {
@@ -246,6 +257,11 @@ Status TableFunctionNode::get_next(RuntimeState* state,
RowBatch* row_batch, boo
}
}
+ // if any table function is not outer and has empty result, go to
next child row
+ if (skip_child_row = _is_inner_and_empty(); skip_child_row) {
+ continue;
+ }
+
// get slots from every table function
// Notice that _fn_values[i] may be null if the table function has
empty result set.
for (int i = 0; i < _fn_num; i++) {
diff --git a/be/src/exec/table_function_node.h
b/be/src/exec/table_function_node.h
index fd06760943..06de804c3c 100644
--- a/be/src/exec/table_function_node.h
+++ b/be/src/exec/table_function_node.h
@@ -32,14 +32,15 @@ public:
TableFunctionNode(ObjectPool* pool, const TPlanNode& tnode, const
DescriptorTbl& descs);
~TableFunctionNode();
- virtual Status init(const TPlanNode& tnode, RuntimeState* state = nullptr);
- virtual Status prepare(RuntimeState* state);
- virtual Status open(RuntimeState* state);
- virtual Status get_next(RuntimeState* state, RowBatch* row_batch, bool*
eos);
- virtual Status close(RuntimeState* state);
+ Status init(const TPlanNode& tnode, RuntimeState* state = nullptr)
override;
+ Status prepare(RuntimeState* state) override;
+ Status open(RuntimeState* state) override;
+ Status get_next(RuntimeState* state, RowBatch* row_batch, bool* eos)
override;
+ Status close(RuntimeState* state) override;
protected:
Status _prepare_output_slot_ids(const TPlanNode& tnode);
+ bool _is_inner_and_empty();
// return:
// 0: all fns are eos
diff --git a/be/src/vec/exec/vtable_function_node.cpp
b/be/src/vec/exec/vtable_function_node.cpp
index 6b25849f77..d21b252f35 100644
--- a/be/src/vec/exec/vtable_function_node.cpp
+++ b/be/src/vec/exec/vtable_function_node.cpp
@@ -92,16 +92,6 @@ Status VTableFunctionNode::get_next(RuntimeState* state,
Block* block, bool* eos
return Status::OK();
}
-bool VTableFunctionNode::_is_inner_and_empty() {
- for (int i = 0; i < _fn_num; i++) {
- // if any table function is not outer and has empty result, go to next
child row
- if (!_fns[i]->is_outer() && _fns[i]->current_empty()) {
- return true;
- }
- }
- return false;
-}
-
Status VTableFunctionNode::get_expanded_block(RuntimeState* state, Block*
output_block, bool* eos) {
DCHECK(_child_block != nullptr);
@@ -156,7 +146,7 @@ Status VTableFunctionNode::get_expanded_block(RuntimeState*
state, Block* output
}
// if any table function is not outer and has empty result, go to
next child row
- if ((skip_child_row = _is_inner_and_empty()) == true) {
+ if (skip_child_row = _is_inner_and_empty(); skip_child_row) {
continue;
}
@@ -225,7 +215,7 @@ Status VTableFunctionNode::_process_next_child_row() {
RETURN_IF_ERROR(fn->process_close());
}
- release_block_memory(*_child_block.get());
+ release_block_memory(*_child_block);
_cur_child_offset = -1;
return Status::OK();
}
diff --git a/be/src/vec/exec/vtable_function_node.h
b/be/src/vec/exec/vtable_function_node.h
index 6192e52ff6..1913cd1d35 100644
--- a/be/src/vec/exec/vtable_function_node.h
+++ b/be/src/vec/exec/vtable_function_node.h
@@ -37,8 +37,6 @@ private:
Status get_expanded_block(RuntimeState* state, Block* output_block, bool*
eos);
- bool _is_inner_and_empty();
-
std::unique_ptr<Block> _child_block;
std::vector<SlotDescriptor*> _child_slots;
std::vector<SlotDescriptor*> _output_slots;
diff --git a/be/src/vec/functions/function_fake.cpp
b/be/src/vec/functions/function_fake.cpp
index 1f52297806..faf8d0d525 100644
--- a/be/src/vec/functions/function_fake.cpp
+++ b/be/src/vec/functions/function_fake.cpp
@@ -21,33 +21,21 @@
#include <string_view>
#include <type_traits>
+#include "vec/data_types/data_type_nullable.h"
+
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;
+template <typename ReturnType, bool AlwaysNullable = false>
+struct FunctionFakeBaseImpl {
static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
+ if constexpr (AlwaysNullable) {
+ return make_nullable(std::make_shared<ReturnType>());
+ }
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(
@@ -55,16 +43,49 @@ struct FunctionExplode {
}
};
+template <typename ReturnType, bool Nullable = false>
+void register_function_default(SimpleFunctionFactory& factory, const
std::string& name) {
+ factory.register_function<FunctionFake<FunctionFakeBaseImpl<ReturnType,
Nullable>>>(name);
+};
+
+template <typename FunctionImpl>
+void register_table_function_expand(SimpleFunctionFactory& factory, const
std::string& name,
+ const std::string& suffix) {
+ factory.register_function<FunctionFake<FunctionImpl>>(name);
+ factory.register_function<FunctionFake<FunctionImpl>>(name + suffix);
+};
+
+template <typename ReturnType>
+void register_table_function_expand_default(SimpleFunctionFactory& factory,
const std::string& name,
+ const std::string& suffix) {
+
factory.register_function<FunctionFake<FunctionFakeBaseImpl<ReturnType>>>(name);
+ factory.register_function<FunctionFake<FunctionFakeBaseImpl<ReturnType,
true>>>(name + suffix);
+};
+
+template <typename FunctionImpl>
+void register_table_function_expand_outer(SimpleFunctionFactory& factory,
const std::string& name) {
+ register_table_function_expand<FunctionImpl>(factory, name,
COMBINATOR_SUFFIX_OUTER);
+};
+
+template <typename ReturnType>
+void register_table_function_expand_outer_default(SimpleFunctionFactory&
factory,
+ const std::string& name) {
+ register_table_function_expand_default<ReturnType>(factory, name,
COMBINATOR_SUFFIX_OUTER);
+};
+
void register_function_fake(SimpleFunctionFactory& factory) {
- factory.register_function<FunctionFake<FunctionEsquery>>();
+ register_function_default<DataTypeUInt8>(factory, "esquery");
+
+ register_table_function_expand_outer<FunctionExplode>(factory, "explode");
- 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>>();
+ register_table_function_expand_outer_default<DataTypeString>(factory,
"explode_split");
+ register_table_function_expand_outer_default<DataTypeInt32>(factory,
"explode_numbers");
+ 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<DataTypeFloat64>(factory,
+
"explode_json_array_double");
+ register_table_function_expand_outer_default<DataTypeInt64>(factory,
"explode_bitmap");
}
} // namespace doris::vectorized
diff --git a/be/src/vec/functions/function_fake.h
b/be/src/vec/functions/function_fake.h
index eaaecaf843..2dbf4f263f 100644
--- a/be/src/vec/functions/function_fake.h
+++ b/be/src/vec/functions/function_fake.h
@@ -20,6 +20,7 @@
#include "common/status.h"
#include "vec/core/types.h"
#include "vec/data_types/data_type_array.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"
#include "vec/functions/function_helpers.h"
@@ -31,7 +32,7 @@ namespace doris::vectorized {
template <typename Impl>
class FunctionFake : public IFunction {
public:
- static constexpr auto name = Impl::name;
+ static constexpr auto name = "fake";
static FunctionPtr create() { return std::make_shared<FunctionFake>(); }
diff --git a/be/src/vec/functions/simple_function_factory.h
b/be/src/vec/functions/simple_function_factory.h
index 033682212a..986528f25f 100644
--- a/be/src/vec/functions/simple_function_factory.h
+++ b/be/src/vec/functions/simple_function_factory.h
@@ -112,10 +112,8 @@ public:
}
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_function(std::string name) {
+ function_creators[name] = &createDefaultFunction<Function>;
}
void register_alias(const std::string& name, const std::string& alias) {
diff --git
a/regression-test/data/query/sql_functions/table_function/explode_json_array.out
b/regression-test/data/query/sql_functions/table_function/explode_json_array.out
index 52e504bdfb..4170e82089 100644
---
a/regression-test/data/query/sql_functions/table_function/explode_json_array.out
+++
b/regression-test/data/query/sql_functions/table_function/explode_json_array.out
@@ -22,10 +22,6 @@
60 8
-- !explode_json_array3 --
-100 John 30 1 Street 1 \N
-200 Mary \N 1 Street 2 \N
-300 Mike 80 3 Street 3 \N
-400 Dan 50 4 Street 4 \N
-- !explode_json_array4 --
100 John 30 1 Street 1 1.23 1
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]