init push
This commit is contained in:
2000
src/sql/engine/window_function/ob_window_function.cpp
Normal file
2000
src/sql/engine/window_function/ob_window_function.cpp
Normal file
File diff suppressed because it is too large
Load Diff
514
src/sql/engine/window_function/ob_window_function.h
Normal file
514
src/sql/engine/window_function/ob_window_function.h
Normal file
@ -0,0 +1,514 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#ifndef _OB_WINDOW_FUNCTION_H
|
||||
#define _OB_WINDOW_FUNCTION_H 1
|
||||
|
||||
#include "lib/container/ob_array.h"
|
||||
#include "lib/container/ob_fixed_array.h"
|
||||
#include "common/row/ob_row.h"
|
||||
#include "sql/parser/ob_item_type.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr.h"
|
||||
#include "sql/engine/basic/ob_ra_row_store.h"
|
||||
#include "sql/engine/ob_single_child_phy_operator.h"
|
||||
#include "sql/engine/sort/ob_base_sort.h"
|
||||
#include "sql/engine/expr/ob_sql_expression.h"
|
||||
#include "sql/engine/aggregate/ob_aggregate_function.h"
|
||||
#include "sql/engine/px/datahub/ob_dh_msg.h"
|
||||
#include "sql/engine/px/datahub/components/ob_dh_winbuf.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace common {
|
||||
class ObExprCtx;
|
||||
}
|
||||
namespace sql {
|
||||
class ObPhysicalPlan;
|
||||
class ObSqlExpression;
|
||||
struct ExtBound {
|
||||
OB_UNIS_VERSION_V(1);
|
||||
|
||||
public:
|
||||
ExtBound() : my_phy_plan_(NULL), is_preceding_(false), is_unbounded_(false), is_nmb_literal_(false), sql_expr_(NULL)
|
||||
{
|
||||
MEMSET(sql_exprs_, 0, sizeof(ObSqlExpression*) * BOUND_EXPR_MAX);
|
||||
}
|
||||
TO_STRING_EMPTY();
|
||||
ObPhysicalPlan* my_phy_plan_;
|
||||
bool is_preceding_;
|
||||
bool is_unbounded_;
|
||||
bool is_nmb_literal_;
|
||||
ObSqlExpression* sql_expr_;
|
||||
ObSqlExpression* sql_exprs_[BOUND_EXPR_MAX];
|
||||
};
|
||||
struct FuncInfo {
|
||||
OB_UNIS_VERSION_V(1);
|
||||
|
||||
public:
|
||||
FuncInfo()
|
||||
: my_phy_plan_(NULL),
|
||||
func_type_(T_MAX),
|
||||
aggr_column_(NULL),
|
||||
is_distinct_(false),
|
||||
is_ignore_null_(false),
|
||||
is_from_first_(false),
|
||||
win_type_(WINDOW_MAX),
|
||||
result_index_(-1)
|
||||
{}
|
||||
|
||||
virtual ~FuncInfo()
|
||||
{}
|
||||
|
||||
inline int set_allocator(common::ObIAllocator* alloc)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
params_.set_allocator(alloc);
|
||||
partition_cols_.set_allocator(alloc);
|
||||
sort_cols_.set_allocator(alloc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int init(int64_t params_cnt, int64_t cols_cnt, int64_t sort_cnt)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
if (params_cnt < 0 || cols_cnt < 0 || sort_cnt < 0) {
|
||||
ret = common::OB_INVALID_ARGUMENT;
|
||||
SQL_ENG_LOG(WARN, "invalid cnt", K(params_cnt), K(cols_cnt), K(sort_cnt));
|
||||
} else if (params_cnt > 0 && OB_FAIL(params_.init(params_cnt))) {
|
||||
SQL_ENG_LOG(WARN, "fail to init array", K(ret), K(params_cnt));
|
||||
} else if (cols_cnt > 0 && OB_FAIL(partition_cols_.init(cols_cnt))) {
|
||||
SQL_ENG_LOG(WARN, "fail to init array", K(ret), K(cols_cnt));
|
||||
} else if (sort_cnt > 0 && OB_FAIL(sort_cols_.init(sort_cnt))) {
|
||||
SQL_ENG_LOG(WARN, "fail to init array", K(ret), K(sort_cnt));
|
||||
} else { /* do nothing. */
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
TO_STRING_KV(K_(func_type), K_(win_type), K_(is_distinct), K_(is_ignore_null), K_(upper), K_(lower), K_(result_index),
|
||||
K_(partition_cols), K_(sort_cols));
|
||||
ObPhysicalPlan* my_phy_plan_;
|
||||
ObItemType func_type_;
|
||||
ObAggregateExpression* aggr_column_;
|
||||
bool is_distinct_;
|
||||
bool is_ignore_null_;
|
||||
bool is_from_first_;
|
||||
common::ObFixedArray<ObSqlExpression*, common::ObIAllocator> params_;
|
||||
WindowType win_type_;
|
||||
ExtBound upper_;
|
||||
ExtBound lower_;
|
||||
int64_t result_index_;
|
||||
common::ObFixedArray<common::ObColumnInfo, common::ObIAllocator> partition_cols_;
|
||||
common::ObFixedArray<ObSortColumn, common::ObIAllocator> sort_cols_;
|
||||
};
|
||||
|
||||
class ObWindowFunction : public ObSingleChildPhyOperator {
|
||||
OB_UNIS_VERSION_V(1);
|
||||
|
||||
private:
|
||||
struct WinFrame {
|
||||
WinFrame(const int64_t head = -1, const int64_t tail = -1) : head_(head), tail_(tail)
|
||||
{}
|
||||
int64_t head_;
|
||||
int64_t tail_;
|
||||
TO_STRING_KV(K(head_), K(tail_));
|
||||
};
|
||||
|
||||
class IGetRow {
|
||||
public:
|
||||
inline int at(const int64_t row_idx, const common::ObNewRow*& row)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
row = NULL;
|
||||
if (OB_FAIL(inner_get_row(row_idx, row))) {
|
||||
row = NULL;
|
||||
SQL_ENG_LOG(ERROR, "get row failed", K(row_idx), K(ret));
|
||||
} else if (OB_ISNULL(row)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_ENG_LOG(ERROR, "get row failed", K(row_idx), K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int inner_get_row(const int64_t row_idx, const common::ObNewRow*& row) = 0;
|
||||
};
|
||||
|
||||
class RowReader;
|
||||
class RowsWrapper : public IGetRow {
|
||||
friend class RowReader;
|
||||
|
||||
public:
|
||||
RowsWrapper() : rows_buf_(NULL /*allocator*/, true /*keep_projector*/), begin_idx_(0), row_cnt_(0)
|
||||
{}
|
||||
inline int add_row(const common::ObNewRow& row)
|
||||
{
|
||||
row_cnt_++;
|
||||
return rows_buf_.add_row(row);
|
||||
}
|
||||
inline int64_t count() const
|
||||
{
|
||||
return row_cnt_;
|
||||
}
|
||||
inline int reset_buf(const uint64_t tenant_id)
|
||||
{
|
||||
begin_idx_ = row_cnt_;
|
||||
rows_buf_.reset();
|
||||
const int64_t mem_limit = 0;
|
||||
const int64_t mem_ctx_id = common::ObCtxIds::WORK_AREA;
|
||||
const char* label = common::ObModIds::OB_SQL_WINDOW_ROW_STORE;
|
||||
return rows_buf_.init(mem_limit, tenant_id, mem_ctx_id, label);
|
||||
}
|
||||
inline int reset(const uint64_t tenant_id)
|
||||
{
|
||||
begin_idx_ = 0;
|
||||
row_cnt_ = 0;
|
||||
return reset_buf(tenant_id);
|
||||
}
|
||||
TO_STRING_KV(K_(begin_idx), K_(row_cnt));
|
||||
|
||||
private:
|
||||
virtual int inner_get_row(const int64_t row_idx, const common::ObNewRow*& row)
|
||||
{
|
||||
return rows_buf_.get_row(row_idx - begin_idx_, row);
|
||||
}
|
||||
|
||||
private:
|
||||
ObRARowStore rows_buf_;
|
||||
int64_t begin_idx_;
|
||||
int64_t row_cnt_;
|
||||
};
|
||||
|
||||
class RowReader : public IGetRow {
|
||||
public:
|
||||
RowReader(RowsWrapper& rw) : rw_(rw), reader_(rw.rows_buf_)
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual int inner_get_row(const int64_t row_idx, const common::ObNewRow*& row)
|
||||
{
|
||||
return reader_.get_row(row_idx - rw_.begin_idx_, row);
|
||||
}
|
||||
|
||||
private:
|
||||
RowsWrapper& rw_;
|
||||
ObRARowStore::Reader reader_;
|
||||
};
|
||||
|
||||
class ObWindowFunctionCtx;
|
||||
struct FuncCtx {
|
||||
FuncCtx() : func_info_(NULL), w_ctx_(NULL), part_first_row_(0), part_iter_end_(false)
|
||||
{}
|
||||
// assign once
|
||||
FuncInfo* func_info_;
|
||||
ObWindowFunctionCtx* w_ctx_;
|
||||
|
||||
// init them when invoke input_first_row
|
||||
int64_t part_first_row_;
|
||||
bool part_iter_end_;
|
||||
RowsWrapper rw_;
|
||||
TO_STRING_KV(KP(this), K(*func_info_), K_(part_first_row), K_(part_iter_end), K_(rw));
|
||||
};
|
||||
|
||||
class BaseFunc : public common::ObDLinkBase<BaseFunc> {
|
||||
public:
|
||||
virtual ~BaseFunc()
|
||||
{}
|
||||
WinFrame last_valid_frame_;
|
||||
FuncCtx* func_ctx_;
|
||||
void reset_for_restart()
|
||||
{
|
||||
last_valid_frame_.head_ = last_valid_frame_.tail_ = -1;
|
||||
reset_for_restart_self();
|
||||
}
|
||||
virtual bool is_agg() const = 0;
|
||||
virtual int init_all_first()
|
||||
{
|
||||
return common::OB_SUCCESS;
|
||||
}
|
||||
TO_STRING_EMPTY();
|
||||
|
||||
protected:
|
||||
virtual void reset_for_restart_self()
|
||||
{}
|
||||
};
|
||||
|
||||
class AggFunc : public BaseFunc {
|
||||
public:
|
||||
virtual ~AggFunc();
|
||||
int trans(const common::ObNewRow& row)
|
||||
{
|
||||
return trans_self(row);
|
||||
}
|
||||
virtual bool can_inv() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int inv_trans(const common::ObNewRow& row)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
if (!can_inv()) {
|
||||
ret = common::OB_NOT_SUPPORTED;
|
||||
} else {
|
||||
ret = inv_trans_self(row);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
virtual int final(common::ObObj& val);
|
||||
virtual bool is_agg() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual int init_all_first();
|
||||
TO_STRING_EMPTY();
|
||||
|
||||
protected:
|
||||
virtual int trans_self(const common::ObNewRow& row);
|
||||
virtual int inv_trans_self(const common::ObNewRow& row)
|
||||
{
|
||||
UNUSED(row);
|
||||
int ret = common::OB_SUCCESS;
|
||||
ret = common::OB_NOT_SUPPORTED;
|
||||
return ret;
|
||||
}
|
||||
virtual void reset_for_restart_self();
|
||||
|
||||
private:
|
||||
bool prepare_;
|
||||
ObAggregateFunction aggr_func_;
|
||||
ObAggrExprList aggr_columns_;
|
||||
int64_t result_index_;
|
||||
common::ObObj* result_;
|
||||
common::ObObj result_buf_;
|
||||
};
|
||||
|
||||
class NonAggFunc : public BaseFunc {
|
||||
public:
|
||||
virtual int eval(RowReader& assist_reader, const int64_t row_idx, const common::ObNewRow& row,
|
||||
const WinFrame& frame, common::ObObj& val) = 0;
|
||||
virtual bool is_agg() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
TO_STRING_EMPTY();
|
||||
};
|
||||
|
||||
class NonAggFuncRowNumber : public NonAggFunc {
|
||||
public:
|
||||
virtual int eval(RowReader& assist_reader, const int64_t row_idx, const common::ObNewRow& row,
|
||||
const WinFrame& frame, common::ObObj& val);
|
||||
virtual void reset_for_restart_self()
|
||||
{}
|
||||
};
|
||||
|
||||
class NonAggFuncNtile : public NonAggFunc {
|
||||
public:
|
||||
virtual int eval(RowReader& assist_reader, const int64_t row_idx, const common::ObNewRow& row,
|
||||
const WinFrame& frame, common::ObObj& val);
|
||||
virtual void reset_for_restart_self()
|
||||
{}
|
||||
};
|
||||
|
||||
class NonAggFuncNthValue : public NonAggFunc {
|
||||
public:
|
||||
virtual int eval(RowReader& assist_reader, const int64_t row_idx, const common::ObNewRow& row,
|
||||
const WinFrame& frame, common::ObObj& val);
|
||||
virtual void reset_for_restart_self()
|
||||
{}
|
||||
};
|
||||
|
||||
class NonAggFuncLeadOrLag : public NonAggFunc {
|
||||
public:
|
||||
virtual int eval(RowReader& assist_reader, const int64_t row_idx, const common::ObNewRow& row,
|
||||
const WinFrame& frame, common::ObObj& val);
|
||||
virtual void reset_for_restart_self();
|
||||
};
|
||||
|
||||
class NonAggFuncRankLike : public NonAggFunc {
|
||||
public:
|
||||
virtual int eval(RowReader& assist_reader, const int64_t row_idx, const common::ObNewRow& row,
|
||||
const WinFrame& frame, common::ObObj& val);
|
||||
virtual void reset_for_restart_self();
|
||||
int64_t rank_of_prev_row_;
|
||||
};
|
||||
|
||||
class NonAggFuncCumeDist : public NonAggFunc {
|
||||
public:
|
||||
virtual int eval(RowReader& assist_reader, const int64_t row_idx, const common::ObNewRow& row,
|
||||
const WinFrame& frame, common::ObObj& val);
|
||||
virtual void reset_for_restart_self()
|
||||
{}
|
||||
};
|
||||
|
||||
class Utils {
|
||||
public:
|
||||
static int copy_new_row(common::ObIAllocator& allocator, const common::ObNewRow& src, common::ObNewRow*& dst);
|
||||
static int clone_cell(common::ObIAllocator& allocator, const common::ObObj& cell, common::ObObj& cell_clone);
|
||||
static int convert_stored_row(const common::ObNewRow& stored_row, common::ObNewRow& row);
|
||||
static int check_same_partition(const common::ObIArray<common::ObColumnInfo>& partition_cols,
|
||||
const common::ObNewRow& row1, const common::ObNewRow& row2, bool& is_same);
|
||||
static bool need_restart_agg(const AggFunc& agg_func, const WinFrame& last_valid_frame, const WinFrame& new_frame);
|
||||
static bool valid_frame(const WinFrame& part_frame, const WinFrame& frame);
|
||||
static bool same_frame(const WinFrame& left, const WinFrame& right);
|
||||
static void prune_frame(const WinFrame& part_frame, WinFrame& frame);
|
||||
static int invoke_agg(AggFunc& agg_func, const bool use_trans, const common::ObNewRow& row);
|
||||
};
|
||||
|
||||
class FuncAllocer {
|
||||
public:
|
||||
template <class FuncType>
|
||||
int alloc(BaseFunc*& return_func);
|
||||
common::ObIAllocator* local_allocator_;
|
||||
};
|
||||
|
||||
class ObWindowFunctionCtx : public ObPhyOperatorCtx {
|
||||
friend class ObWindowFunction;
|
||||
typedef common::ObDList<BaseFunc> BaseFuncList;
|
||||
|
||||
public:
|
||||
explicit ObWindowFunctionCtx(ObExecContext& ctx);
|
||||
virtual ~ObWindowFunctionCtx()
|
||||
{}
|
||||
|
||||
virtual void destroy()
|
||||
{
|
||||
rw_.~RowsWrapper();
|
||||
func_list_.~BaseFuncList();
|
||||
local_allocator_.~ObArenaAllocator();
|
||||
}
|
||||
int init();
|
||||
void reset_for_next_part()
|
||||
{
|
||||
last_output_row_ = -1;
|
||||
}
|
||||
void reset()
|
||||
{
|
||||
next_part_first_row_ = NULL;
|
||||
op_ = NULL;
|
||||
all_first_ = true;
|
||||
}
|
||||
int update_next_part_first_row(const common::ObNewRow& row);
|
||||
int get_next_row(const common::ObNewRow*& row);
|
||||
int get_pos(RowReader& assist_reader, FuncCtx* func_ctx, const int64_t row_idx, const common::ObNewRow& row,
|
||||
const bool is_rows, const bool is_upper, const bool is_preceding, const bool is_unbounded,
|
||||
const bool is_nmb_literal, ObSqlExpression* sql_expr, ObSqlExpression** sql_exprs, int64_t& pos,
|
||||
bool& got_null_val);
|
||||
int input_one_row(FuncCtx* func_ctx);
|
||||
int input_first_row();
|
||||
int compute(RowReader& assist_reader, BaseFunc* func, const int64_t row_idx, common::ObObj& val);
|
||||
|
||||
private:
|
||||
int parallel_winbuf_process();
|
||||
int get_whole_msg(bool is_end, ObWinbufWholeMsg& whole, const ObNewRow* res_row = NULL);
|
||||
|
||||
private:
|
||||
RowsWrapper rw_;
|
||||
BaseFuncList func_list_;
|
||||
common::ObArenaAllocator local_allocator_;
|
||||
common::ObNewRow* next_part_first_row_;
|
||||
int64_t last_output_row_;
|
||||
// In sql syntax, next_output_row and upper and lower bounds can be a combination of any positional relationship,
|
||||
// such as
|
||||
/*
|
||||
a.
|
||||
next_output_row
|
||||
|
|
||||
upper
|
||||
|
|
||||
lower
|
||||
b.
|
||||
upper
|
||||
|
|
||||
next_output_row
|
||||
|
|
||||
lower
|
||||
c.
|
||||
upper
|
||||
|
|
||||
lower
|
||||
|
|
||||
next_output_row
|
||||
|
||||
In addition to the above three, the positional relationship between upper and lower can also
|
||||
be reversed, with more combinations
|
||||
|
||||
*/
|
||||
|
||||
ObWindowFunction* op_;
|
||||
bool all_first_;
|
||||
bool rescan_;
|
||||
bool finish_parallel_;
|
||||
};
|
||||
|
||||
public:
|
||||
explicit ObWindowFunction(common::ObIAllocator& alloc);
|
||||
virtual ~ObWindowFunction();
|
||||
|
||||
virtual void reset();
|
||||
virtual void reuse();
|
||||
virtual int rescan(ObExecContext& ctx) const;
|
||||
virtual int register_to_datahub(ObExecContext& ctx) const override;
|
||||
inline int init(int64_t func_info_cnt)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
ret = init_array_size<>(func_infos_, func_info_cnt);
|
||||
return ret;
|
||||
}
|
||||
inline int add_func_info(const FuncInfo& func_info)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
ret = func_infos_.push_back(func_info);
|
||||
return ret;
|
||||
}
|
||||
void set_parallel(bool is_parallel)
|
||||
{
|
||||
is_parallel_ = is_parallel;
|
||||
}
|
||||
static int get_param_int_value(ObExprCtx& expr_ctx, const ObObj& tmp_obj, int64_t& value);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief init operator context, will create a physical operator context (and a current row space)
|
||||
* @param ctx[in], execute context
|
||||
* @return if success, return OB_SUCCESS, otherwise, return errno
|
||||
*/
|
||||
virtual int init_op_ctx(ObExecContext& ctx) const;
|
||||
/**
|
||||
* @brief: called by get_next_row(), get a row from the child operator or row_store
|
||||
* @param: ctx[in], execute context
|
||||
* @param: row[out], ObSqlRow an obj array and row_size
|
||||
*/
|
||||
virtual int inner_get_next_row(ObExecContext& ctx, const common::ObNewRow*& row) const;
|
||||
/**
|
||||
* @brief open operator, not including children operators.
|
||||
* called by open.
|
||||
* Every op should implement this method.
|
||||
*/
|
||||
virtual int inner_open(ObExecContext& ctx) const;
|
||||
/**
|
||||
* @brief close operator, not including children operators.
|
||||
* Every op should implement this method.
|
||||
*/
|
||||
virtual int inner_close(ObExecContext& ctx) const;
|
||||
virtual int64_t to_string_kv(char* buf, const int64_t buf_len) const;
|
||||
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObWindowFunction);
|
||||
|
||||
private:
|
||||
common::ObFixedArray<FuncInfo, common::ObIAllocator> func_infos_;
|
||||
bool is_parallel_;
|
||||
};
|
||||
} // end namespace sql
|
||||
} // end namespace oceanbase
|
||||
|
||||
#endif /* _OB_WINDOW_FUNCTION_H */
|
||||
1656
src/sql/engine/window_function/ob_window_function_op.cpp
Normal file
1656
src/sql/engine/window_function/ob_window_function_op.cpp
Normal file
File diff suppressed because it is too large
Load Diff
509
src/sql/engine/window_function/ob_window_function_op.h
Normal file
509
src/sql/engine/window_function/ob_window_function_op.h
Normal file
@ -0,0 +1,509 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#ifndef _OB_WINDOW_FUNCTION_OP_H
|
||||
#define _OB_WINDOW_FUNCTION_OP_H 1
|
||||
|
||||
#include "lib/container/ob_array.h"
|
||||
#include "lib/container/ob_fixed_array.h"
|
||||
#include "sql/parser/ob_item_type.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr.h"
|
||||
#include "sql/engine/basic/ob_ra_datum_store.h"
|
||||
#include "sql/engine/ob_single_child_phy_operator.h"
|
||||
#include "sql/engine/aggregate/ob_aggregate_processor.h"
|
||||
#include "sql/engine/ob_operator.h"
|
||||
#include "sql/engine/px/datahub/ob_dh_msg.h"
|
||||
#include "sql/engine/px/datahub/components/ob_dh_winbuf.h"
|
||||
#include "sql/engine/basic/ob_chunk_datum_store.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace sql {
|
||||
struct WinFuncInfo {
|
||||
OB_UNIS_VERSION_V(1);
|
||||
|
||||
public:
|
||||
struct ExtBound {
|
||||
OB_UNIS_VERSION_V(1);
|
||||
|
||||
public:
|
||||
ExtBound()
|
||||
: is_preceding_(false),
|
||||
is_unbounded_(false),
|
||||
is_nmb_literal_(false),
|
||||
between_value_expr_(NULL),
|
||||
range_bound_expr_(NULL)
|
||||
{}
|
||||
TO_STRING_KV(
|
||||
K_(is_preceding), K_(is_unbounded), K_(is_nmb_literal), KPC_(between_value_expr), KPC_(range_bound_expr));
|
||||
|
||||
bool is_preceding_;
|
||||
bool is_unbounded_;
|
||||
bool is_nmb_literal_; // only support is_nmb_literal now
|
||||
ObExpr* between_value_expr_; // when row/range between a preceding and b following, store a or b
|
||||
ObExpr* range_bound_expr_; // when order by c1 range between a preceding and b following, store (c1 - a) or (c1 +
|
||||
// b)
|
||||
};
|
||||
|
||||
public:
|
||||
WinFuncInfo() : win_type_(WINDOW_MAX), func_type_(T_MAX), is_ignore_null_(false), is_from_first_(false), expr_(NULL)
|
||||
{}
|
||||
|
||||
virtual ~WinFuncInfo()
|
||||
{}
|
||||
|
||||
inline void set_allocator(common::ObIAllocator* alloc)
|
||||
{
|
||||
aggr_info_.set_allocator(alloc);
|
||||
param_exprs_.set_allocator(alloc);
|
||||
partition_exprs_.set_allocator(alloc);
|
||||
sort_exprs_.set_allocator(alloc);
|
||||
sort_collations_.set_allocator(alloc);
|
||||
sort_cmp_funcs_.set_allocator(alloc);
|
||||
}
|
||||
|
||||
inline int init(int64_t params_cnt, int64_t cols_cnt, int64_t sort_cnt)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
if (OB_UNLIKELY(params_cnt < 0 || cols_cnt < 0 || sort_cnt < 0)) {
|
||||
ret = common::OB_INVALID_ARGUMENT;
|
||||
SQL_ENG_LOG(WARN, "invalid cnt", K(params_cnt), K(cols_cnt), K(sort_cnt));
|
||||
} else if (params_cnt > 0 && OB_FAIL(param_exprs_.init(params_cnt))) {
|
||||
SQL_ENG_LOG(WARN, "fail to init array", K(ret), K(params_cnt));
|
||||
} else if (cols_cnt > 0 && OB_FAIL(partition_exprs_.init(cols_cnt))) {
|
||||
SQL_ENG_LOG(WARN, "fail to init array", K(ret), K(cols_cnt));
|
||||
} else if (sort_cnt > 0 && (OB_FAIL(sort_exprs_.init(sort_cnt)))) {
|
||||
SQL_ENG_LOG(WARN, "fail to init array", K(ret), K(sort_cnt));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
TO_STRING_KV(K_(win_type), K_(func_type), K_(is_ignore_null), K_(is_from_first), KPC_(expr), K_(aggr_info), K_(upper),
|
||||
K_(lower), K_(param_exprs), K_(partition_exprs), K_(sort_exprs), K_(sort_collations), K_(sort_cmp_funcs));
|
||||
WindowType win_type_;
|
||||
ObItemType func_type_;
|
||||
bool is_ignore_null_;
|
||||
bool is_from_first_;
|
||||
|
||||
ObExpr* expr_; // same as aggr_info_.expr_
|
||||
ObAggrInfo aggr_info_;
|
||||
ExtBound upper_;
|
||||
ExtBound lower_;
|
||||
|
||||
ExprFixedArray param_exprs_;
|
||||
ExprFixedArray partition_exprs_;
|
||||
|
||||
ExprFixedArray sort_exprs_;
|
||||
ObSortCollations sort_collations_;
|
||||
ObSortFuncs sort_cmp_funcs_;
|
||||
};
|
||||
|
||||
typedef common::ObFixedArray<WinFuncInfo, common::ObIAllocator> WFInfoFixedArray;
|
||||
|
||||
class ObWindowFunctionSpec : public ObOpSpec {
|
||||
public:
|
||||
OB_UNIS_VERSION_V(1);
|
||||
|
||||
public:
|
||||
ObWindowFunctionSpec(common::ObIAllocator& alloc, const ObPhyOperatorType type)
|
||||
: ObOpSpec(alloc, type), wf_infos_(alloc), all_expr_(alloc), is_parallel_(false)
|
||||
{}
|
||||
DECLARE_VIRTUAL_TO_STRING;
|
||||
virtual int register_to_datahub(ObExecContext& ctx) const override;
|
||||
|
||||
public:
|
||||
WFInfoFixedArray wf_infos_;
|
||||
ExprFixedArray all_expr_; // child output + all sort expr
|
||||
bool is_parallel_;
|
||||
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObWindowFunctionSpec);
|
||||
};
|
||||
|
||||
class ObWindowFunctionOp : public ObOperator {
|
||||
public:
|
||||
struct Frame {
|
||||
Frame(const int64_t head = -1, const int64_t tail = -1) : head_(head), tail_(tail)
|
||||
{}
|
||||
static bool valid_frame(const Frame& part_frame, const Frame& frame);
|
||||
static bool same_frame(const Frame& left, const Frame& right);
|
||||
static void prune_frame(const Frame& part_frame, Frame& frame);
|
||||
static bool need_restart_aggr(const bool can_inv, const Frame& last_valid_frame, const Frame& new_frame);
|
||||
TO_STRING_KV(K(head_), K(tail_));
|
||||
|
||||
int64_t head_;
|
||||
int64_t tail_;
|
||||
};
|
||||
|
||||
class RowsStore {
|
||||
public:
|
||||
RowsStore() : rows_buf_(NULL /*allocator*/), begin_idx_(0), row_cnt_(0)
|
||||
{}
|
||||
~RowsStore()
|
||||
{
|
||||
destory();
|
||||
}
|
||||
void destory()
|
||||
{
|
||||
rows_buf_.reset();
|
||||
}
|
||||
inline int add_row(
|
||||
const common::ObIArray<ObExpr*>& exprs, ObEvalCtx* ctx, ObRADatumStore::StoredRow** stored_row = nullptr)
|
||||
{
|
||||
int ret = rows_buf_.add_row(exprs, ctx, stored_row);
|
||||
++row_cnt_;
|
||||
SQL_ENG_LOG(DEBUG, "add_row", K_(row_cnt), K(ret));
|
||||
return ret;
|
||||
}
|
||||
inline int add_row(
|
||||
const common::ObIArray<common::ObDatum>& datums, ObRADatumStore::StoredRow** stored_row = nullptr)
|
||||
{
|
||||
int ret = rows_buf_.add_row(datums, stored_row);
|
||||
++row_cnt_;
|
||||
SQL_ENG_LOG(DEBUG, "add_row", K_(row_cnt), K(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int64_t count() const
|
||||
{
|
||||
return row_cnt_;
|
||||
}
|
||||
inline int reset_buf(const uint64_t tenant_id)
|
||||
{
|
||||
// row_cnt_ no need reset
|
||||
begin_idx_ = row_cnt_;
|
||||
rows_buf_.reset();
|
||||
const int64_t mem_limit = 0;
|
||||
const int64_t mem_ctx_id = common::ObCtxIds::WORK_AREA;
|
||||
const char* label = common::ObModIds::OB_SQL_WINDOW_ROW_STORE;
|
||||
return rows_buf_.init(mem_limit, tenant_id, mem_ctx_id, label);
|
||||
}
|
||||
inline int reset(const uint64_t tenant_id)
|
||||
{
|
||||
begin_idx_ = 0;
|
||||
row_cnt_ = 0;
|
||||
rows_buf_.reset();
|
||||
return reset_buf(tenant_id);
|
||||
}
|
||||
inline int get_row(const int64_t row_idx, const ObRADatumStore::StoredRow*& sr)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
if (OB_FAIL(rows_buf_.get_row(row_idx - begin_idx_, sr))) {
|
||||
sr = NULL;
|
||||
SQL_ENG_LOG(WARN, "get row failed", K(row_idx), K(begin_idx_), K(ret));
|
||||
} else if (OB_ISNULL(sr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_ENG_LOG(WARN, "get row failed", K(row_idx), K(ret));
|
||||
} else {
|
||||
SQL_ENG_LOG(DEBUG, "get row", K(row_idx), KPC(sr));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
TO_STRING_KV(K_(begin_idx), K_(row_cnt), K_(rows_buf));
|
||||
|
||||
public:
|
||||
ObRADatumStore rows_buf_;
|
||||
int64_t begin_idx_;
|
||||
int64_t row_cnt_;
|
||||
};
|
||||
|
||||
class RowsReader {
|
||||
public:
|
||||
RowsReader(RowsStore& rows_store) : rows_store_(rows_store), reader_(rows_store.rows_buf_)
|
||||
{}
|
||||
inline int get_row(const int64_t row_idx, const ObRADatumStore::StoredRow*& sr)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
if (OB_FAIL(reader_.get_row(row_idx - rows_store_.begin_idx_, sr))) {
|
||||
sr = NULL;
|
||||
SQL_ENG_LOG(WARN, "get row failed", K(row_idx), K(ret));
|
||||
} else if (OB_ISNULL(sr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_ENG_LOG(WARN, "get row failed", K(row_idx), K(ret));
|
||||
} else {
|
||||
SQL_ENG_LOG(DEBUG, "get row", K(row_idx), KPC(sr));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
RowsStore& rows_store_;
|
||||
ObRADatumStore::Reader reader_;
|
||||
};
|
||||
|
||||
class WinFuncCell : public common::ObDLinkBase<WinFuncCell> {
|
||||
public:
|
||||
WinFuncCell(WinFuncInfo& wf_info, ObWindowFunctionOp& op)
|
||||
: wf_info_(wf_info),
|
||||
op_(op),
|
||||
wf_idx_(0),
|
||||
part_first_row_idx_(0),
|
||||
part_values_(op.local_allocator_),
|
||||
last_valid_frame_()
|
||||
{}
|
||||
virtual ~WinFuncCell()
|
||||
{
|
||||
part_rows_store_.destory();
|
||||
}
|
||||
void reset_for_restart()
|
||||
{
|
||||
last_valid_frame_.head_ = last_valid_frame_.tail_ = -1;
|
||||
reset_for_restart_self();
|
||||
}
|
||||
virtual bool is_aggr() const = 0;
|
||||
VIRTUAL_TO_STRING_KV(K_(wf_idx), K_(wf_info), K_(part_first_row_idx), K_(part_rows_store), K_(last_valid_frame));
|
||||
|
||||
protected:
|
||||
virtual void reset_for_restart_self()
|
||||
{}
|
||||
|
||||
public:
|
||||
WinFuncInfo& wf_info_;
|
||||
ObWindowFunctionOp& op_;
|
||||
|
||||
int64_t wf_idx_;
|
||||
int64_t part_first_row_idx_;
|
||||
ObChunkDatumStore::LastStoredRow<> part_values_;
|
||||
RowsStore part_rows_store_;
|
||||
|
||||
Frame last_valid_frame_;
|
||||
};
|
||||
|
||||
class AggrCell : public WinFuncCell {
|
||||
public:
|
||||
AggrCell(WinFuncInfo& wf_info, ObWindowFunctionOp& op, ObIArray<ObAggrInfo>& aggr_infos)
|
||||
: WinFuncCell(wf_info, op),
|
||||
finish_prepared_(false),
|
||||
aggr_processor_(op_.eval_ctx_, aggr_infos),
|
||||
result_(),
|
||||
got_result_(false)
|
||||
{}
|
||||
virtual ~AggrCell()
|
||||
{
|
||||
aggr_processor_.destroy();
|
||||
}
|
||||
int trans(const ObRADatumStore::StoredRow& row)
|
||||
{
|
||||
return trans_self(row);
|
||||
}
|
||||
virtual bool can_inv() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int inv_trans(const ObRADatumStore::StoredRow& row)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
if (!can_inv()) {
|
||||
ret = common::OB_NOT_SUPPORTED;
|
||||
} else {
|
||||
ret = inv_trans_self(row);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
int invoke_aggr(const bool use_trans, const ObRADatumStore::StoredRow& row)
|
||||
{
|
||||
return use_trans ? trans(row) : inv_trans(row);
|
||||
}
|
||||
|
||||
virtual int final(common::ObDatum& val);
|
||||
virtual bool is_aggr() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
DECLARE_VIRTUAL_TO_STRING;
|
||||
|
||||
protected:
|
||||
virtual int trans_self(const ObRADatumStore::StoredRow& row);
|
||||
virtual int inv_trans_self(const ObRADatumStore::StoredRow& row)
|
||||
{
|
||||
UNUSED(row);
|
||||
int ret = common::OB_SUCCESS;
|
||||
ret = common::OB_NOT_SUPPORTED;
|
||||
return ret;
|
||||
}
|
||||
virtual void reset_for_restart_self() override
|
||||
{
|
||||
finish_prepared_ = false;
|
||||
aggr_processor_.reuse();
|
||||
result_.reset();
|
||||
got_result_ = false;
|
||||
}
|
||||
|
||||
public:
|
||||
bool finish_prepared_;
|
||||
ObAggregateProcessor aggr_processor_;
|
||||
ObDatum result_;
|
||||
bool got_result_;
|
||||
};
|
||||
|
||||
class NonAggrCell : public WinFuncCell {
|
||||
public:
|
||||
NonAggrCell(WinFuncInfo& wf_info, ObWindowFunctionOp& op) : WinFuncCell(wf_info, op)
|
||||
{}
|
||||
virtual int eval(RowsReader& assist_reader, const int64_t row_idx, const ObRADatumStore::StoredRow& row,
|
||||
const Frame& frame, common::ObDatum& val) = 0;
|
||||
virtual bool is_aggr() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class NonAggrCellRowNumber : public NonAggrCell {
|
||||
public:
|
||||
NonAggrCellRowNumber(WinFuncInfo& wf_info, ObWindowFunctionOp& op) : NonAggrCell(wf_info, op)
|
||||
{}
|
||||
virtual int eval(RowsReader& assist_reader, const int64_t row_idx, const ObRADatumStore::StoredRow& row,
|
||||
const Frame& frame, common::ObDatum& val);
|
||||
};
|
||||
|
||||
class NonAggrCellNtile : public NonAggrCell {
|
||||
public:
|
||||
NonAggrCellNtile(WinFuncInfo& wf_info, ObWindowFunctionOp& op) : NonAggrCell(wf_info, op)
|
||||
{}
|
||||
virtual int eval(RowsReader& assist_reader, const int64_t row_idx, const ObRADatumStore::StoredRow& row,
|
||||
const Frame& frame, common::ObDatum& val);
|
||||
};
|
||||
|
||||
class NonAggrCellNthValue : public NonAggrCell {
|
||||
public:
|
||||
NonAggrCellNthValue(WinFuncInfo& wf_info, ObWindowFunctionOp& op) : NonAggrCell(wf_info, op)
|
||||
{}
|
||||
virtual int eval(RowsReader& assist_reader, const int64_t row_idx, const ObRADatumStore::StoredRow& row,
|
||||
const Frame& frame, common::ObDatum& val);
|
||||
};
|
||||
|
||||
class NonAggrCellLeadOrLag : public NonAggrCell {
|
||||
public:
|
||||
NonAggrCellLeadOrLag(WinFuncInfo& wf_info, ObWindowFunctionOp& op) : NonAggrCell(wf_info, op)
|
||||
{}
|
||||
virtual int eval(RowsReader& assist_reader, const int64_t row_idx, const ObRADatumStore::StoredRow& row,
|
||||
const Frame& frame, common::ObDatum& val);
|
||||
};
|
||||
|
||||
class NonAggrCellRankLike : public NonAggrCell {
|
||||
public:
|
||||
NonAggrCellRankLike(WinFuncInfo& wf_info, ObWindowFunctionOp& op) : NonAggrCell(wf_info, op), rank_of_prev_row_(0)
|
||||
{}
|
||||
virtual int eval(RowsReader& assist_reader, const int64_t row_idx, const ObRADatumStore::StoredRow& row,
|
||||
const Frame& frame, common::ObDatum& val);
|
||||
virtual void reset_for_restart_self() override
|
||||
{
|
||||
rank_of_prev_row_ = 0;
|
||||
}
|
||||
DECLARE_VIRTUAL_TO_STRING;
|
||||
|
||||
int64_t rank_of_prev_row_;
|
||||
};
|
||||
|
||||
class NonAggrCellCumeDist : public NonAggrCell {
|
||||
public:
|
||||
NonAggrCellCumeDist(WinFuncInfo& wf_info, ObWindowFunctionOp& op) : NonAggrCell(wf_info, op)
|
||||
{}
|
||||
virtual int eval(RowsReader& assist_reader, const int64_t row_idx, const ObRADatumStore::StoredRow& row,
|
||||
const Frame& frame, common::ObDatum& val);
|
||||
};
|
||||
|
||||
typedef common::ObDList<WinFuncCell> WinFuncCellList;
|
||||
|
||||
class FuncAllocer {
|
||||
public:
|
||||
template <class FuncType>
|
||||
int alloc(WinFuncCell*& return_func, WinFuncInfo& wf_info, ObWindowFunctionOp& op, const int64_t tenant_id);
|
||||
common::ObIAllocator* local_allocator_;
|
||||
};
|
||||
|
||||
public:
|
||||
ObWindowFunctionOp(ObExecContext& exec_ctx, const ObOpSpec& spec, ObOpInput* input)
|
||||
: ObOperator(exec_ctx, spec, input),
|
||||
local_allocator_(),
|
||||
rows_store_(),
|
||||
wf_list_(),
|
||||
next_row_(),
|
||||
next_row_valid_(false),
|
||||
curr_row_collect_values_(local_allocator_),
|
||||
last_output_row_idx_(common::OB_INVALID_INDEX),
|
||||
finish_parallel_(false),
|
||||
child_iter_end_(false),
|
||||
iter_end_(false)
|
||||
{}
|
||||
virtual ~ObWindowFunctionOp()
|
||||
{}
|
||||
virtual int inner_open() override;
|
||||
virtual int inner_close() override;
|
||||
virtual int rescan() override;
|
||||
virtual int switch_iterator() override;
|
||||
virtual int inner_get_next_row() override;
|
||||
virtual void destroy() override;
|
||||
|
||||
protected:
|
||||
int init();
|
||||
|
||||
inline int reset_for_scan(const int64_t tenant_id)
|
||||
{
|
||||
last_output_row_idx_ = common::OB_INVALID_INDEX;
|
||||
next_row_valid_ = false;
|
||||
child_iter_end_ = false;
|
||||
return rows_store_.reset(tenant_id);
|
||||
}
|
||||
int reset_for_part_scan(const int64_t tenant_id);
|
||||
|
||||
int get_pos(RowsReader& assist_reader, WinFuncCell& func_ctx, const int64_t row_idx,
|
||||
const ObRADatumStore::StoredRow& row, const bool is_upper, int64_t& pos, bool& got_null_val);
|
||||
bool all_outputed() const
|
||||
{
|
||||
static_assert(-1 == static_cast<int64_t>(common::OB_INVALID_INDEX), "invalid index is not -1");
|
||||
return rows_store_.count() == static_cast<int64_t>(last_output_row_idx_) + 1;
|
||||
}
|
||||
int fetch_child_row();
|
||||
int input_one_row(WinFuncCell& func_ctx, bool& part_end);
|
||||
int compute(RowsReader& row_reader, WinFuncCell& wf_cell, const int64_t row_idx, common::ObDatum& val);
|
||||
int check_same_partition(
|
||||
const ExprFixedArray& other_exprs, bool& is_same_part, const ExprFixedArray* curr_exprs = NULL);
|
||||
int check_same_partition(WinFuncCell& cell, bool& same);
|
||||
int collect_result(const int64_t idx, common::ObDatum& in_datum, WinFuncCell& wf_cell);
|
||||
inline ObExprPtrIArray& get_all_expr()
|
||||
{
|
||||
return *const_cast<ExprFixedArray*>(&(MY_SPEC.all_expr_));
|
||||
}
|
||||
inline int64_t get_part_end_idx() const
|
||||
{
|
||||
return rows_store_.count() - 1;
|
||||
}
|
||||
static int get_param_int_value(
|
||||
ObExpr& expr, ObEvalCtx& eval_ctx, bool& is_null, int64_t& value, const bool need_number_type = false);
|
||||
int parallel_winbuf_process();
|
||||
int get_whole_msg(bool is_end, ObWinbufWholeMsg& whole, const ObRADatumStore::StoredRow* row = NULL);
|
||||
int copy_datum_row(const ObRADatumStore::StoredRow& row, ObWinbufPieceMsg& piece, int64_t buf_len, char* buf);
|
||||
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObWindowFunctionOp);
|
||||
|
||||
private:
|
||||
common::ObArenaAllocator local_allocator_;
|
||||
|
||||
RowsStore rows_store_;
|
||||
WinFuncCellList wf_list_;
|
||||
// shadow copy the next and restore it before get next row from child.
|
||||
ObChunkDatumStore::ShadowStoredRow<> next_row_;
|
||||
bool next_row_valid_; // TODO
|
||||
DatumFixedArray curr_row_collect_values_;
|
||||
|
||||
int64_t last_output_row_idx_;
|
||||
bool finish_parallel_;
|
||||
bool child_iter_end_;
|
||||
bool iter_end_;
|
||||
};
|
||||
} // end namespace sql
|
||||
} // end namespace oceanbase
|
||||
|
||||
#endif /* _OB_WINDOW_FUNCTION_OP_H */
|
||||
Reference in New Issue
Block a user