[feature](vectorized) support lateral view (#8448)

This commit is contained in:
Pxl
2022-03-17 10:04:24 +08:00
committed by GitHub
parent aadfbcb9c8
commit a824c3e489
18 changed files with 602 additions and 93 deletions

View File

@ -19,23 +19,21 @@
#include "exprs/expr.h"
#include "exprs/expr_context.h"
#include "exprs/table_function/table_function_factory.h"
#include "runtime/descriptors.h"
#include "runtime/raw_value.h"
#include "runtime/row_batch.h"
#include "runtime/runtime_state.h"
#include "runtime/tuple_row.h"
#include "exprs/table_function/table_function_factory.h"
#include "vec/exprs/vexpr.h"
namespace doris {
TableFunctionNode::TableFunctionNode(ObjectPool* pool, const TPlanNode& tnode, const DescriptorTbl& descs)
: ExecNode(pool, tnode, descs) {
TableFunctionNode::TableFunctionNode(ObjectPool* pool, const TPlanNode& tnode,
const DescriptorTbl& descs)
: ExecNode(pool, tnode, descs) {}
}
TableFunctionNode::~TableFunctionNode() {
}
TableFunctionNode::~TableFunctionNode() {}
Status TableFunctionNode::init(const TPlanNode& tnode, RuntimeState* state) {
RETURN_IF_ERROR(ExecNode::init(tnode, state));
@ -46,14 +44,15 @@ Status TableFunctionNode::init(const TPlanNode& tnode, RuntimeState* state) {
_fn_ctxs.push_back(ctx);
Expr* root = ctx->root();
const std::string& tf_name = root->fn().name.function_name;
TableFunction* fn;
RETURN_IF_ERROR(TableFunctionFactory::get_fn(tf_name, _pool, &fn));
const std::string& tf_name = root->fn().name.function_name;
TableFunction* fn = nullptr;
RETURN_IF_ERROR(TableFunctionFactory::get_fn(tf_name, false, _pool, &fn));
fn->set_expr_context(ctx);
_fns.push_back(fn);
}
_fn_num = _fns.size();
_fn_values.resize(_fn_num);
_fn_value_lengths.resize(_fn_num);
// Prepare output slot ids
RETURN_IF_ERROR(_prepare_output_slot_ids(tnode));
@ -83,7 +82,7 @@ Status TableFunctionNode::prepare(RuntimeState* state) {
RETURN_IF_ERROR(ExecNode::prepare(state));
_num_rows_filtered_counter = ADD_COUNTER(_runtime_profile, "RowsFiltered", TUnit::UNIT);
RETURN_IF_ERROR(Expr::prepare(_fn_ctxs, state, _row_descriptor, expr_mem_tracker()));
for (auto fn : _fns) {
RETURN_IF_ERROR(fn->prepare());
@ -97,6 +96,8 @@ Status TableFunctionNode::open(RuntimeState* state) {
RETURN_IF_ERROR(ExecNode::open(state));
RETURN_IF_ERROR(Expr::open(_fn_ctxs, state));
RETURN_IF_ERROR(vectorized::VExpr::open(_vfn_ctxs, state));
for (auto fn : _fns) {
RETURN_IF_ERROR(fn->open());
}
@ -139,7 +140,7 @@ Status TableFunctionNode::_process_next_child_row() {
// -1: all fns are not eos
// >0: some of fns are eos
int TableFunctionNode::_find_last_fn_eos_idx() {
for (int i = _fn_num - 1; i >=0; --i) {
for (int i = _fn_num - 1; i >= 0; --i) {
if (!_fns[i]->eos()) {
if (i == _fn_num - 1) {
return -1;
@ -193,7 +194,7 @@ Status TableFunctionNode::get_next(RuntimeState* state, RowBatch* row_batch, boo
_child_tuple_desc_size = child_rowdesc.tuple_descriptors().size();
for (int i = 0; i < _child_tuple_desc_size; ++i) {
_child_slot_sizes.push_back(child_rowdesc.tuple_descriptors()[i]->slots().size());
}
}
}
uint8_t* tuple_buffer = nullptr;
@ -205,12 +206,13 @@ Status TableFunctionNode::get_next(RuntimeState* state, RowBatch* row_batch, boo
RETURN_IF_ERROR(state->check_query_state("TableFunctionNode, while getting next batch."));
if (_cur_child_batch == nullptr) {
_cur_child_batch.reset(new RowBatch(child_rowdesc, state->batch_size(), mem_tracker().get()));
_cur_child_batch.reset(
new RowBatch(child_rowdesc, state->batch_size(), mem_tracker().get()));
}
if (_child_batch_exhausted) {
if (_child_eos) {
// current child batch is exhausted, and no more batch from child node
break;
break;
}
// current child batch is exhausted, get next batch from child
RETURN_IF_ERROR(_children[0]->get_next(state, _cur_child_batch.get(), &_child_eos));
@ -238,7 +240,7 @@ Status TableFunctionNode::get_next(RuntimeState* state, RowBatch* row_batch, boo
// some of table functions' results are exhausted
if (!_roll_table_functions(idx)) {
// continue to process next child row
continue;
continue;
}
}
@ -251,11 +253,11 @@ Status TableFunctionNode::get_next(RuntimeState* state, RowBatch* row_batch, boo
// allocate memory for row batch for the first time
if (tuple_buffer == nullptr) {
int64_t tuple_buffer_size;
RETURN_IF_ERROR(
row_batch->resize_and_allocate_tuple_buffer(state, &tuple_buffer_size, &tuple_buffer));
RETURN_IF_ERROR(row_batch->resize_and_allocate_tuple_buffer(
state, &tuple_buffer_size, &tuple_buffer));
tuple_ptr = reinterpret_cast<Tuple*>(tuple_buffer);
}
pre_tuple_ptr = tuple_ptr;
// The tuples order in parent row batch should be
// child1, child2, tf1, tf2, ...
@ -266,22 +268,27 @@ Status TableFunctionNode::get_next(RuntimeState* state, RowBatch* row_batch, boo
TupleDescriptor* child_tuple_desc = child_rowdesc.tuple_descriptors()[tuple_idx];
TupleDescriptor* parent_tuple_desc = parent_rowdesc.tuple_descriptors()[tuple_idx];
Tuple* child_tuple = _cur_child_tuple_row->get_tuple(child_rowdesc.get_tuple_idx(child_tuple_desc->id()));
Tuple* child_tuple = _cur_child_tuple_row->get_tuple(
child_rowdesc.get_tuple_idx(child_tuple_desc->id()));
for (int j = 0; j < _child_slot_sizes[i]; ++j) {
SlotDescriptor* child_slot_desc = child_tuple_desc->slots()[j];
SlotDescriptor* parent_slot_desc = parent_tuple_desc->slots()[j];
if (_output_slot_ids[parent_slot_desc->id()] && !child_tuple->is_null(child_slot_desc->null_indicator_offset())) {
if (_output_slot_ids[parent_slot_desc->id()] &&
!child_tuple->is_null(child_slot_desc->null_indicator_offset())) {
// only write child slot if it is selected and not null.
void* dest_slot = tuple_ptr->get_slot(parent_slot_desc->tuple_offset());
RawValue::write(child_tuple->get_slot(child_slot_desc->tuple_offset()), dest_slot, parent_slot_desc->type(), row_batch->tuple_data_pool());
RawValue::write(child_tuple->get_slot(child_slot_desc->tuple_offset()),
dest_slot, parent_slot_desc->type(),
row_batch->tuple_data_pool());
tuple_ptr->set_not_null(parent_slot_desc->null_indicator_offset());
} else {
tuple_ptr->set_null(parent_slot_desc->null_indicator_offset());
}
}
parent_tuple_row->set_tuple(tuple_idx, tuple_ptr);
tuple_ptr = reinterpret_cast<Tuple*>(reinterpret_cast<uint8_t*>(tuple_ptr) + parent_tuple_desc->byte_size());
tuple_ptr = reinterpret_cast<Tuple*>(reinterpret_cast<uint8_t*>(tuple_ptr) +
parent_tuple_desc->byte_size());
}
// 2. copy function result
@ -290,13 +297,15 @@ Status TableFunctionNode::get_next(RuntimeState* state, RowBatch* row_batch, boo
SlotDescriptor* parent_slot_desc = parent_tuple_desc->slots()[0];
void* dest_slot = tuple_ptr->get_slot(parent_slot_desc->tuple_offset());
if (_fn_values[i] != nullptr) {
RawValue::write(_fn_values[i], dest_slot, parent_slot_desc->type(), row_batch->tuple_data_pool());
RawValue::write(_fn_values[i], dest_slot, parent_slot_desc->type(),
row_batch->tuple_data_pool());
tuple_ptr->set_not_null(parent_slot_desc->null_indicator_offset());
} else {
tuple_ptr->set_null(parent_slot_desc->null_indicator_offset());
}
parent_tuple_row->set_tuple(tuple_idx, tuple_ptr);
tuple_ptr = reinterpret_cast<Tuple*>(reinterpret_cast<uint8_t*>(tuple_ptr) + parent_tuple_desc->byte_size());
tuple_ptr = reinterpret_cast<Tuple*>(reinterpret_cast<uint8_t*>(tuple_ptr) +
parent_tuple_desc->byte_size());
}
// 3. eval conjuncts
@ -311,7 +320,7 @@ Status TableFunctionNode::get_next(RuntimeState* state, RowBatch* row_batch, boo
// Forward after write success.
// Because data in `_fn_values` points to the data saved in functions.
// And `forward` will change the data in functions.
bool tmp;
bool tmp = false;
_fns[_fn_num - 1]->forward(&tmp);
if (row_batch->at_capacity()) {
@ -321,7 +330,7 @@ Status TableFunctionNode::get_next(RuntimeState* state, RowBatch* row_batch, boo
if (row_batch->at_capacity()) {
break;
}
}
} // end while cur_eos
if (reached_limit()) {
@ -344,7 +353,9 @@ Status TableFunctionNode::close(RuntimeState* state) {
RETURN_IF_ERROR(exec_debug_action(TExecNodePhase::CLOSE));
Expr::close(_fn_ctxs, state);
COUNTER_SET(_num_rows_filtered_counter, static_cast<int64_t>(_num_rows_filtered));
if (_num_rows_filtered_counter != nullptr) {
COUNTER_SET(_num_rows_filtered_counter, static_cast<int64_t>(_num_rows_filtered));
}
return ExecNode::close(state);
}