patch 4.0

This commit is contained in:
wangzelin.wzl
2022-10-24 10:34:53 +08:00
parent 4ad6e00ec3
commit 93a1074b0c
10533 changed files with 2588271 additions and 2299373 deletions

View File

@ -13,250 +13,32 @@
#define USING_LOG_PREFIX SQL_OPT
#include "ob_log_window_function.h"
#include "ob_opt_est_cost.h"
#include "sql/optimizer/ob_join_order.h"
#include "common/ob_smart_call.h"
using namespace oceanbase::sql;
using namespace oceanbase::common;
using namespace oceanbase::sql::log_op_def;
int ObLogWindowFunction::copy_without_child(ObLogicalOperator*& out)
int ObLogWindowFunction::get_op_exprs(ObIArray<ObRawExpr*> &all_exprs)
{
int ret = OB_SUCCESS;
out = NULL;
ObLogicalOperator* op = NULL;
ObLogWindowFunction* win_func = NULL;
if (OB_FAIL(clone(op))) {
LOG_WARN("failed to clone sort operator", K(ret));
} else if (OB_ISNULL(win_func = static_cast<ObLogWindowFunction*>(op))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("NULL ptr", K(win_func), K(ret));
} else {
for (int64_t i = 0; i < win_exprs_.count() && OB_SUCC(ret); ++i) {
ret = win_func->win_exprs_.push_back(win_exprs_.at(i));
}
if (OB_SUCC(ret)) {
out = win_func;
FOREACH_CNT_X(it, rd_sort_keys_, OB_SUCC(ret)) {
if (OB_FAIL(all_exprs.push_back(it->expr_))) {
LOG_WARN("array push back failed", K(ret));
}
}
return ret;
}
int ObLogWindowFunction::match_parallel_condition(bool& can_parallel)
{
int ret = OB_SUCCESS;
bool flag = true;
ObWinFunRawExpr* win_expr = NULL;
for (int64_t i = 0; OB_SUCC(ret) && flag && i < win_exprs_.count(); ++i) {
win_expr = win_exprs_.at(i);
switch (win_expr->get_func_type()) {
case T_FUN_COUNT:
case T_FUN_SUM:
case T_FUN_MAX:
case T_FUN_MIN: {
/*do nothing*/
break;
}
default: {
flag = false;
break;
}
}
if (flag) {
if (win_expr->get_upper().type_ != BoundType::BOUND_UNBOUNDED ||
win_expr->get_lower().type_ != BoundType::BOUND_UNBOUNDED) {
flag = false;
}
}
if (flag) {
if (win_expr->get_partition_exprs().count() > 0) {
flag = false;
}
}
}
if (OB_SUCC(ret)) {
can_parallel = flag;
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(append(all_exprs, win_exprs_))) {
LOG_WARN("failed to append exprs", K(ret));
} else if (OB_FAIL(ObLogicalOperator::get_op_exprs(all_exprs))) {
LOG_WARN("failed to get op exprs", K(ret));
} else { /*do nothing*/ }
return ret;
}
int ObLogWindowFunction::allocate_exchange_post(AllocExchContext* ctx)
{
int ret = OB_SUCCESS;
bool is_basic = false;
ObLogicalOperator* child = NULL;
if (OB_ISNULL(ctx) || OB_ISNULL(child = get_child(first_child))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ctx), K(child), K(ret));
} else if (OB_FAIL(compute_basic_sharding_info(ctx, is_basic))) {
LOG_WARN("failed to compute basic sharding info", K(ret));
} else if (is_basic) {
LOG_TRACE("is basic sharding info", K(sharding_info_));
} else if (OB_UNLIKELY(win_exprs_.empty())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("empty window exprs", K(ret));
} else {
bool sharding_compatible = false;
ObSEArray<ObRawExpr*, 4> win_part_exprs;
ObSEArray<ObRawExpr*, 4> key_exprs;
if (OB_FAIL(get_win_partition_intersect_exprs(win_exprs_, win_part_exprs))) {
LOG_WARN("failed to get win partition intersect exprs", K(ret));
} else if (OB_FAIL(prune_weak_part_exprs(*ctx, win_part_exprs, key_exprs))) {
LOG_WARN("failed to prune weak part exprs", K(ret));
} else if (OB_FAIL(check_sharding_compatible_with_reduce_expr(child->get_sharding_info(),
key_exprs,
child->get_sharding_output_equal_sets(),
sharding_compatible))) {
LOG_WARN("Failed to check sharding compatible with reduce expr", K(ret), K(*child));
} else if (sharding_compatible) {
if (OB_FAIL(sharding_info_.copy_with_part_keys(child->get_sharding_info()))) {
LOG_WARN("failed to deep copy sharding info from child", K(ret));
} else {
is_partition_wise_ = (NULL != sharding_info_.get_phy_table_location_info());
}
} else {
ObExchangeInfo exch_info;
bool can_parallel = false;
if (!win_part_exprs.empty()) {
if (OB_FAIL(exch_info.append_hash_dist_expr(win_part_exprs))) {
LOG_WARN("failed to append hash dist expr", K(ret));
} else if (OB_FAIL(sharding_info_.get_partition_keys().assign(win_part_exprs))) {
LOG_WARN("failed to assign exprs", K(ret));
} else {
exch_info.dist_method_ = ObPQDistributeMethod::HASH;
sharding_info_.set_location_type(OB_TBL_LOCATION_DISTRIBUTED);
}
} else if (OB_FAIL(match_parallel_condition(can_parallel))) {
LOG_WARN("fail to check match parallel condition", K(ret));
} else if (can_parallel) {
is_parallel_ = true;
sharding_info_.set_location_type(OB_TBL_LOCATION_DISTRIBUTED);
} else {
exch_info.dist_method_ = ObPQDistributeMethod::MAX_VALUE;
sharding_info_.set_location_type(OB_TBL_LOCATION_LOCAL);
}
if (OB_SUCC(ret)) {
if (!is_parallel_ && OB_FAIL(child->allocate_exchange(ctx, exch_info))) {
LOG_WARN("failed to allocate exchange", K(ret));
} else { /*do nothing*/
}
}
}
}
return ret;
}
int ObLogWindowFunction::allocate_expr_pre(ObAllocExprContext& ctx)
{
int ret = OB_SUCCESS;
ObSEArray<ObRawExpr*, 8> temp_exprs;
ObSEArray<ObRawExpr*, 8> win_exprs;
uint64_t producer_id = OB_INVALID_ID;
if (OB_FAIL(get_next_producer_id(get_child(first_child), producer_id))) {
LOG_WARN("failed to get next producer id", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < win_exprs_.count(); ++i) {
ObWinFunRawExpr* raw_expr = win_exprs_.at(i);
if (OB_ISNULL(raw_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(win_exprs.push_back(raw_expr))) {
LOG_WARN("failed to push back exprs", K(ret));
} else {
for (int64_t j = 0; OB_SUCC(ret) && j < raw_expr->get_param_count(); ++j) {
bool should_add = false;
ObRawExpr* param_expr = raw_expr->get_param_expr(j);
if (OB_ISNULL(param_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(check_param_expr_should_be_added(param_expr, should_add))) {
LOG_WARN("failed to check if param should be added", K(ret));
} else if (should_add && OB_FAIL(temp_exprs.push_back(param_expr))) {
LOG_WARN("failed to push back exprs", K(ret));
} else { /*do nothing*/
}
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(add_exprs_to_ctx(ctx, win_exprs))) {
LOG_WARN("failed to add exprs to ctx", K(ret));
} else if (OB_FAIL(add_exprs_to_ctx(ctx, temp_exprs, producer_id))) {
LOG_WARN("failed to add exprs to ctx", K(ret));
} else if (OB_FAIL(ObLogicalOperator::allocate_expr_pre(ctx))) {
LOG_WARN("failed to add parent need expr", K(ret));
} else { /*do nothing*/
}
}
// set producer id for aggr expr
for (int64_t i = 0; OB_SUCC(ret) && i < ctx.expr_producers_.count(); ++i) {
ExprProducer& producer = ctx.expr_producers_.at(i);
if (OB_ISNULL(producer.expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_INVALID_ID == producer.producer_id_ && producer.expr_->has_flag(IS_WINDOW_FUNC) &&
ObOptimizerUtil::find_item(win_exprs, producer.expr_)) {
producer.producer_id_ = id_;
} else { /*do nothing*/
}
}
}
return ret;
}
int ObLogWindowFunction::check_output_dep_specific(ObRawExprCheckDep& checker)
{
int ret = OB_SUCCESS;
ObSEArray<ObRawExpr*, 8> temp_exprs;
for (int64_t i = 0; OB_SUCC(ret) && i < win_exprs_.count(); ++i) {
ObWinFunRawExpr* raw_expr = win_exprs_.at(i);
if (OB_ISNULL(raw_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
for (int64_t j = 0; OB_SUCC(ret) && j < raw_expr->get_param_count(); ++j) {
if (OB_ISNULL(raw_expr->get_param_expr(j))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(temp_exprs.push_back(raw_expr->get_param_expr(j)))) {
LOG_WARN("failed to push back exprs", K(ret));
} else { /*do nothing*/
}
}
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < temp_exprs.count(); i++) {
if (OB_ISNULL(temp_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(i));
} else if (OB_FAIL(checker.check(*temp_exprs.at(i)))) {
LOG_WARN("failed to check output expr", K(ret), K(i));
} else {
}
}
return ret;
}
int ObLogWindowFunction::is_my_window_expr(const ObRawExpr* expr, bool& is_mine)
{
int ret = OB_SUCCESS;
ObSEArray<ObRawExpr*, 8> win_exprs;
for (int64_t i = 0; OB_SUCC(ret) && i < win_exprs_.count(); ++i) {
ObWinFunRawExpr* raw_expr = win_exprs_.at(i);
if (OB_ISNULL(raw_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(win_exprs.push_back(raw_expr))) {
LOG_WARN("failed to push back exprs", K(ret));
} else { /*do nothing*/
}
}
if (OB_SUCC(ret)) {
is_mine = ObOptimizerUtil::find_item(win_exprs, expr);
}
return ret;
;
}
int ObLogWindowFunction::print_my_plan_annotation(char* buf, int64_t& buf_len, int64_t& pos, ExplainType type)
int ObLogWindowFunction::print_my_plan_annotation(char *buf, int64_t &buf_len, int64_t &pos,
ExplainType type)
{
int ret = OB_SUCCESS;
if (OB_FAIL(BUF_PRINTF(", "))) {
@ -269,14 +51,14 @@ int ObLogWindowFunction::print_my_plan_annotation(char* buf, int64_t& buf_len, i
if (i != 0 && OB_FAIL(BUF_PRINTF("\n "))) {
LOG_WARN("BUF_PRINTF fails", K(ret));
}
ObWinFunRawExpr* win_expr = win_exprs_.at(i);
ObWinFunRawExpr *win_expr = win_exprs_.at(i);
EXPLAIN_PRINT_EXPR(win_expr, type);
// partition by
if (OB_SUCC(ret)) {
if (OB_FAIL(BUF_PRINTF(", "))) {
LOG_WARN("BUF_PRINTF fails", K(ret));
} else {
const ObIArray<ObRawExpr*>& partition_by = win_expr->get_partition_exprs();
const ObIArray<ObRawExpr *> &partition_by = win_expr->get_partition_exprs();
EXPLAIN_PRINT_EXPRS(partition_by, type);
}
}
@ -285,7 +67,7 @@ int ObLogWindowFunction::print_my_plan_annotation(char* buf, int64_t& buf_len, i
if (OB_FAIL(BUF_PRINTF(", "))) {
LOG_WARN("BUF_PRINTF fails", K(ret));
} else {
const ObIArray<OrderItem>& order_by = win_expr->get_order_items();
const ObIArray<OrderItem> &order_by = win_expr->get_order_items();
EXPLAIN_PRINT_SORT_ITEMS(order_by, type);
}
}
@ -295,68 +77,69 @@ int ObLogWindowFunction::print_my_plan_annotation(char* buf, int64_t& buf_len, i
LOG_WARN("BUF_PRINTF fails", K(ret));
}
if (OB_SUCC(ret)) {
const char* win_type_str = "MAX";
const char *win_type_str = "MAX";
if (WINDOW_ROWS == win_expr->get_window_type()) {
win_type_str = "window_type(ROWS), ";
} else if (WINDOW_RANGE == win_expr->get_window_type()) {
win_type_str = "window_type(RANGE), ";
}
if (OB_FAIL(BUF_PRINTF(win_type_str))) {
if (OB_FAIL(BUF_PRINTF("%s", win_type_str))) {
LOG_WARN("BUF_PRINTF fails", K(ret));
}
}
#define PRINT_BOUND(bound_name, bound) \
if (OB_SUCC(ret)) { \
if (OB_FAIL(BUF_PRINTF(#bound_name "("))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} else { \
bool print_dir = false; \
if (BOUND_UNBOUNDED == bound.type_) { \
print_dir = true; \
if (OB_FAIL(BUF_PRINTF("UNBOUNDED"))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} else if (BOUND_CURRENT_ROW == bound.type_) { \
if (OB_FAIL(BUF_PRINTF("CURRENT ROW"))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} else if (BOUND_INTERVAL == bound.type_) { \
print_dir = true; \
if (OB_FAIL(bound.interval_expr_->get_name(buf, buf_len, pos, type))) { \
LOG_WARN("print expr name failed", K(ret)); \
} else if (!bound.is_nmb_literal_) { \
int64_t date_unit_type = DATE_UNIT_MAX; \
ObConstRawExpr* con_expr = static_cast<ObConstRawExpr*>(bound.date_unit_expr_); \
if (OB_ISNULL(con_expr)) { \
ret = OB_ERR_UNEXPECTED; \
LOG_WARN("con_expr should not be NULL", K(ret)); \
} else { \
con_expr->get_value().get_int(date_unit_type); \
const static char* date_unit = ob_date_unit_type_str(static_cast<ObDateUnitType>(date_unit_type)); \
if (OB_FAIL(BUF_PRINTF(" %s", date_unit))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} \
} \
} \
if (OB_SUCC(ret) && print_dir) { \
if (bound.is_preceding_) { \
if (OB_FAIL(BUF_PRINTF(" PRECEDING"))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} else { \
if (OB_FAIL(BUF_PRINTF(" FOLLOWING"))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} \
} \
if (OB_SUCC(ret)) { \
if (OB_FAIL(BUF_PRINTF(")"))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} \
} \
}
#define PRINT_BOUND(bound_name, bound) \
if (OB_SUCC(ret)) { \
if (OB_FAIL(BUF_PRINTF(#bound_name"("))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} else { \
bool print_dir = false; \
if (BOUND_UNBOUNDED == bound.type_) { \
print_dir = true; \
if (OB_FAIL(BUF_PRINTF("UNBOUNDED"))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} else if (BOUND_CURRENT_ROW == bound.type_) { \
if (OB_FAIL(BUF_PRINTF("CURRENT ROW"))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} else if (BOUND_INTERVAL == bound.type_) { \
print_dir = true; \
if (OB_FAIL(bound.interval_expr_->get_name(buf, buf_len, pos, type))) { \
LOG_WARN("print expr name failed", K(ret)); \
} else if (!bound.is_nmb_literal_) { \
int64_t date_unit_type = DATE_UNIT_MAX; \
ObConstRawExpr *con_expr = static_cast<ObConstRawExpr*>(bound.date_unit_expr_); \
if (OB_ISNULL(con_expr)) { \
ret = OB_ERR_UNEXPECTED; \
LOG_WARN("con_expr should not be NULL", K(ret)); \
} else { \
con_expr->get_value().get_int(date_unit_type); \
const static char *date_unit = \
ob_date_unit_type_str(static_cast<ObDateUnitType>(date_unit_type)); \
if (OB_FAIL(BUF_PRINTF(" %s", date_unit))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} \
} \
} \
if (OB_SUCC(ret) && print_dir) { \
if (bound.is_preceding_) { \
if (OB_FAIL(BUF_PRINTF(" PRECEDING"))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} else { \
if (OB_FAIL(BUF_PRINTF(" FOLLOWING"))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} \
} \
if (OB_SUCC(ret)) { \
if (OB_FAIL(BUF_PRINTF(")"))) { \
LOG_WARN("BUF_PRINTF fails", K(ret)); \
} \
} \
} \
}
PRINT_BOUND(upper, win_expr->get_upper());
if (OB_FAIL(BUF_PRINTF(", "))) {
@ -370,120 +153,128 @@ int ObLogWindowFunction::print_my_plan_annotation(char* buf, int64_t& buf_len, i
return ret;
}
int ObLogWindowFunction::est_width()
{
int ret = OB_SUCCESS;
double width = 0.0;
ObLogPlan *plan = NULL;
ObSEArray<ObRawExpr*, 16> output_exprs;
if (OB_ISNULL(plan = get_plan())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid input", K(ret));
} else if (OB_FAIL(get_winfunc_output_exprs(output_exprs))) {
LOG_WARN("failed to compute winfunc output exprs", K(ret));
} else if (OB_FAIL(ObOptEstCost::estimate_width_for_exprs(get_plan()->get_basic_table_metas(),
get_plan()->get_selectivity_ctx(),
output_exprs,
width))) {
LOG_WARN("failed to estimate width for output winfunc exprs", K(ret));
} else {
set_width(width);
LOG_TRACE("est_width for winfunc", K(output_exprs), K(width));
}
return ret;
}
int ObLogWindowFunction::get_winfunc_output_exprs(ObIArray<ObRawExpr *> &output_exprs)
{
int ret = OB_SUCCESS;
ObLogPlan *plan = NULL;
ObSEArray<ObRawExpr*, 16> candi_exprs;
ObSEArray<ObRawExpr*, 16> extracted_col_aggr_winfunc_exprs;
if (OB_ISNULL(plan = get_plan())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid input", K(ret));
} else if (OB_FAIL(append_array_no_dup(candi_exprs, plan->get_select_item_exprs_for_width_est()))) {
LOG_WARN("failed to add into output exprs", K(ret));
} else if (OB_FAIL(append_array_no_dup(candi_exprs, plan->get_orderby_exprs_for_width_est()))) {
LOG_WARN("failed to add into output exprs", K(ret));
} else if (OB_FAIL(ObRawExprUtils::extract_col_aggr_winfunc_exprs(candi_exprs,
extracted_col_aggr_winfunc_exprs))) {
} else if (OB_FAIL(append_array_no_dup(output_exprs, extracted_col_aggr_winfunc_exprs))) {
LOG_WARN("failed to add into output exprs", K(ret));
} else {/*do nothing*/}
return ret;
}
int ObLogWindowFunction::est_cost()
{
int ret = OB_SUCCESS;
ObLogicalOperator* first_child = get_child(ObLogicalOperator::first_child);
double op_cost = 0.0;
// compute window for operator
if (OB_ISNULL(first_child)) {
int64_t parallel = 0;
ObLogicalOperator *first_child = NULL;
if (OB_ISNULL(get_plan()) ||
OB_ISNULL(first_child = get_child(ObLogicalOperator::first_child))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("first child is null", K(ret), K(first_child));
} else if (OB_FAIL(ObOptEstCost::cost_window_function(first_child->get_card(), op_cost))) {
} else if (OB_UNLIKELY((parallel = get_parallel()) < 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected parallel degree", K(parallel), K(ret));
} else if (OB_FAIL(ObOptEstCost::cost_window_function(first_child->get_card() / parallel,
first_child->get_width(),
win_exprs_.count(),
op_cost_,
get_plan()->get_optimizer_context().get_cost_model_type()))) {
LOG_WARN("calculate cost of window function failed", K(ret));
} else {
set_card(first_child->get_card());
set_op_cost(op_cost);
set_cost(first_child->get_cost() + op_cost);
// TODO () add widths of winexprs
set_width(first_child->get_width());
set_cost(first_child->get_cost() + op_cost_);
}
return ret;
}
int ObLogWindowFunction::re_est_cost(const ObLogicalOperator* parent, double need_row_count, bool& re_est)
int ObLogWindowFunction::re_est_cost(EstimateCostInfo &param, double &card, double &cost)
{
int ret = OB_SUCCESS;
double op_cost = op_cost_;
ObLogicalOperator* child = NULL;
UNUSED(parent);
re_est = false;
if (need_row_count >= get_card()) {
/* do nothing */
} else if (OB_ISNULL(child = get_child(first_child))) {
LOG_WARN("get child failed", K(ret), K_(card), K(need_row_count));
} else if (OB_FAIL(child->re_est_cost(this, need_row_count, re_est))) {
LOG_WARN("re-estimate cost of child failed", K(ret), K(re_est));
} else if (OB_FAIL(ObOptEstCost::cost_window_function(need_row_count, op_cost))) {
LOG_WARN("cost window function failed", K(ret));
int64_t parallel = 0;
ObLogicalOperator *child = NULL;
if (OB_ISNULL(get_plan()) ||
OB_ISNULL(child = get_child(ObLogicalOperator::first_child))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(child), K(ret));
} else if (OB_UNLIKELY((parallel = get_parallel()) < 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected parallel degree", K(parallel), K(ret));
} else {
re_est = true;
op_cost_ = op_cost;
cost_ = op_cost + child->get_cost();
set_card(need_row_count);
}
return ret;
}
int ObLogWindowFunction::transmit_op_ordering()
{
int ret = OB_SUCCESS;
reset_op_ordering();
reset_local_ordering();
ObLogicalOperator* child = get_child(first_child);
bool need_sort = false;
if (OB_ISNULL(child)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("child is null", K(ret));
} else if (OB_FAIL(check_need_sort_below_node(0, expected_ordering_, need_sort))) {
LOG_WARN("failed to check need sort", K(ret));
} else if (need_sort && OB_FAIL(allocate_sort_below(0, expected_ordering_))) {
LOG_WARN("failed to allocate implicit sort", K(ret));
} else if (OB_ISNULL(child = get_child(first_child))) { // get child again for sort and defend null value
ret = OB_ERR_UNEXPECTED;
LOG_WARN("child is null", K(ret));
} else if (OB_FAIL(set_op_ordering(child->get_op_ordering()))) {
LOG_WARN("failed to set op's ordering", K(ret));
}
return ret;
}
uint64_t ObLogWindowFunction::hash(uint64_t seed) const
{
HASH_PTR_ARRAY(win_exprs_, seed);
seed = ObLogicalOperator::hash(seed);
return seed;
}
int ObLogWindowFunction::allocate_granule_pre(AllocGIContext& ctx)
{
return pw_allocate_granule_pre(ctx);
}
int ObLogWindowFunction::allocate_granule_post(AllocGIContext& ctx)
{
return pw_allocate_granule_post(ctx);
}
int ObLogWindowFunction::inner_append_not_produced_exprs(ObRawExprUniqueSet& raw_exprs) const
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < win_exprs_.count(); ++i) {
if (win_exprs_.at(i)->get_agg_expr() != NULL) {
ObRawExpr* expr = NULL;
switch (win_exprs_.at(i)->get_agg_expr()->get_expr_type()) {
case T_FUN_GROUP_CONCAT: {
expr = win_exprs_.at(i)->get_agg_expr()->get_separator_param_expr();
OZ(raw_exprs.append(expr));
break;
}
case T_FUN_MEDIAN:
case T_FUN_GROUP_PERCENTILE_CONT: {
expr = win_exprs_.at(i)->get_agg_expr()->get_linear_inter_expr();
OZ(raw_exprs.append(expr));
break;
}
default:
break;
double child_card = child->get_card();
double child_cost = child->get_cost();
double op_cost = 0.0;
ObOptimizerContext &opt_ctx = get_plan()->get_optimizer_context();
if (is_block_op()) {
param.need_row_count_ = -1; //reset need row count
}
if (OB_FAIL(SMART_CALL(child->re_est_cost(param, child_card, child_cost)))) {
LOG_WARN("failed to re est exchange cost", K(ret));
} else if (OB_FAIL(ObOptEstCost::cost_window_function(child_card / parallel,
child->get_width(),
win_exprs_.count(),
op_cost,
opt_ctx.get_cost_model_type()))) {
LOG_WARN("calculate cost of window function failed", K(ret));
} else {
cost = child_cost + op_cost;
card = child_card;
if (param.override_) {
set_op_cost(op_cost);
set_cost(cost);
set_card(card);
}
}
}
return ret;
}
int ObLogWindowFunction::get_win_partition_intersect_exprs(
ObIArray<ObWinFunRawExpr*>& win_exprs, ObIArray<ObRawExpr*>& win_part_exprs)
int ObLogWindowFunction::allocate_granule_pre(AllocGIContext &ctx)
{
return pw_allocate_granule_pre(ctx);
}
int ObLogWindowFunction::allocate_granule_post(AllocGIContext &ctx)
{
return pw_allocate_granule_post(ctx);
}
int ObLogWindowFunction::get_win_partition_intersect_exprs(ObIArray<ObWinFunRawExpr *> &win_exprs,
ObIArray<ObRawExpr *> &win_part_exprs)
{
int ret = OB_SUCCESS;
if (win_exprs.count() > 0) {
@ -494,34 +285,117 @@ int ObLogWindowFunction::get_win_partition_intersect_exprs(
LOG_WARN("failed to append exprs", K(ret));
} else {
for (int64_t i = 1; OB_SUCC(ret) && i < win_exprs.count(); ++i) {
ObWinFunRawExpr* win_expr = win_exprs.at(i);
ObWinFunRawExpr *win_expr = win_exprs.at(i);
if (OB_ISNULL(win_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(ObOptimizerUtil::intersect_exprs(
win_part_exprs, win_expr->get_partition_exprs(), win_part_exprs))) {
} else if (OB_FAIL(ObOptimizerUtil::intersect_exprs(win_part_exprs,
win_expr->get_partition_exprs(),
win_part_exprs))) {
LOG_WARN("failed to intersect exprs", K(ret));
} else { /*do nothing*/
}
} else { /*do nothing*/ }
}
}
}
return ret;
}
int ObLogWindowFunction::compute_op_ordering()
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObLogicalOperator::compute_op_ordering())) {
LOG_WARN("failed to compute op ordering", K(ret));
} else if (!single_part_parallel_) {
is_local_order_ = (range_dist_parallel_ || is_fully_paratition_wise())
&& !get_op_ordering().empty();
}
return ret;
}
int ObLogWindowFunction::compute_sharding_info()
{
int ret = OB_SUCCESS;
if (is_single_part_parallel()) {
if (OB_ISNULL(get_plan())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
strong_sharding_ = get_plan()->get_optimizer_context().get_distributed_sharding();
}
} else if (OB_FAIL(ObLogicalOperator::compute_sharding_info())) {
LOG_WARN("failed to compute sharding info", K(ret));
}
return ret;
}
bool ObLogWindowFunction::is_block_op() const
{
bool is_block_op = true;
ObWinFunRawExpr* win_expr = NULL;
// 对于window function算子, 在没有partition by以及完整窗口情况下,
// 所有数据作为一个窗口, 认为是block算子
// 在其他情况下, 认为是非block算子
ObWinFunRawExpr *win_expr = NULL;
for (int64_t i = 0; i < win_exprs_.count(); ++i) {
if (OB_ISNULL(win_expr = win_exprs_.at(i))) {
LOG_ERROR("win expr is null");
} else if (win_expr->get_partition_exprs().count() > 0 ||
win_expr->get_upper().type_ != BoundType::BOUND_UNBOUNDED ||
win_expr->get_lower().type_ != BoundType::BOUND_UNBOUNDED) {
win_expr->get_upper().type_ != BoundType::BOUND_UNBOUNDED ||
win_expr->get_lower().type_ != BoundType::BOUND_UNBOUNDED ) {
is_block_op = false;
break;
}
}
return is_block_op;
}
int ObLogWindowFunction::print_outline(planText &plan_text)
{
int ret = OB_SUCCESS;
char *buf = plan_text.buf;
int64_t &buf_len = plan_text.buf_len;
int64_t &pos = plan_text.pos;
const ObDMLStmt *stmt = NULL;
ObString qb_name;
if (OB_ISNULL(get_plan()) || OB_ISNULL(stmt = get_plan()->get_stmt())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected NULL", K(ret), K(get_plan()), K(stmt));
} else if (USED_HINT == plan_text.outline_type_) {
auto win_dist = get_plan()->get_log_plan_hint().get_window_dist();
bool has_same_method = false;
if (NULL != win_dist && !win_dist->get_algos().empty()) {
if (is_array_equal(dist_hint_, win_dist->get_algos())) {
if (OB_FAIL(win_dist->print_hint(plan_text))) {
LOG_WARN("print hint failed", K(ret));
}
}
}
} else if (OUTLINE_DATA == plan_text.outline_type_) {
if (!dist_hint_.empty()) {
ObWindowDistHint win_dist;
if (OB_FAIL(stmt->get_qb_name(qb_name))) {
LOG_WARN("get qb name failed", K(ret));
} else if (OB_FAIL(win_dist.get_algos().assign(dist_hint_))) {
LOG_WARN("array assign failed", K(ret));
} else {
win_dist.set_qb_name(qb_name);
if (OB_FAIL(win_dist.print_hint(plan_text))) {
LOG_WARN("print hint failed", K(ret));
}
}
}
}
return ret;
}
int ObLogWindowFunction::inner_replace_generated_agg_expr(
const common::ObIArray<std::pair<ObRawExpr *, ObRawExpr*>> &to_replace_exprs)
{
int ret = OB_SUCCESS;
FOREACH_X(key, rd_sort_keys_, OB_SUCC(ret)) {
if (OB_FAIL(replace_expr_action(to_replace_exprs, key->expr_))) {
LOG_WARN("replace expr failed", K(ret));
}
}
return ret;
}